static void
end_element (GMarkupParseContext  *context,
             const gchar          *element_name,
             gpointer              user_data,
             GError              **error)
{
  ParseState *state = user_data;

  if (strcmp (element_name, "default") == 0)
    {
      state->value = g_variant_parse (state->type, state->string->str,
                                      NULL, NULL, error);
      if (state->value == NULL)
        return;

      if (state->l10n)
        {
          if (state->context)
            {
              gint len;

              /* Contextified messages are supported by prepending the
               * context, followed by '\004' to the start of the message
               * string.  We do that here to save GSettings the work
               * later on.
               *
               * Note: we are about to g_free() the context anyway...
               */
              len = strlen (state->context);
              state->context[len] = '\004';
              g_string_prepend_len (state->string, state->context, len + 1);
            }

          g_variant_builder_add (&state->key_options, "{sv}", "l10n",
                                 g_variant_new ("(ys)",
                                                state->l10n,
                                                state->string->str));
        }

      g_string_free (state->string, TRUE);
      state->string = NULL;
      g_free (state->context);
      state->context = NULL;
    }

  else if (strcmp (element_name, "key") == 0)
    {
      if (state->value == NULL)
        {
          g_set_error_literal (error,
                               G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
                               "element <default> is required in <key>\n");
          return;
        }

      if (state->min != NULL)
        {
          if (g_variant_compare (state->value, state->min) < 0 ||
              g_variant_compare (state->value, state->max) > 0)
            {
              g_set_error (error, G_MARKUP_ERROR,
                           G_MARKUP_ERROR_INVALID_CONTENT,
                           "<default> is not contained in the specified range");
              return;
            }

          state->min = state->max = NULL;
        }
      else if (state->choices != NULL)
        {
          if (!is_valid_choices (state->value, state->choices->str))
            {
              g_set_error_literal (error, G_MARKUP_ERROR,
                                   G_MARKUP_ERROR_INVALID_CONTENT,
                                   "<default> contains string not in <choices>");
              return;
            }

          state->choices = NULL;
        }

      gvdb_item_set_value (state->key, state->value);
      gvdb_item_set_options (state->key,
                             g_variant_builder_end (&state->key_options));

      state->value = NULL;
    }

  else if (strcmp (element_name, "summary") == 0 ||
           strcmp (element_name, "description") == 0)
    {
      g_string_free (state->string, TRUE);
      state->string = NULL;
    }

  else if (strcmp (element_name, "choices") == 0)
    {
      gchar *choices;

      choices = g_string_free (state->choices, FALSE);
      g_variant_builder_add (&state->key_options, "{sv}", "choices",
                             g_variant_new_byte_array (choices, -1));
      g_free (choices);
    }
}
Beispiel #2
0
static gboolean
_eventd_events_event_matches(EventdEventsEvent *self, EventdEvent *event, GQuark *current_flags)
{
    if ( self->if_data != NULL )
    {
        gchar **data;
        for ( data = self->if_data ; *data != NULL ; ++data )
        {
            if ( ! eventd_event_has_data(event, *data) )
                return FALSE;
        }
    }

    if ( self->if_data_matches != NULL )
    {
        EventdEventsEventDataMatch *match;
        GVariant *data;
        for ( match = self->if_data_matches ; match->data != NULL ; ++match )
        {
            if ( ! eventd_event_has_data(event, match->data) )
                continue;
            if ( ( data = eventd_event_get_data(event, match->data) ) == NULL )
                return FALSE;

            if ( match->key != NULL )
            {
                if ( ! g_variant_is_of_type(data, G_VARIANT_TYPE_VARDICT) )
                    return FALSE;

                data = g_variant_lookup_value(data, match->key, g_variant_get_type(match->value));
                if ( data == NULL )
                    return FALSE;
            }
            else if ( ! g_variant_type_equal(g_variant_get_type(data), g_variant_get_type(match->value)) )
                return FALSE;

            gint ret;
            ret = g_variant_compare(data, match->value);
            ret = CLAMP(ret, -1, 1);
            if ( ( ret != match->accepted[0] ) && ( ret != match->accepted[1] ) )
                return FALSE;
        }
    }

    if ( self->if_data_regexes != NULL )
    {
        EventdEventsEventDataRegex *match;
        const gchar *data;
        for ( match = self->if_data_regexes ; match->data != NULL ; ++match )
        {
            if ( ! eventd_event_has_data(event, match->data) )
                continue;
            if ( ( data = eventd_event_get_data_string(event, match->data) ) == NULL )
                return FALSE;
            if ( ! g_regex_match(match->regex, data, 0, NULL) )
                return FALSE;
        }
    }

    if ( current_flags != NULL )
    {
        GQuark *flag;
        if ( self->flags_whitelist != NULL )
        {
            GQuark *wflag;
            for ( wflag = self->flags_whitelist ; *wflag != 0 ; ++wflag )
            {
                gboolean has = FALSE;
                for ( flag = current_flags ; ( *flag != 0 ) && ( ! has ) ; ++flag )
                {
                    if ( *flag == *wflag )
                        has = TRUE;
                }
                if ( ! has )
                    return FALSE;
            }
        }

        if ( self->flags_blacklist != NULL )
        {
            GQuark *bflag;
            for ( bflag = self->flags_blacklist ; *bflag != 0 ; ++bflag )
            {
                for ( flag = current_flags ; *flag != 0 ; ++flag )
                {
                    if ( *flag == *bflag )
                        return FALSE;
                }
            }
        }
    }

    return TRUE;
}
static void
start_element (GMarkupParseContext  *context,
               const gchar          *element_name,
               const gchar         **attribute_names,
               const gchar         **attribute_values,
               gpointer              user_data,
               GError              **error)
{
  ParseState *state = user_data;
  const GSList *element_stack;
  const gchar *container;

  element_stack = g_markup_parse_context_get_element_stack (context);
  container = element_stack->next ? element_stack->next->data : NULL;

#define COLLECT(first, ...) \
  g_markup_collect_attributes (element_name,                                 \
                               attribute_names, attribute_values, error,     \
                               first, __VA_ARGS__, G_MARKUP_COLLECT_INVALID)
#define OPTIONAL   G_MARKUP_COLLECT_OPTIONAL
#define STRDUP     G_MARKUP_COLLECT_STRDUP
#define STRING     G_MARKUP_COLLECT_STRING
#define NO_ATTRS()  COLLECT (G_MARKUP_COLLECT_INVALID, NULL)

  if (container == NULL)
    {
      if (strcmp (element_name, "schemalist") == 0)
        {
          COLLECT (OPTIONAL | STRDUP,
                   "gettext-domain",
                   &state->schemalist_domain);
          return;
        }
    }
  else if (strcmp (container, "schemalist") == 0)
    {
      if (strcmp (element_name, "schema") == 0)
        {
          const gchar *id, *path;

          if (COLLECT (STRING, "id", &id,
                       OPTIONAL | STRING, "path", &path,
                       OPTIONAL | STRDUP, "gettext-domain",
                                          &state->schema_domain))
            {
              if (!g_hash_table_lookup (state->schemas, id))
                {
                  state->schema = gvdb_hash_table_new (state->schemas, id);
                  state->schema_root = gvdb_hash_table_insert (state->schema, "");

                  if (path != NULL)
                    gvdb_hash_table_insert_string (state->schema,
                                                   ".path", path);
                }
              else
                g_set_error (error, G_MARKUP_ERROR,
                             G_MARKUP_ERROR_INVALID_CONTENT,
                             "<schema id='%s'> already specified", id);
            }
          return;
        }
    }
  else if (strcmp (container, "schema") == 0)
    {
      if (strcmp (element_name, "key") == 0)
        {
          const gchar *name, *type;

          if (COLLECT (STRING, "name", &name, STRING, "type", &type))
            {
              if (!is_valid_keyname (name, error))
                return;

              if (!g_hash_table_lookup (state->schema, name))
                {
                  state->key = gvdb_hash_table_insert (state->schema, name);
                  gvdb_item_set_parent (state->key, state->schema_root);
                }
              else
                {
                  g_set_error (error, G_MARKUP_ERROR,
                               G_MARKUP_ERROR_INVALID_CONTENT,
                               "<key name='%s'> already specified", name);
                  return;
                }

              if (g_variant_type_string_is_valid (type))
                state->type = g_variant_type_new (type);
              else
                {
                  g_set_error (error, G_MARKUP_ERROR,
                               G_MARKUP_ERROR_INVALID_CONTENT,
                               "invalid GVariant type string '%s'", type);
                  return;
                }

              g_variant_builder_init (&state->key_options,
                                      G_VARIANT_TYPE ("a{sv}"));
            }

          return;
        }
      else if (strcmp (element_name, "child") == 0)
        {
          const gchar *name, *schema;

          if (COLLECT (STRING, "name", &name, STRING, "schema", &schema))
            {
              gchar *childname;

              if (!is_valid_keyname (name, error))
                return;

              childname = g_strconcat (name, "/", NULL);

              if (!g_hash_table_lookup (state->schema, childname))
                gvdb_hash_table_insert_string (state->schema, childname, schema);
              else
                g_set_error (error, G_MARKUP_ERROR,
                             G_MARKUP_ERROR_INVALID_CONTENT,
                             "<child name='%s'> already specified", name);

              g_free (childname);
              return;
            }
        }
    }
  else if (strcmp (container, "key") == 0)
    {
      if (strcmp (element_name, "default") == 0)
        {
          const gchar *l10n;

          if (COLLECT (STRING | OPTIONAL, "l10n", &l10n,
                       STRDUP | OPTIONAL, "context", &state->context))
            {
              if (l10n != NULL)
                {
                  if (!g_hash_table_lookup (state->schema, ".gettext-domain"))
                    {
                      const gchar *domain = state->schema_domain ?
                                            state->schema_domain :
                                            state->schemalist_domain;

                      if (domain == NULL)
                        {
                          g_set_error_literal (error, G_MARKUP_ERROR,
                                               G_MARKUP_ERROR_INVALID_CONTENT,
                                               "l10n requested, but no "
                                               "gettext domain given");
                          return;
                        }

                      gvdb_hash_table_insert_string (state->schema,
                                                     ".gettext-domain",
                                                     domain);

                      if (strcmp (l10n, "messages") == 0)
                        state->l10n = 'm';
                      else if (strcmp (l10n, "time") == 0)
                        state->l10n = 't';
                      else
                        {
                          g_set_error (error, G_MARKUP_ERROR,
                                       G_MARKUP_ERROR_INVALID_CONTENT,
                                       "unsupported l10n category: %s", l10n);
                          return;
                        }
                    }
                }
              else
                {
                  state->l10n = '\0';

                  if (state->context != NULL)
                    {
                      g_set_error_literal (error, G_MARKUP_ERROR,
                                           G_MARKUP_ERROR_INVALID_CONTENT,
                                           "translation context given for "
                                           " value without l10n enabled");
                      return;
                    }
                }

              state->string = g_string_new (NULL);
            }

          return;
        }
      else if (strcmp (element_name, "summary") == 0 ||
               strcmp (element_name, "description") == 0)
        {
          state->string = g_string_new (NULL);
          NO_ATTRS ();
          return;
        }
      else if (strcmp (element_name, "range") == 0)
        {
          const gchar *min_str, *max_str;

          if (!type_allows_range (state->type))
            {
              gchar *type = g_variant_type_dup_string (state->type);
              g_set_error (error, G_MARKUP_ERROR,
                          G_MARKUP_ERROR_INVALID_CONTENT,
                          "Element <%s> not allowed for keys of type \"%s\"\n",
                          element_name, type);
              g_free (type);
              return;
            }

          if (!COLLECT (STRING, "min", &min_str,
                        STRING, "max", &max_str))
            return;

          state->min = g_variant_parse (state->type, min_str, NULL, NULL, error);
          if (state->min == NULL)
            return;

          state->max = g_variant_parse (state->type, max_str, NULL, NULL, error);
          if (state->max == NULL)
            return;

          if (g_variant_compare (state->min, state->max) > 0)
            {
              g_set_error (error, G_MARKUP_ERROR,
                           G_MARKUP_ERROR_INVALID_CONTENT,
                           "Element <%s> specified minimum is greater than maxmimum",
                           element_name);
              return;
            }

          g_variant_builder_add (&state->key_options, "{sv}", "range",
                                 g_variant_new ("(@?@?)", state->min, state->max));
          return;
        }
      else if (strcmp (element_name, "choices") == 0)
        {
          if (!type_allows_choices (state->type))
            {
              gchar *type = g_variant_type_dup_string (state->type);
              g_set_error (error, G_MARKUP_ERROR,
                           G_MARKUP_ERROR_INVALID_CONTENT,
                           "Element <%s> not allowed for keys of type \"%s\"\n",
                           element_name, type);
              g_free (type);
              return;
            }

          state->choices = g_string_new ("\xff");

          NO_ATTRS ();
          return;
        }
    }
  else if (strcmp (container, "choices") == 0)
    {
      if (strcmp (element_name, "choice") == 0)
        {
          const gchar *value;

          if (COLLECT (STRING, "value", &value))
            g_string_append_printf (state->choices, "%s\xff", value);

          return;
        }
    }

  if (container)
    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                 "Element <%s> not allowed inside <%s>\n",
                 element_name, container);
  else
    g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                 "Element <%s> not allowed at toplevel\n", element_name);
}
Beispiel #4
0
static gboolean
check_gsettings_condition (NemoAction *action, const gchar *condition)
{

    gchar **split = g_strsplit (condition, " ", 6);
    gint len = g_strv_length (split);

    if (len != 6 && 
        len != 3) {
        g_strfreev (split);
        return FALSE;
    }

    if (g_strcmp0 (split[0], "gsettings") != 0) {
        g_strfreev (split);
        return FALSE;
    }

    if (len == 6 &&
        (!g_variant_type_string_is_valid (split[GSETTINGS_TYPE_INDEX]) || 
         !operator_is_valid (split[GSETTINGS_OP_INDEX]))) {
        g_printerr ("Nemo Action: Either gsettings variant type (%s) or operator (%s) is invalid.\n",
                    split[GSETTINGS_TYPE_INDEX], split[GSETTINGS_OP_INDEX]);
        g_strfreev (split);
        return FALSE;
    }

    GSettingsSchemaSource *schema_source;
    gboolean ret = FALSE;
    const GVariantType *target_type;

    if (len == 3) {
        target_type = G_VARIANT_TYPE_BOOLEAN;
    } else {
        target_type = G_VARIANT_TYPE (split[GSETTINGS_TYPE_INDEX]);
    }

    schema_source = g_settings_schema_source_get_default();

    if (g_settings_schema_source_lookup (schema_source, split[GSETTINGS_SCHEMA_INDEX], TRUE)) {
        GSettings *s = g_settings_new (split[GSETTINGS_SCHEMA_INDEX]);
        gchar **keys = g_settings_list_keys (s);
        gint i;
        for (i = 0; i < g_strv_length (keys); i++) {
            if (len == 3) {
                if (g_strcmp0 (keys[i], split[GSETTINGS_KEY_INDEX]) == 0) {
                    GVariant *setting_var = g_settings_get_value (s, split[GSETTINGS_KEY_INDEX]);
                    const GVariantType *setting_type = g_variant_get_type (setting_var);
                    if (g_variant_type_equal (setting_type, target_type))
                        ret = g_variant_get_boolean (setting_var);
                    g_variant_unref (setting_var);
                }
            } else {
                if (g_strcmp0 (keys[i], split[GSETTINGS_KEY_INDEX]) == 0) {
                    GVariant *setting_var = g_settings_get_value (s, split[GSETTINGS_KEY_INDEX]);
                    const GVariantType *setting_type = g_variant_get_type (setting_var);
                    if (g_variant_type_equal (setting_type, target_type)) {
                        GVariant *target_var = g_variant_parse (target_type,
                                                                split[GSETTINGS_VAL_INDEX],
                                                                NULL, NULL, NULL);
                        if (target_var != NULL) {
                            gint vector = g_variant_compare (setting_var, target_var);
                            ret = try_vector (split[GSETTINGS_OP_INDEX], vector);
                            g_variant_unref (target_var);
                        } else {
                            g_printerr ("Nemo Action: gsettings value could not be parsed into a valid GVariant\n");
                        }
                    }
                    g_variant_unref (setting_var);
                }
            }
        }
        g_strfreev (keys);
        g_object_unref (s);
        g_strfreev (split);
        return ret;
    } else {
        g_strfreev (split);
        return FALSE;
    }
}