static GType
object_peek_type (JsonNode *node)
{
   JsonObject *obj;
   const gchar *type_str;

   if (!node ||
       !JSON_NODE_HOLDS_OBJECT(node) ||
       !(obj = json_node_get_object(node)) ||
       !json_object_has_member(obj, "type") ||
       !JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "type")) ||
       !(type_str = json_object_get_string_member(obj, "type"))) {
      return FALSE;
   }

   if (!g_strcmp0(type_str, "note")) {
      return CATCH_TYPE_NOTE;
   } else if (!g_strcmp0(type_str, "image")) {
      return CATCH_TYPE_IMAGE;
   } else if (!g_strcmp0(type_str, "audio")) {
      return CATCH_TYPE_AUDIO;
   } else if (!g_strcmp0(type_str, "comment")) {
      return CATCH_TYPE_COMMENT;
   } else if (!g_strcmp0(type_str, "attachment")) {
      return CATCH_TYPE_ATTACHMENT;
   } else if (!g_strcmp0(type_str, "checkitem")) {
      return CATCH_TYPE_CHECK_ITEM;
   }

   return G_TYPE_NONE;
}
Beispiel #2
0
static gboolean
catch_space_load_from_json (CatchResource  *resource,
                             JsonNode       *node,
                             GError        **error)
{
   CatchSpace *space = (CatchSpace *)resource;
   JsonObject *obj;

   ENTRY;

   g_return_val_if_fail(CATCH_IS_SPACE(space), FALSE);
   g_return_val_if_fail(node != NULL, FALSE);

   if (CATCH_RESOURCE_CLASS(catch_space_parent_class)->load_from_json) {
      if (!CATCH_RESOURCE_CLASS(catch_space_parent_class)->
          load_from_json(resource, node, error)) {
         RETURN(FALSE);
      }
   }

   if (JSON_NODE_HOLDS_OBJECT(node) &&
       (obj = json_node_get_object(node))) {
      if (json_object_has_member(obj, "name") &&
          JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "name"))) {
         catch_space_set_name(CATCH_SPACE(resource),
                               json_object_get_string_member(obj, "name"));
      }
   }

   RETURN(TRUE);
}
Beispiel #3
0
/**
 * json_reader_get_boolean_value:
 * @reader: a #JsonReader
 *
 * Retrieves the boolean value of the current position of @reader
 *
 * Return value: the boolean value
 *
 * Since: 0.12
 */
gboolean
json_reader_get_boolean_value (JsonReader *reader)
{
  JsonNode *node;

  g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
  json_reader_return_val_if_error_set (reader, FALSE);

  if (reader->priv->current_node == NULL)
    {
      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
                             _("No node available at the current position"));
      return FALSE;
    }

  node = reader->priv->current_node;

  if (!JSON_NODE_HOLDS_VALUE (node))
    {
      json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
                             _("The current position holds a '%s' and not a value"),
                             json_node_type_get_name (JSON_NODE_TYPE (node)));
      return FALSE;
    }

  return json_node_get_boolean (node);
}
Beispiel #4
0
static void
add_alias_to_listing (GHashTable *listing,
                      CockpitPackage *package,
                      JsonNode *node)
{
  const gchar *value;

  if (JSON_NODE_HOLDS_VALUE (node) && json_node_get_value_type (node) == G_TYPE_STRING)
    {
      value = json_node_get_string (node);
      if (validate_package (value))
        {
          g_hash_table_replace (listing, (gchar *)value, cockpit_package_ref (package));
          g_debug ("%s: package has alias: %s", package->name, value);
        }
      else
        {
          g_message ("invalid \"alias\" package name: \"%s\"", value);
        }
    }
  else
    {
      g_message ("invalid \"alias\" value type: \"%s\"", json_node_type_name (node));
    }
}
Beispiel #5
0
/**
 * json_reader_get_string_value:
 * @reader: a #JsonReader
 *
 * Retrieves the string value of the current position of @reader
 *
 * Return value: the string value
 *
 * Since: 0.12
 */
const gchar *
json_reader_get_string_value (JsonReader *reader)
{
  JsonNode *node;

  g_return_val_if_fail (JSON_IS_READER (reader), NULL);
  json_reader_return_val_if_error_set (reader, NULL);

  if (reader->priv->current_node == NULL)
    {
      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_NODE,
                             _("No node available at the current position"));
      return NULL;
    }

  node = reader->priv->current_node;

  if (!JSON_NODE_HOLDS_VALUE (node))
    {
      json_reader_set_error (reader, JSON_READER_ERROR_NO_VALUE,
                             _("The current position holds a '%s' and not a value"),
                             json_node_type_get_name (JSON_NODE_TYPE (node)));
      return NULL;
    }

  if (json_node_get_value_type (node) != G_TYPE_STRING)
    {
      json_reader_set_error (reader, JSON_READER_ERROR_INVALID_TYPE,
                             _("The current position does not hold a string type"));
      return NULL;
    }

  return json_node_get_string (reader->priv->current_node);
}
Beispiel #6
0
static void
router_rule_compile (RouterRule *rule,
                     JsonObject *object)
{
  RouterMatch *match;
  GList *names, *l;
  JsonNode *node;
  gint i;

  g_assert (rule->matches == NULL);

  names = json_object_get_members (object);
  rule->matches = g_new0 (RouterMatch, g_list_length (names) + 1);
  for (l = names, i = 0; l != NULL; l = g_list_next (l), i++)
    {
      match = &rule->matches[i];
      match->name = g_strdup (l->data);
      node = json_object_get_member (object, l->data);

      /* A glob style string pattern */
      if (JSON_NODE_HOLDS_VALUE (node) && json_node_get_value_type (node) == G_TYPE_STRING)
        match->glob = g_pattern_spec_new (json_node_get_string (node));

      /* A null matches anything */
      if (!JSON_NODE_HOLDS_NULL (node))
        match->node = json_node_copy (node);
    }

  /* The last match has a null name */
  g_list_free (names);
}
/**
 * json_reader_is_value:
 * @reader: a #JsonReader
 *
 * Checks whether the @reader is currently on a value
 *
 * Return value: %TRUE if the #JsonReader is on a value, and %FALSE
 *   otherwise
 *
 * Since: 0.12
 */
gboolean
json_reader_is_value (JsonReader *reader)
{
  g_return_val_if_fail (JSON_IS_READER (reader), FALSE);
  json_reader_return_val_if_error_set (reader, FALSE);

  if (reader->priv->current_node == NULL)
    return FALSE;

  return JSON_NODE_HOLDS_VALUE (reader->priv->current_node);
}
Beispiel #8
0
static gboolean
read_config_file(AppContext *app, GError **err)
{
  JsonNode *root;
  JsonParser *parser;
  parser = json_parser_new ();
  if (!json_parser_load_from_file (parser, app->config_filename, err)) {
    g_object_unref(parser);
    return FALSE;
  }
  root = json_parser_get_root(parser);
  if (JSON_NODE_HOLDS_OBJECT(root)) {
    JsonNode *value_node;
    JsonObject *root_obj = json_node_get_object(root);
    value_node = json_object_get_member(root_obj, "extensionPort");
    if (value_node && JSON_NODE_HOLDS_VALUE(value_node)) {
      app->http_port = json_node_get_int(value_node);
    }
    value_node = json_object_get_member(root_obj, "httpRootPath");
    if (value_node && JSON_NODE_HOLDS_VALUE(value_node)) {
      GFile *base;
      GFile *http_root;
      GFile *config;
      char *path = json_node_dup_string(value_node);
      config = g_file_new_for_path(app->config_filename);
      base = g_file_get_parent(config);
      g_object_unref(config);
      g_free(app->http_root);
      http_root = g_file_resolve_relative_path (base, path);
      g_free(path);
      g_object_unref(base);
      if (http_root) {
	app->http_root = g_file_get_path(http_root);
	g_debug("HTTP root: %s", app->http_root);
	g_object_unref(http_root);
      }
    }
  }
  g_object_unref(parser);
  return TRUE;
}
/**
 * json_reader_get_value:
 * @reader: a #JsonReader
 *
 * Retrieves the #JsonNode of the current position of @reader
 *
 * Return value: (transfer none): a #JsonNode, or %NULL. The returned node
 *   is owned by the #JsonReader and it should not be modified or freed
 *   directly
 *
 * Since: 0.12
 */
JsonNode *
json_reader_get_value (JsonReader *reader)
{
  g_return_val_if_fail (JSON_IS_READER (reader), NULL);
  json_reader_return_val_if_error_set (reader, NULL);

  if (reader->priv->current_node == NULL)
    return NULL;

  if (!JSON_NODE_HOLDS_VALUE (reader->priv->current_node))
    return NULL;

  return reader->priv->current_node;
}
/**
 * json_reader_get_double_value:
 * @reader: a #JsonReader
 *
 * Retrieves the floating point value of the current position of @reader
 *
 * Return value: the floating point value
 *
 * Since: 0.12
 */
gdouble
json_reader_get_double_value (JsonReader *reader)
{
  g_return_val_if_fail (JSON_IS_READER (reader), 0.0);
  json_reader_return_val_if_error_set (reader, 0.0);

  if (reader->priv->current_node == NULL)
    return 0.0;

  if (!JSON_NODE_HOLDS_VALUE (reader->priv->current_node))
    return 0.0;

  return json_node_get_double (reader->priv->current_node);
}
/**
 * json_reader_get_string_value:
 * @reader: a #JsonReader
 *
 * Retrieves the string value of the current position of @reader
 *
 * Return value: the string value
 *
 * Since: 0.12
 */
G_CONST_RETURN gchar *
json_reader_get_string_value (JsonReader *reader)
{
  g_return_val_if_fail (JSON_IS_READER (reader), NULL);
  json_reader_return_val_if_error_set (reader, NULL);

  if (reader->priv->current_node == NULL)
    return NULL;

  if (!JSON_NODE_HOLDS_VALUE (reader->priv->current_node))
    return NULL;

  return json_node_get_string (reader->priv->current_node);
}
/**
 * json_array_get_string_element:
 * @array: a #JsonArray
 * @index_: the index of the element to retrieve
 *
 * Conveniently retrieves the string value of the element at @index_
 * inside @array
 *
 * See also: json_array_get_element(), json_node_get_string()
 *
 * Return value: the string value; the returned string is owned by
 *   the #JsonArray and should not be modified or freed
 *
 * Since: 0.8
 */
G_CONST_RETURN gchar *
json_array_get_string_element (JsonArray *array,
                               guint      index_)
{
  JsonNode *node;

  g_return_val_if_fail (array != NULL, NULL);
  g_return_val_if_fail (index_ < array->elements->len, NULL);

  node = g_ptr_array_index (array->elements, index_);
  g_return_val_if_fail (node != NULL, NULL);
  g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);

  if (JSON_NODE_HOLDS_NULL (node))
    return NULL;

  return json_node_get_string (node);
}
Beispiel #13
0
/**
 * json_object_get_string_member:
 * @object: a #JsonObject
 * @member_name: the name of the member
 *
 * Convenience function that retrieves the string value
 * stored in @member_name of @object
 *
 * See also: json_object_get_member()
 *
 * Return value: the string value of the object's member
 *
 * Since: 0.8
 */
const gchar *
json_object_get_string_member (JsonObject  *object,
                               const gchar *member_name)
{
  JsonNode *node;

  g_return_val_if_fail (object != NULL, NULL);
  g_return_val_if_fail (member_name != NULL, NULL);

  node = object_get_member_internal (object, member_name);
  g_return_val_if_fail (node != NULL, NULL);
  g_return_val_if_fail (JSON_NODE_HOLDS_VALUE (node) || JSON_NODE_HOLDS_NULL (node), NULL);

  if (JSON_NODE_HOLDS_NULL (node))
    return NULL;

  return json_node_get_string (node);
}
GHashTable *
json_ghashtable_deserialize (JsonNode *node,
                             GError **error)
{
  GHashTable *table = NULL;
  GList *k;
  GList *keys;
  JsonNode *node_value;
  JsonObject *object;
  gchar *value;

  if (!node || !JSON_NODE_HOLDS_OBJECT (node)) {
    g_set_error_literal (error,
                         JSON_READER_ERROR,
                         JSON_READER_ERROR_NO_OBJECT,
                         "Expected JSON object");
    return table;
  }

  object = json_node_get_object (node);
  keys = json_object_get_members (object);
  table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);

  for (k = keys; k ; k = g_list_next (k)) {
    node_value = json_object_get_member (object, k->data);
    if (!JSON_NODE_HOLDS_VALUE (node_value) ||
        (value = json_node_dup_string (node_value)) == NULL) {
      g_set_error_literal (error,
                           JSON_READER_ERROR,
                           JSON_READER_ERROR_INVALID_TYPE,
                           "Expected JSON string");
      g_hash_table_unref (table);
      table = NULL;
      break;
    } else {
      g_hash_table_insert (table, g_strdup (k->data), value);
    }
  }

  g_list_free (keys);
  json_object_unref (object);

  return table;
}
Beispiel #15
0
void
js_util_pushjsonnode(js_State *state, JsonNode *node)
{
  GType type;

  if (!JSON_NODE_HOLDS_VALUE(node))
  {
    js_pushundefined(state);
    return;
  }

  type = json_node_get_value_type(node);
  if (type == G_TYPE_STRING)
    js_pushstring(state, json_node_get_string(node));
  else if (type == G_TYPE_INT)
    js_pushnumber(state, json_node_get_int(node));
  else if (type == G_TYPE_BOOLEAN)
    js_pushboolean(state, json_node_get_boolean(node));
  else
    js_pushundefined(state);
}
Beispiel #16
0
static void
ide_compile_commands_load_worker (GTask        *task,
                                  gpointer      source_object,
                                  gpointer      task_data,
                                  GCancellable *cancellable)
{
  IdeCompileCommands *self = source_object;
  GFile *gfile = task_data;
  g_autoptr(JsonParser) parser = NULL;
  g_autoptr(GError) error = NULL;
  g_autoptr(GHashTable) info_by_file = NULL;
  g_autoptr(GHashTable) directories_by_path = NULL;
  g_autoptr(GPtrArray) vala_info = NULL;
  g_autofree gchar *contents = NULL;
  JsonNode *root;
  JsonArray *ar;
  gsize len = 0;
  guint n_items;

  IDE_ENTRY;

  g_assert (G_IS_TASK (task));
  g_assert (IDE_IS_COMPILE_COMMANDS (self));
  g_assert (G_IS_FILE (gfile));
  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));

  parser = json_parser_new ();

  if (!g_file_load_contents (gfile, cancellable, &contents, &len, NULL, &error) ||
      !json_parser_load_from_data (parser, contents, len, &error))
    {
      g_task_return_error (task, g_steal_pointer (&error));
      IDE_EXIT;
    }

  if (NULL == (root = json_parser_get_root (parser)) ||
      !JSON_NODE_HOLDS_ARRAY (root) ||
      NULL == (ar = json_node_get_array (root)))
    {
      g_task_return_new_error (task,
                               G_IO_ERROR,
                               G_IO_ERROR_INVALID_DATA,
                               "Failed to extract commands, invalid json");
      IDE_EXIT;
    }

  info_by_file = g_hash_table_new_full (g_file_hash,
                                        (GEqualFunc)g_file_equal,
                                        NULL,
                                        compile_info_free);

  directories_by_path = g_hash_table_new_full (g_str_hash,
                                               g_str_equal,
                                               NULL,
                                               g_object_unref);

  vala_info = g_ptr_array_new_with_free_func (compile_info_free);

  n_items = json_array_get_length (ar);

  for (guint i = 0; i < n_items; i++)
    {
      CompileInfo *info;
      JsonNode *item;
      JsonNode *value;
      JsonObject *obj;
      GFile *dir;
      const gchar *directory = NULL;
      const gchar *file = NULL;
      const gchar *command = NULL;

      item = json_array_get_element (ar, i);

      /* Skip past this node if its invalid for some reason, so we
       * can try to be tolerante of errors created by broken tooling.
       */
      if (item == NULL ||
          !JSON_NODE_HOLDS_OBJECT (item) ||
          NULL == (obj = json_node_get_object (item)))
        continue;

      if (json_object_has_member (obj, "file") &&
          NULL != (value = json_object_get_member (obj, "file")) &&
          JSON_NODE_HOLDS_VALUE (value))
        file = json_node_get_string (value);

      if (json_object_has_member (obj, "directory") &&
          NULL != (value = json_object_get_member (obj, "directory")) &&
          JSON_NODE_HOLDS_VALUE (value))
        directory = json_node_get_string (value);

      if (json_object_has_member (obj, "command") &&
          NULL != (value = json_object_get_member (obj, "command")) &&
          JSON_NODE_HOLDS_VALUE (value))
        command = json_node_get_string (value);

      /* Ignore items that are missing something or other */
      if (file == NULL || command == NULL || directory == NULL)
        continue;

      /* Try to reduce the number of GFile we have for directories */
      if (NULL == (dir = g_hash_table_lookup (directories_by_path, directory)))
        {
          dir = g_file_new_for_path (directory);
          g_hash_table_insert (directories_by_path, (gchar *)directory, dir);
        }

      info = g_slice_new (CompileInfo);
      info->file = g_file_resolve_relative_path (dir, file);
      info->directory = g_object_ref (dir);
      info->command = g_strdup (command);
      g_hash_table_replace (info_by_file, info->file, info);

      /*
       * We might need to keep a special copy of this for resolving .vala
       * builds which won't be able ot be matched based on the filename. We
       * keep all of them around right now in case we want to later on find
       * the closest match based on directory.
       */
      if (g_str_has_suffix (file, ".vala"))
        {
          info = g_slice_new (CompileInfo);
          info->file = g_file_resolve_relative_path (dir, file);
          info->directory = g_object_ref (dir);
          info->command = g_strdup (command);
          g_ptr_array_add (vala_info, info);
        }
    }

  self->info_by_file = g_steal_pointer (&info_by_file);
  self->vala_info = g_steal_pointer (&vala_info);

  g_task_return_boolean (task, TRUE);

  IDE_EXIT;
}
gchar *build_remote_exec_cmd(TrgClient * tc, GtkTreeModel * model,
                             GList * selection, const gchar * input)
{
    TrgPrefs *prefs = trg_client_get_prefs(tc);
    JsonObject *session = trg_client_get_session(tc);
    JsonObject *profile = trg_prefs_get_connection(prefs);
    gchar *work;
    GRegex *regex, *replacerx;
    GMatchInfo *match_info;
    gchar *whole, *wholeEscaped, *id, *tmp, *valuestr, *repeater;
    JsonNode *replacement;

    if (!profile)
        return NULL;

    work = g_strdup(input);
    regex = g_regex_new("%{([A-Za-z\\-]+)}(?:\\[(.*)\\])?", 0, 0, NULL);

    g_regex_match_full(regex, input, -1, 0, 0, &match_info, NULL);

    if (match_info) {
        while (g_match_info_matches(match_info)) {
            whole = g_match_info_fetch(match_info, 0);
            wholeEscaped = g_regex_escape_string(whole, -1);
            id = g_match_info_fetch(match_info, 1);
            repeater = g_match_info_fetch(match_info, 2);

            replacerx = g_regex_new(wholeEscaped, 0, 0, NULL);
            valuestr = NULL;

            if (profile && json_object_has_member(profile, id)) {
                replacement = json_object_get_member(profile, id);
                if (JSON_NODE_HOLDS_VALUE(replacement))
                    valuestr = dump_json_value(replacement);
            } else if (session && json_object_has_member(session, id)) {
                replacement = json_object_get_member(session, id);
                if (JSON_NODE_HOLDS_VALUE(replacement))
                    valuestr = dump_json_value(replacement);
            } else {
                GString *gs = g_string_new("");
                GList *li;
                GtkTreeIter iter;
                JsonObject *json;
                gchar *piece;

                for (li = selection; li; li = g_list_next(li)) {
                    piece = NULL;
                    gtk_tree_model_get_iter(model, &iter,
                                            (GtkTreePath *) li->data);
                    gtk_tree_model_get(model, &iter, TORRENT_COLUMN_JSON,
                                       &json, -1);
                    if (json_object_has_member(json, id)) {
                        replacement = json_object_get_member(json, id);
                        if (JSON_NODE_HOLDS_VALUE(replacement)) {
                            piece = dump_json_value(replacement);
                        }
                    }

                    if (!piece) {
                        if (!g_strcmp0(id, "full-dir")) {
                            piece = torrent_get_full_dir(json);
                        } else if (!g_strcmp0(id, "full-path")) {
                            piece = torrent_get_full_path(json);
                        }
                    }

                    if (piece) {
                        g_string_append(gs, piece);
                        g_free(piece);
                    }

                    if (!repeater)
                        break;

                    if (piece && li != g_list_last(selection))
                        g_string_append(gs, repeater);
                }

                if (gs->len > 0)
                    valuestr = g_string_free(gs, FALSE);
                else
                    g_string_free(gs, TRUE);
            }

            if (valuestr) {
                tmp = g_regex_replace(replacerx, work, -1, 0, valuestr, 0,
                                      NULL);
                g_free(work);
                work = tmp;
                g_free(valuestr);
            }

            g_regex_unref(replacerx);
            g_free(whole);
            g_free(repeater);
            g_free(wholeEscaped);
            g_free(id);
            g_match_info_next(match_info, NULL);
        }

        g_match_info_free(match_info);
    }

    g_regex_unref(regex);
    return work;
}
static void
on_socket_connect (GObject *object,
                   GAsyncResult *result,
                   gpointer user_data)
{
  CockpitWebSocketStream *self = COCKPIT_WEB_SOCKET_STREAM (user_data);
  CockpitChannel *channel = COCKPIT_CHANNEL (self);
  const gchar *problem = "protocol-error";
  gchar **protocols = NULL;
  GList *l, *names = NULL;
  GError *error = NULL;
  JsonObject *options;
  JsonObject *headers;
  const gchar *value;
  JsonNode *node;
  GIOStream *io;

  io = cockpit_connect_stream_finish (result, &error);
  if (error)
    {
      problem = cockpit_stream_problem (error, self->origin, "couldn't connect",
                                        cockpit_channel_close_options (channel));
      cockpit_channel_close (channel, problem);
      goto out;
    }

  options = cockpit_channel_get_options (channel);

  if (!cockpit_json_get_strv (options, "protocols", NULL, &protocols))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "%s: invalid \"protocol\" value in WebSocket stream request", self->origin);
      goto out;
    }

  if (G_IS_TLS_CONNECTION (io))
    {
      self->sig_accept_cert =  g_signal_connect (G_TLS_CONNECTION (io),
                                                 "accept-certificate",
                                                 G_CALLBACK (on_rejected_certificate),
                                                 self);
    }
  else
    {
      self->sig_accept_cert = 0;
    }

  self->client = web_socket_client_new_for_stream (self->url, self->origin, (const gchar **)protocols, io);

  node = json_object_get_member (options, "headers");
  if (node)
    {
      if (!JSON_NODE_HOLDS_OBJECT (node))
        {
          cockpit_channel_fail (channel, "protocol-error",
                                "%s: invalid \"headers\" field in WebSocket stream request", self->origin);
          goto out;
        }

      headers = json_node_get_object (node);
      names = json_object_get_members (headers);
      for (l = names; l != NULL; l = g_list_next (l))
        {
          node = json_object_get_member (headers, l->data);
          if (!node || !JSON_NODE_HOLDS_VALUE (node) || json_node_get_value_type (node) != G_TYPE_STRING)
            {
              cockpit_channel_fail (channel, "protocol-error",
                                    "%s: invalid header value in WebSocket stream request: %s",
                                    self->origin, (gchar *)l->data);
              goto out;
            }
          value = json_node_get_string (node);

          g_debug ("%s: sending header: %s %s", self->origin, (gchar *)l->data, value);
          web_socket_client_include_header (WEB_SOCKET_CLIENT (self->client), l->data, value);
        }
    }

  self->sig_open = g_signal_connect (self->client, "open", G_CALLBACK (on_web_socket_open), self);
  self->sig_message = g_signal_connect (self->client, "message", G_CALLBACK (on_web_socket_message), self);
  self->sig_closing = g_signal_connect (self->client, "closing", G_CALLBACK (on_web_socket_closing), self);
  self->sig_close = g_signal_connect (self->client, "close", G_CALLBACK (on_web_socket_close), self);
  self->sig_error = g_signal_connect (self->client, "error", G_CALLBACK (on_web_socket_error), self);

  problem = NULL;

out:
  g_clear_error (&error);
  g_strfreev (protocols);
  if (io)
    g_object_unref (io);
  g_list_free (names);
}
Beispiel #19
0
Datei: json.c Projekt: GNOME/gegl
static void
attach (GeglOperation *operation)
{
  JsonOp *self = (JsonOp *)operation;
  GeglNode  *gegl = operation->node;
  JsonArray *connections;
  GList *l;

  // Processes
  JsonObject *root = self->json_root;
  JsonObject *processes = json_object_get_object_member(root, "processes");

  GList *process_names = json_object_get_members(processes);
  for (l = process_names; l != NULL; l = l->next) {
      const gchar *name = l->data;
      JsonObject *proc = json_object_get_object_member(processes, name);
      const gchar *component = json_object_get_string_member(proc, "component");
      gchar *opname = component2geglop(component);

      GeglNode *node = gegl_node_new_child (gegl, "operation", opname, NULL);
      gegl_operation_meta_watch_node (operation, node);
      g_assert(node);
      g_hash_table_insert(self->nodes, (gpointer)g_strdup(name), (gpointer)node);
      g_free(opname);
  }
  g_list_free(process_names);

  // Connections
  connections = json_object_get_array_member(root, "connections");
  g_assert(connections);
  for (int i=0; i<json_array_get_length(connections); i++) {
      JsonObject *conn = json_array_get_object_element(connections, i);
      JsonObject *tgt = json_object_get_object_member(conn, "tgt");
      const gchar *tgt_proc = json_object_get_string_member(tgt, "process");
      const gchar *tgt_port = json_object_get_string_member(tgt, "port");
      GeglNode *tgt_node = g_hash_table_lookup(self->nodes, tgt_proc);
      JsonNode *srcnode;

      g_assert(tgt_node);

      srcnode = json_object_get_member(conn, "src");
      if (srcnode) {
          // Connection
          JsonObject *src = json_object_get_object_member(conn, "src");
          const gchar *src_proc = json_object_get_string_member(src, "process");
          const gchar *src_port = json_object_get_string_member(src, "port");
          GeglNode *src_node = g_hash_table_lookup(self->nodes, src_proc);

          g_assert(src_node);

          gegl_node_connect_to (src_node, src_port, tgt_node, tgt_port);
      } else {
          // IIP
          JsonNode *datanode = json_object_get_member(conn, "data");
          GValue value = G_VALUE_INIT;
          GParamSpec *paramspec;

          g_assert(JSON_NODE_HOLDS_VALUE(datanode));
          json_node_get_value(datanode, &value);
          paramspec = gegl_node_find_property(tgt_node, tgt_port);

          set_prop(tgt_node, tgt_port, paramspec, &value);
          g_value_unset(&value);
      }
  }


  // Exported ports
  if (json_object_has_member(root, "inports")) {
      JsonObject *inports = json_object_get_object_member(root, "inports");
      GList *inport_names = json_object_get_members(inports);
      for (l = inport_names; l != NULL; l = l->next) {
          const gchar *name = l->data;
          JsonObject *conn = json_object_get_object_member(inports, name);
          const gchar *proc = json_object_get_string_member(conn, "process");
          const gchar *port = json_object_get_string_member(conn, "port");
          GeglNode *node = g_hash_table_lookup(self->nodes, proc);

          g_assert(node);

          if (g_strcmp0(name, "input") == 0) {
              GeglNode *input = gegl_node_get_input_proxy (gegl, "input");
              gegl_node_connect_to (input, "output", node, "input");
          } else {
            gegl_operation_meta_redirect (operation, name, node, port);
          }
      }

      g_list_free(inport_names);
  }

  if (json_object_has_member(root, "outports")) {
      JsonObject *outports = json_object_get_object_member(root, "outports");
      GList *outport_names = json_object_get_members(outports);
      for (l = outport_names; l != NULL; l = l->next) {
          const gchar *name = l->data;
          JsonObject *conn = json_object_get_object_member(outports, name);
          const gchar *proc = json_object_get_string_member(conn, "process");
          const gchar *port = json_object_get_string_member(conn, "port");
          GeglNode *node = g_hash_table_lookup(self->nodes, proc);
          g_assert(node);

          if (g_strcmp0(name, "output") == 0) {
            GeglNode *proxy = gegl_node_get_output_proxy (gegl, "output");
            gegl_node_connect_to (node, port, proxy, "input");
          } else {
            g_warning("Unsupported output '%s' exported in .json file", name);
          }
      }

      g_list_free(outport_names);
  }

}
Beispiel #20
0
static void
postal_http_handle_v1_notify (UrlRouter         *router,
                              SoupServer        *server,
                              SoupMessage       *message,
                              const gchar       *path,
                              GHashTable        *params,
                              GHashTable        *query,
                              SoupClientContext *client,
                              gpointer           user_data)
{
   PostalNotification *notif;
   const gchar *collapse_key = NULL;
   const gchar *str;
   PostalHttp *http = user_data;
   JsonObject *aps;
   JsonObject *c2dm;
   JsonObject *gcm;
   JsonObject *object;
   JsonArray *devices;
   JsonArray *users;
   GPtrArray *devices_ptr;
   GPtrArray *users_ptr;
   JsonNode *node;
   GError *error = NULL;
   guint count;
   guint i;

   g_assert(SOUP_IS_SERVER(server));
   g_assert(SOUP_IS_MESSAGE(message));
   g_assert(path);
   g_assert(client);
   g_assert(POSTAL_IS_HTTP(http));

   if (message->method != SOUP_METHOD_POST) {
      soup_message_set_status(message, SOUP_STATUS_METHOD_NOT_ALLOWED);
      return;
   }

   soup_server_pause_message(server, message);

   if (!(node = postal_http_parse_body(message, &error))) {
      postal_http_reply_error(http, message, error);
      g_error_free(error);
      return;
   }

   if (!JSON_NODE_HOLDS_OBJECT(node) ||
       !(object = json_node_get_object(node)) ||
       !json_object_has_member(object, "aps") ||
       !(node = json_object_get_member(object, "aps")) ||
       !JSON_NODE_HOLDS_OBJECT(node) ||
       !(aps = json_object_get_object_member(object, "aps")) ||
       !json_object_has_member(object, "c2dm") ||
       !(node = json_object_get_member(object, "c2dm")) ||
       !JSON_NODE_HOLDS_OBJECT(node) ||
       !(c2dm = json_object_get_object_member(object, "c2dm")) ||
       !json_object_has_member(object, "gcm") ||
       !(node = json_object_get_member(object, "gcm")) ||
       !JSON_NODE_HOLDS_OBJECT(node) ||
       !(gcm = json_object_get_object_member(object, "gcm")) ||
       !json_object_has_member(object, "users") ||
       !(node = json_object_get_member(object, "users")) ||
       !JSON_NODE_HOLDS_ARRAY(node) ||
       !(users = json_object_get_array_member(object, "users")) ||
       !json_object_has_member(object, "devices") ||
       !(node = json_object_get_member(object, "devices")) ||
       !JSON_NODE_HOLDS_ARRAY(node) ||
       !(devices = json_object_get_array_member(object, "devices"))) {
      error = g_error_new(postal_json_error_quark(), 0,
                          "Missing or invalid fields in JSON payload.");
      postal_http_reply_error(http, message, error);
      json_node_free(node);
      g_error_free(error);
      return;
   }

   if (json_object_has_member(object, "collapse_key") &&
       (node = json_object_get_member(object, "collapse_key")) &&
       JSON_NODE_HOLDS_VALUE(node)) {
      collapse_key = json_node_get_string(node);
   }

   notif = g_object_new(POSTAL_TYPE_NOTIFICATION,
                        "aps", aps,
                        "c2dm", c2dm,
                        "collapse-key", collapse_key,
                        "gcm", gcm,
                        NULL);

   count = json_array_get_length(users);
   users_ptr = g_ptr_array_sized_new(count);
   for (i = 0; i < count; i++) {
      node = json_array_get_element(users, i);
      if (json_node_get_value_type(node) == G_TYPE_STRING) {
         str = json_node_get_string(node);
         g_ptr_array_add(users_ptr, (gchar *)str);
      }
   }
   g_ptr_array_add(users_ptr, NULL);

   count = json_array_get_length(devices);
   devices_ptr = g_ptr_array_sized_new(count);
   g_ptr_array_set_free_func(devices_ptr, g_free);
   for (i = 0; i < count; i++) {
      node = json_array_get_element(devices, i);
      if (json_node_get_value_type(node) == G_TYPE_STRING) {
         str = json_node_get_string(node);
         g_ptr_array_add(devices_ptr, g_strdup(str));
      }
   }
   g_ptr_array_add(devices_ptr, NULL);

   postal_service_notify(http->priv->service,
                         notif,
                         (gchar **)users_ptr->pdata,
                         (gchar **)devices_ptr->pdata,
                         NULL, /* TODO: Cancellable/Timeout? */
                         postal_http_notify_cb,
                         g_object_ref(message));

   g_ptr_array_unref(devices_ptr);
   g_ptr_array_unref(users_ptr);
   json_node_free(node);
   g_object_unref(notif);
}
static gboolean
catch_resource_group_api_parse_objects (CatchResourceGroup  *group,
                                        JsonNode            *result,
                                        guint               *result_offset,
                                        guint               *n_resources,
                                        GError             **error)
{
   CatchResourceGroupPrivate *priv;
   CatchResource *resource;
   JsonObject *obj;
   JsonArray *array;
   JsonNode *element;
   gboolean set_first_page = FALSE;
   gboolean ret = FALSE;
   GType resource_type;
   guint i;
   guint length;
   guint offset = 0;

   ENTRY;

   g_return_val_if_fail(CATCH_IS_RESOURCE_GROUP(group), FALSE);
   g_return_val_if_fail(result != NULL, FALSE);

   priv = group->priv;

   g_object_freeze_notify(G_OBJECT(group));

   if (!JSON_NODE_HOLDS_OBJECT(result) ||
       !(obj = json_node_get_object(result)) ||
       !json_object_has_member(obj, "objects") ||
       !JSON_NODE_HOLDS_ARRAY(json_object_get_member(obj, "objects")) ||
       !(array = json_object_get_array_member(obj, "objects"))) {
      g_set_error(error, CATCH_API_ERROR, CATCH_API_ERROR_BAD_RESPONSE,
                  _("The resonse did not contain the objects array."));
      GOTO(failure);
   }

   if (json_object_has_member(obj, "count") &&
       JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "count"))) {
      priv->count = json_object_get_int_member(obj, "count");
      set_first_page = TRUE;
      g_object_notify(G_OBJECT(group), "count");
   }

   if (json_object_has_member(obj, "offset") &&
       JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "offset"))) {
      offset = json_object_get_int_member(obj, "offset");
   }

   length = json_array_get_length(array);
   for (i = 0; i < length; i++) {
      element = json_array_get_element(array, i);
      if (!(resource_type = object_peek_type(element))) {
         g_set_error(error, CATCH_API_ERROR, CATCH_API_ERROR_BAD_RESPONSE,
                     _("The JSON object did not contain a \"type\" field."));
         GOTO(failure);
      }
      resource = g_object_new(resource_type, NULL);
      g_assert(CATCH_IS_RESOURCE(resource));
      if (!catch_resource_load_from_json(resource, element, error)) {
         g_object_unref(resource);
         GOTO(failure);
      }
      catch_resource_group_set_resource(CATCH_RESOURCE_GROUP(group),
                                        offset + i, resource);
      g_object_unref(resource);
   }

   if (set_first_page) {
      priv->first_page_size = length;
   }

   if (result_offset) {
      *result_offset = offset;
   }

   if (n_resources) {
      *n_resources = length;
   }

   ret = TRUE;

failure:
   g_object_thaw_notify(G_OBJECT(group));

   RETURN(ret);
}
static gboolean
catch_resource_group_api_parse_activities (CatchResourceGroup  *group,
                                           JsonNode            *result,
                                           guint               *result_offset,
                                           guint               *n_resources,
                                           GError             **error)
{
   CatchResourceGroupPrivate *priv;
   CatchResource *resource;
   JsonObject *obj;
   JsonArray *array;
   JsonNode *element;
   gboolean set_first_page = FALSE;
   gboolean ret = FALSE;
   guint i;
   guint length;
   guint offset = 0;

   ENTRY;

   g_return_val_if_fail(CATCH_IS_RESOURCE_GROUP(group), FALSE);
   g_return_val_if_fail(result != NULL, FALSE);

   priv = group->priv;

   g_object_freeze_notify(G_OBJECT(group));

   if (!JSON_NODE_HOLDS_OBJECT(result) ||
       !(obj = json_node_get_object(result)) ||
       !json_object_has_member(obj, "activities") ||
       !JSON_NODE_HOLDS_ARRAY(json_object_get_member(obj, "activities")) ||
       !(array = json_object_get_array_member(obj, "activities"))) {
      g_set_error(error, CATCH_API_ERROR, CATCH_API_ERROR_BAD_RESPONSE,
                  _("The resonse was invalid."));
      GOTO(failure);
   }

   if (json_object_has_member(obj, "count") &&
       JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "count"))) {
      priv->count = json_object_get_int_member(obj, "count");
      set_first_page = TRUE;
      g_object_notify_by_pspec(G_OBJECT(group), gParamSpecs[PROP_COUNT]);
   }

   if (json_object_has_member(obj, "offset") &&
       JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "offset"))) {
      offset = json_object_get_int_member(obj, "offset");
   }

   length = json_array_get_length(array);
   for (i = 0; i < length; i++) {
      element = json_array_get_element(array, i);
      resource = g_object_new(CATCH_TYPE_ACTIVITY, NULL);
      if (!catch_resource_load_from_json(resource, element, error)) {
         g_object_unref(resource);
         GOTO(failure);
      }
      catch_resource_group_set_resource(CATCH_RESOURCE_GROUP(group),
                                        offset + i, resource);
      g_object_unref(resource);
   }

   if (set_first_page) {
      priv->first_page_size = length;
   }

   if (result_offset) {
      *result_offset = offset;
   }

   if (n_resources) {
      *n_resources = length;
   }

   ret = TRUE;

failure:
   g_object_thaw_notify(G_OBJECT(group));

   RETURN(ret);
}
static JsonNode *
catch_resource_group_api_parse_response (CatchResourceGroup   *group,
                                         SoupMessage          *message,
                                         GError              **error)
{
   const gchar *content_type;
   const gchar *error_message = NULL;
   const gchar *status = NULL;
   JsonParser *parser;
   JsonObject *obj = NULL;
   JsonNode *result = NULL;
   JsonNode *root;

   ENTRY;

   g_return_val_if_fail(CATCH_IS_RESOURCE_GROUP(group), NULL);
   g_return_val_if_fail(SOUP_IS_MESSAGE(message), NULL);

   /*
    * If the result isn't application/json, something really wrong happened.
    */
   content_type = soup_message_headers_get_one(message->response_headers,
                                               "Content-Type");
   if (!!g_strcmp0("application/json", content_type)) {
      g_set_error(error, CATCH_API_ERROR, CATCH_API_ERROR_BAD_REQUEST,
                  _("The API request failed for unknown reasons; HTTP %d."),
                  message->status_code);
      RETURN(NULL);
   }

   /*
    * Create a JSON parser to extract the result object from the response. Load
    * the content from the response body.
    */
   parser = json_parser_new();
   if (!json_parser_load_from_data(parser, message->response_body->data,
                                   message->response_body->length, error)) {
      g_object_unref(parser);
      RETURN(NULL);
   }

   /*
    * Check to see if the response is improperly formatted or an error.
    */
   root = json_parser_get_root(parser);
   if (!(root = json_parser_get_root(parser)) ||
       !JSON_NODE_HOLDS_OBJECT(root) ||
       !(obj = json_node_get_object(root)) ||
       !json_object_has_member(obj, "status") ||
       !JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "status")) ||
       !(status = json_object_get_string_member(obj, "status")) ||
       !!g_strcmp0("ok", status)) {
      if (obj &&
          json_object_has_member(obj, "error") &&
          JSON_NODE_HOLDS_OBJECT(json_object_get_member(obj, "error")) &&
          (obj = json_object_get_object_member(obj, "error")) &&
          json_object_has_member(obj, "message") &&
          JSON_NODE_HOLDS_VALUE(json_object_get_member(obj, "message")) &&
          (error_message = json_object_get_string_member(obj, "message"))) {
         g_set_error(error, CATCH_API_ERROR, CATCH_API_ERROR_BAD_REQUEST,
                     _("%s"), error_message);
      } else {
         g_set_error(error, CATCH_API_ERROR, CATCH_API_ERROR_BAD_REQUEST,
                     _("The API request failed for unknown reasons; HTTP %d."),
                     message->status_code);
      }
      g_object_unref(parser);
      RETURN(NULL);
   }

   /*
    * Try to extract the result node from the response.
    */
   if (obj && json_object_has_member(obj, "result")) {
      if ((result = json_object_get_member(obj, "result"))) {
         result = json_node_copy(result);
      }
   }

   g_object_unref(parser);

   RETURN(result);
}
Beispiel #24
0
static void
postal_http_handle_v1_users_user_badge (UrlRouter         *router,
                                        SoupServer        *server,
                                        SoupMessage       *message,
                                        const gchar       *path,
                                        GHashTable        *params,
                                        GHashTable        *query,
                                        SoupClientContext *client,
                                        gpointer           user_data)
{
   const gchar *user;
   PostalHttp *http = user_data;
   JsonNode *node = NULL;
   GError *error = NULL;
   guint badge;

   ENTRY;

   g_assert(router);
   g_assert(SOUP_IS_SERVER(server));
   g_assert(SOUP_IS_MESSAGE(message));
   g_assert(path);
   g_assert(params);
   g_assert(g_hash_table_contains(params, "user"));
   g_assert(client);
   g_assert(POSTAL_IS_HTTP(http));

   user = g_hash_table_lookup(params, "user");

   if (message->method == SOUP_METHOD_PUT) {
      if (!(node = postal_http_parse_body(message, &error)) ||
          !JSON_NODE_HOLDS_VALUE(node)) {
         if (!error) {
            error = g_error_new(JSON_PARSER_ERROR,
                                JSON_PARSER_ERROR_UNKNOWN,
                                _("JSON must contain integer."));
         }
         postal_http_reply_error(http, message, error);
         GOTO(cleanup);
      }
      badge = json_node_get_int(node);
      g_object_set_data(G_OBJECT(message), "http", http);
      postal_service_set_user_badge(http->priv->service,
                                    user,
                                    badge,
                                    NULL,
                                    postal_http_set_user_badge_cb,
                                    g_object_ref(message));
      soup_server_pause_message(server, message);
      EXIT;
   }

   soup_message_set_status(message, SOUP_STATUS_METHOD_NOT_ALLOWED);

cleanup:
   g_clear_error(&error);
   if (node) {
      json_node_free(node);
   }

   EXIT;
}
Beispiel #25
0
static void
push_gcm_client_deliver_cb (SoupSession *session,
                            SoupMessage *message,
                            gpointer     user_data)
{
   GSimpleAsyncResult *simple = user_data;
   const gchar *str;
   JsonObject *obj;
   JsonParser *p = NULL;
   JsonArray *ar;
   JsonNode *root;
   JsonNode *node;
   gboolean removed;
   GError *error = NULL;
   GList *list;
   gsize length;
   guint i;

   ENTRY;

   g_assert(SOUP_IS_SESSION(session));
   g_assert(SOUP_IS_MESSAGE(message));
   g_assert(G_IS_SIMPLE_ASYNC_RESULT(simple));

   switch (message->status_code) {
   case SOUP_STATUS_OK:
      break;
   case SOUP_STATUS_BAD_REQUEST:
      /*
       * TODO: Log that there was a JSON encoding error likely.
       */
      break;
   case SOUP_STATUS_UNAUTHORIZED:
      g_simple_async_result_set_error(simple,
                                      SOUP_HTTP_ERROR,
                                      message->status_code,
                                      _("GCM request unauthorized."));
      GOTO(failure);
   default:
      if (SOUP_STATUS_IS_SERVER_ERROR(message->status_code) &&
          (str = soup_message_headers_get_one(message->response_headers,
                                              "Retry-After"))) {
         /*
          * TODO: Implement exponential back-off.
          */
      }
      g_simple_async_result_set_error(simple,
                                      SOUP_HTTP_ERROR,
                                      message->status_code,
                                      _("Unknown failure occurred."));
      break;
   }

   if (!message->response_body->data || !message->response_body->length) {
      g_simple_async_result_set_error(simple,
                                      SOUP_HTTP_ERROR,
                                      SOUP_STATUS_IO_ERROR,
                                      _("No data was received from GCM."));
      GOTO(failure);
   }

   p = json_parser_new();

   if (!json_parser_load_from_data(p,
                                   message->response_body->data,
                                   message->response_body->length,
                                   &error)) {
      g_simple_async_result_take_error(simple, error);
      GOTO(failure);
   }

   list = g_object_get_data(G_OBJECT(simple), "identities");

   if ((root = json_parser_get_root(p)) &&
       JSON_NODE_HOLDS_OBJECT(root) &&
       (obj = json_node_get_object(root)) &&
       json_object_has_member(obj, "results") &&
       (node = json_object_get_member(obj, "results")) &&
       JSON_NODE_HOLDS_ARRAY(node) &&
       (ar = json_node_get_array(node))) {
      length = json_array_get_length(ar);
      for (i = 0; i < length && list; i++, list = list->next) {
         /*
          * TODO: Handle the case that the device_token has been renamed.
          */
         removed = FALSE;
         if ((obj = json_array_get_object_element(ar, i)) &&
             json_object_has_member(obj, "error") &&
             (node = json_object_get_member(obj, "error")) &&
             JSON_NODE_HOLDS_VALUE(node) &&
             (str = json_node_get_string(node))) {
            if (!g_strcmp0(str, "MissingRegistration")) {
               removed = TRUE;
            } else if (!g_strcmp0(str, "InvalidRegistration")) {
               removed = TRUE;
            } else if (!g_strcmp0(str, "MismatchSenderId")) {
            } else if (!g_strcmp0(str, "NotRegistered")) {
               removed = TRUE;
            } else if (!g_strcmp0(str, "MessageTooBig")) {
            } else if (!g_strcmp0(str, "InvalidDataKey")) {
            } else if (!g_strcmp0(str, "InvalidTtl")) {
            }

            if (removed) {
               g_assert(PUSH_IS_GCM_IDENTITY(list->data));
               g_signal_emit(session, gSignals[IDENTITY_REMOVED], 0, list->data);
            }
         }
      }
   }

   g_simple_async_result_set_op_res_gboolean(simple, TRUE);

failure:
   g_simple_async_result_complete_in_idle(simple);
   g_object_unref(simple);
   if (p) {
      g_object_unref(p);
   }

   EXIT;
}
Beispiel #26
0
static void
send_http_request (CockpitHttpStream *self)
{
  CockpitChannel *channel = COCKPIT_CHANNEL (self);
  JsonObject *options;
  gboolean had_host;
  gboolean had_encoding;
  const gchar *method;
  const gchar *path;
  GString *string = NULL;
  JsonNode *node;
  JsonObject *headers;
  const gchar *header;
  const gchar *value;
  GList *request = NULL;
  GList *names = NULL;
  GBytes *bytes;
  GList *l;
  gsize total;

  options = cockpit_channel_get_options (channel);

  /*
   * The checks we do here for token validity are just enough to be able
   * to format an HTTP response, without leaking across lines etc.
   */

  if (!cockpit_json_get_string (options, "path", NULL, &path))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "%s: bad \"path\" field in HTTP stream request", self->name);
      goto out;
    }
  else if (path == NULL)
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "%s: missing \"path\" field in HTTP stream request", self->name);
      goto out;
    }
  else if (!cockpit_web_response_is_simple_token (path))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "%s: invalid \"path\" field in HTTP stream request", self->name);
      goto out;
    }

  if (!cockpit_json_get_string (options, "method", NULL, &method))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "%s: bad \"method\" field in HTTP stream request", self->name);
      goto out;
    }
  else if (method == NULL)
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "%s: missing \"method\" field in HTTP stream request", self->name);
      goto out;
    }
  else if (!cockpit_web_response_is_simple_token (method))
    {
      cockpit_channel_fail (channel, "protocol-error",
                            "%s: invalid \"method\" field in HTTP stream request", self->name);
      goto out;
    }

  g_debug ("%s: sending %s request", self->name, method);

  string = g_string_sized_new (128);
  g_string_printf (string, "%s %s HTTP/1.1\r\n", method, path);

  had_encoding = had_host = FALSE;

  node = json_object_get_member (options, "headers");
  if (node)
    {
      if (!JSON_NODE_HOLDS_OBJECT (node))
        {
          cockpit_channel_fail (channel, "protocol-error",
                                "%s: invalid \"headers\" field in HTTP stream request", self->name);
          goto out;
        }

      headers = json_node_get_object (node);
      names = json_object_get_members (headers);
      for (l = names; l != NULL; l = g_list_next (l))
        {
          header = l->data;
          if (!cockpit_web_response_is_simple_token (header))
            {
              cockpit_channel_fail (channel, "protocol-error",
                                    "%s: invalid header in HTTP stream request: %s", self->name, header);
              goto out;
            }
          node = json_object_get_member (headers, header);
          if (!node || !JSON_NODE_HOLDS_VALUE (node) || json_node_get_value_type (node) != G_TYPE_STRING)
            {
              cockpit_channel_fail (channel, "protocol-error",
                                    "%s: invalid header value in HTTP stream request: %s", self->name, header);
              goto out;
            }
          value = json_node_get_string (node);
          if (disallowed_header (header, value, self->binary))
            {
              cockpit_channel_fail (channel, "protocol-error",
                                    "%s: disallowed header in HTTP stream request: %s", self->name, header);
              goto out;
            }
          if (!cockpit_web_response_is_header_value (value))
            {
              cockpit_channel_fail (channel, "protocol-error",
                                    "%s: invalid header value in HTTP stream request: %s", self->name, header);
              goto out;
            }

          g_string_append_printf (string, "%s: %s\r\n", (gchar *)l->data, value);
          g_debug ("%s: sending header: %s %s", self->name, (gchar *)l->data, value);

          if (g_ascii_strcasecmp (l->data, "Host") == 0)
            had_host = TRUE;
          if (g_ascii_strcasecmp (l->data, "Accept-Encoding") == 0)
            had_encoding = TRUE;
        }
    }

  if (!had_host)
    {
      g_string_append (string, "Host: ");
      g_string_append_uri_escaped (string, self->client->connectable->name, "[]!%$&()*+,-.:;=\\_~", FALSE);
      g_string_append (string, "\r\n");
    }
  if (!had_encoding)
    g_string_append (string, "Accept-Encoding: identity\r\n");

  if (!self->binary)
    g_string_append (string, "Accept-Charset: UTF-8\r\n");

  request = g_list_reverse (self->request);
  self->request = NULL;

  /* Calculate how much data we have to send */
  total = 0;
  for (l = request; l != NULL; l = g_list_next (l))
    total += g_bytes_get_size (l->data);

  if (request || g_ascii_strcasecmp (method, "POST") == 0)
    g_string_append_printf (string, "Content-Length: %" G_GSIZE_FORMAT "\r\n", total);
  g_string_append (string, "\r\n");

  bytes = g_string_free_to_bytes (string);
  string = NULL;

  cockpit_stream_write (self->stream, bytes);
  g_bytes_unref (bytes);

  /* Now send all the data */
  for (l = request; l != NULL; l = g_list_next (l))
    cockpit_stream_write (self->stream, l->data);

out:
  g_list_free (names);
  g_list_free_full (request, (GDestroyNotify)g_bytes_unref);
  if (string)
    g_string_free (string, TRUE);
}