/** * cockpit_channel_control: * @self: the channel * @command: the control command * @options: optional control message or NULL * * Send a control message to the other side. * * If @options is not NULL, then it may be modified by this code. * * With @command of "done" will send an EOF to the other side. This * should only be called once. Whether an EOF should be sent or not * depends on the payload type. */ void cockpit_channel_control (CockpitChannel *self, const gchar *command, JsonObject *options) { JsonObject *object; GBytes *message; const gchar *problem; gchar *problem_copy = NULL; g_return_if_fail (COCKPIT_IS_CHANNEL (self)); g_return_if_fail (command != NULL); if (g_str_equal (command, "done")) { g_return_if_fail (self->priv->sent_done == FALSE); self->priv->sent_done = TRUE; } /* If closing save the close options * and let close send the message */ else if (g_str_equal (command, "close")) { if (!self->priv->close_options) { /* Ref for close_options, freed in parent */ self->priv->close_options = json_object_ref (options); } if (!cockpit_json_get_string (options, "problem", NULL, &problem)) problem = NULL; /* Use a problem copy so it out lasts the value in close_options */ problem_copy = g_strdup (problem); cockpit_channel_close (self, problem_copy); goto out; } if (options) object = json_object_ref (options); else object = json_object_new (); json_object_set_string_member (object, "command", command); json_object_set_string_member (object, "channel", self->priv->id); message = cockpit_json_write_bytes (object); json_object_unref (object); cockpit_transport_send (self->priv->transport, NULL, message); g_bytes_unref (message); out: g_free (problem_copy); }
/** * cockpit_channel_control: * @self: the channel * @command: the control command * @options: optional control message or NULL * * Send a control message to the other side. * * If @options is not NULL, then it may be modified by this code. * * With @command of "done" will send an EOF to the other side. This * should only be called once. Whether an EOF should be sent or not * depends on the payload type. */ void cockpit_channel_control (CockpitChannel *self, const gchar *command, JsonObject *options) { JsonObject *object; GBytes *message; g_return_if_fail (COCKPIT_IS_CHANNEL (self)); g_return_if_fail (command != NULL); if (g_str_equal (command, "done")) { g_return_if_fail (self->priv->sent_done == FALSE); self->priv->sent_done = TRUE; } if (options) object = json_object_ref (options); else object = json_object_new (); json_object_set_string_member (object, "command", command); json_object_set_string_member (object, "channel", self->priv->id); message = cockpit_json_write_bytes (object); json_object_unref (object); cockpit_transport_send (self->priv->transport, NULL, message); g_bytes_unref (message); }
static JsonObject * parse_login_data (const gchar *json_str) { JsonObject *results = NULL; JsonObject *login_data = NULL; GError *error = NULL; results = cockpit_json_parse_object (json_str, strlen(json_str), &error); if (!results) { g_warning ("received bad json data: %s", error->message); g_error_free (error); goto out; } if (!cockpit_json_get_object (results, "login-data", NULL, &login_data)) { g_warning ("received bad login-data: %s", json_str); login_data = NULL; goto out; } if (login_data) login_data = json_object_ref (login_data); out: if (results) json_object_unref (results); return login_data; }
static const gchar * process_socket_init (CockpitWebService *self, CockpitSocket *socket, JsonObject *options) { gint64 version; if (!cockpit_json_get_int (options, "version", -1, &version)) { g_warning ("invalid version field in init message"); return "protocol-error"; } if (version == 1) { g_debug ("received web socket init message"); if (socket->init_received) json_object_unref (socket->init_received); socket->init_received = json_object_ref (options); return NULL; } else { g_message ("web socket used unsupported version of cockpit protocol: %" G_GINT64_FORMAT, version); return "not-supported"; } }
/** * couchdb_struct_field_set_struct_field: * @sf: A #CouchdbStructField object * @field: Name of the field * @calue: Value to set the field to * * Set the value of a string field in the given struct field. */ void couchdb_struct_field_set_struct_field (CouchdbStructField *sf, const char *field, CouchdbStructField *value) { g_return_if_fail (sf != NULL); g_return_if_fail (field != NULL); g_return_if_fail (value != NULL); json_object_set_object_member (sf->json_object, field, json_object_ref (value->json_object)); }
/** * json_node_dup_object: * @node: a #JsonNode * * Retrieves the #JsonObject inside @node. The reference count of * the returned object is increased. * * Return value: (transfer full): the #JsonObject */ JsonObject * json_node_dup_object (JsonNode *node) { g_return_val_if_fail (JSON_NODE_IS_VALID (node), NULL); g_return_val_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT, NULL); if (node->data.object) return json_object_ref (node->data.object); return NULL; }
static CockpitChannelResponse * cockpit_channel_response_create (CockpitWebService *service, CockpitWebResponse *response, CockpitTransport *transport, const gchar *logname, GHashTable *headers, JsonObject *open) { CockpitChannelResponse *chesp; const gchar *payload; JsonObject *done; GBytes *bytes; payload = json_object_get_string_member (open, "payload"); chesp = g_new0 (CockpitChannelResponse, 1); chesp->response = g_object_ref (response); chesp->transport = g_object_ref (transport); chesp->headers = g_hash_table_ref (headers); chesp->channel = cockpit_web_service_unique_channel (service); chesp->open = json_object_ref (open); if (!cockpit_json_get_string (open, "path", chesp->channel, &chesp->logname)) chesp->logname = chesp->channel; json_object_set_string_member (open, "command", "open"); json_object_set_string_member (open, "channel", chesp->channel); /* Special handling for http-stream1, splice in headers, handle injection */ if (g_strcmp0 (payload, "http-stream1") == 0) chesp->transport_recv = g_signal_connect (transport, "recv", G_CALLBACK (on_httpstream_recv), chesp); else chesp->transport_recv = g_signal_connect (transport, "recv", G_CALLBACK (on_transport_recv), chesp); /* Special handling for http-stream2, splice in headers, handle injection */ if (g_strcmp0 (payload, "http-stream2") == 0) chesp->transport_control = g_signal_connect (transport, "control", G_CALLBACK (on_httpstream_control), chesp); else chesp->transport_control = g_signal_connect (transport, "control", G_CALLBACK (on_transport_control), chesp); chesp->transport_closed = g_signal_connect (transport, "closed", G_CALLBACK (on_transport_closed), chesp); bytes = cockpit_json_write_bytes (chesp->open); cockpit_transport_send (transport, NULL, bytes); g_bytes_unref (bytes); done = cockpit_transport_build_json ("command", "done", "channel", chesp->channel, NULL); bytes = cockpit_json_write_bytes (done); json_object_unref (done); cockpit_transport_send (transport, NULL, bytes); g_bytes_unref (bytes); return chesp; }
static FrozenMessage * frozen_message_new (GBytes *payload, JsonObject *control) { FrozenMessage *frozen = g_slice_new0 (FrozenMessage); if (payload) frozen->payload = g_bytes_ref (payload); if (control) frozen->control = json_object_ref (control); return frozen; }
void trg_prefs_set_connection(TrgPrefs * p, JsonObject * profile) { TrgPrefsPrivate *priv = p->priv; if (priv->connectionObj) json_object_unref(priv->connectionObj); if (profile) json_object_ref(profile); priv->connectionObj = profile; }
CouchdbStructField * couchdb_struct_field_new_from_json_object (JsonObject *json_object) { CouchdbStructField *sf; sf = g_slice_new (CouchdbStructField); sf->ref_count = 1; sf->json_object = json_object_ref (json_object); sf->uuid = NULL; return sf; }
/** * cockpit_transport_parse_command: * @payload: command JSON payload to parse * @command: a location to return the command * @channel: location to return the channel * @options: location to return the options * * Parse a command and return various values from the * command. The @options value is transfered with ownership, * so you should free it after done. @command and @channel are owned by * @options. @channel will be NULL for a missing channel. * * On failure, message has already been printed. * * Returns: whether command parsed or not. */ gboolean cockpit_transport_parse_command (GBytes *payload, const gchar **command, const gchar **channel, JsonObject **options) { GError *error = NULL; gboolean ret = FALSE; JsonObject *object; gboolean valid; object = cockpit_json_parse_bytes (payload, &error); if (!object) { g_warning ("Received unparseable control message: %s", error->message); g_error_free (error); goto out; } /* Parse out the command */ if (command) { if (!cockpit_json_get_string (object, "command", NULL, command) || *command == NULL || g_str_equal (*command, "")) { g_warning ("Received invalid control message: invalid or missing command"); goto out; } } /* Parse out the channel */ valid = cockpit_json_get_string (object, "channel", NULL, channel); if (valid && *channel) { valid = (!g_str_equal ("", *channel) && strcspn (*channel, "\n") == strlen (*channel)); } if (!valid) { g_warning ("Received invalid control message: invalid channel"); goto out; } *options = json_object_ref (object); ret = TRUE; out: if (object) json_object_unref (object); return ret; }
void cockpit_channel_socket_open (CockpitWebService *service, JsonObject *open, const gchar *original_path, const gchar *path, GIOStream *io_stream, GHashTable *headers, GByteArray *input_buffer) { CockpitChannelSocket *chock = NULL; WebSocketDataType data_type; CockpitTransport *transport; gchar **protocols = NULL; if (!cockpit_web_service_parse_external (open, NULL, NULL, &protocols) || !cockpit_web_service_parse_binary (open, &data_type)) { respond_with_error (original_path, path, io_stream, headers, 400, "Bad channel request"); goto out; } transport = cockpit_web_service_ensure_transport (service, open); if (!transport) { respond_with_error (original_path, path, io_stream, headers, 502, "Failed to open channel transport"); goto out; } chock = g_new0 (CockpitChannelSocket, 1); chock->channel = cockpit_web_service_unique_channel (service); chock->open = json_object_ref (open); chock->data_type = data_type; json_object_set_string_member (open, "command", "open"); json_object_set_string_member (open, "channel", chock->channel); chock->socket = cockpit_web_service_create_socket ((const gchar **)protocols, original_path, io_stream, headers, input_buffer); chock->socket_open = g_signal_connect (chock->socket, "open", G_CALLBACK (on_socket_open), chock); chock->socket_message = g_signal_connect (chock->socket, "message", G_CALLBACK (on_socket_message), chock); chock->socket_close = g_signal_connect (chock->socket, "close", G_CALLBACK (on_socket_close), chock); chock->transport = g_object_ref (transport); chock->transport_recv = g_signal_connect (chock->transport, "recv", G_CALLBACK (on_transport_recv), chock); chock->transport_control = g_signal_connect (chock->transport, "control", G_CALLBACK (on_transport_control), chock); chock->transport_closed = g_signal_connect (chock->transport, "closed", G_CALLBACK (on_transport_closed), chock); out: g_free (protocols); }
void cockpit_channel_close_obj_option (CockpitChannel *self, const gchar *name, JsonObject *object) { g_return_if_fail (COCKPIT_IS_CHANNEL (self)); g_return_if_fail (name != NULL); g_return_if_fail (object != NULL); if (!self->priv->close_options) self->priv->close_options = json_object_new (); json_object_set_object_member (self->priv->close_options, name, json_object_ref (object)); }
/** * json_node_set_object: * @node: a #JsonNode initialized to %JSON_NODE_OBJECT * @object: a #JsonObject * * Sets @objects inside @node. The reference count of @object is increased. */ void json_node_set_object (JsonNode *node, JsonObject *object) { g_return_if_fail (node != NULL); g_return_if_fail (JSON_NODE_TYPE (node) == JSON_NODE_OBJECT); if (node->data.object != NULL) json_object_unref (node->data.object); if (object) node->data.object = json_object_ref (object); else node->data.object = NULL; }
static gboolean on_transport_control (CockpitTransport *transport, const char *command, guint channel, JsonObject *options, GBytes *message, gpointer user_data) { CockpitPolkitAgent *self = COCKPIT_POLKIT_AGENT (user_data); ReauthorizeCaller *caller; const gchar *response; const gchar *cookie; GBytes *bytes; if (!g_str_equal (command, "authorize")) return FALSE; if (!cockpit_json_get_string (options, "cookie", NULL, &cookie) || !cockpit_json_get_string (options, "response", NULL, &response) || !cookie || !response) { g_warning ("got an invalid authorize command from cockpit-ws"); cockpit_transport_close (transport, "protocol-error"); return TRUE; } caller = g_hash_table_lookup (self->callers, cookie); if (!caller) { g_debug ("received authorize response for caller that has gone away"); return TRUE; } g_debug ("got \"authorize\" response from cockpit-ws, will send to helper: %s", response); bytes = g_bytes_new_with_free_func (response, strlen (response), (GDestroyNotify)json_object_unref, json_object_ref (options)); cockpit_pipe_write (caller->helper, bytes); g_bytes_unref (bytes); bytes = g_bytes_new_static ("\n", 1); cockpit_pipe_write (caller->helper, bytes); g_bytes_unref (bytes); return TRUE; }
void trg_client_set_session(TrgClient * tc, JsonObject * session) { TrgClientPrivate *priv = tc->priv; if (priv->session) json_object_unref(priv->session); else priv->version = session_get_version(session); priv->session = session; json_object_ref(session); priv->seedRatioLimit = session_get_seed_ratio_limit(session); priv->seedRatioLimited = session_get_seed_ratio_limited(session); g_signal_emit(tc, signals[TC_SESSION_UPDATED], 0, session); }
static void foreach_object_cb (JsonObject *object, const char *member_name, JsonNode *member_node, gpointer user_data) { GSList **list = (GSList **) user_data; if (json_node_get_node_type (member_node) == JSON_NODE_OBJECT) { CouchdbStructField *sf; sf = couchdb_struct_field_new_from_json_object ( json_object_ref (json_node_get_object (member_node))); couchdb_struct_field_set_uuid (sf, member_name); *list = g_slist_prepend (*list, sf); } }
static DynamicPeer * dynamic_peer_create (JsonObject *config) { DynamicPeer *p = g_new0 (DynamicPeer, 1); p->peers = g_hash_table_new_full (dynamic_key_hash, dynamic_key_equal, dynamic_key_free, g_object_unref); p->config = json_object_ref (config); if (!cockpit_json_get_strv (config, "environ", NULL, &p->env)) p->env = NULL; if (!cockpit_json_get_strv (config, "spawn", NULL, &p->spawn)) p->spawn = NULL; return p; }
static JsonObject * get_changes (const gchar *macaroon, gchar **discharges, const gchar *change_id, GCancellable *cancellable, GError **error) { g_autofree gchar *path = NULL; guint status_code; g_autofree gchar *reason_phrase = NULL; g_autofree gchar *response_type = NULL; g_autofree gchar *response = NULL; g_autoptr(JsonParser) parser = NULL; JsonObject *root, *result; path = g_strdup_printf ("/v2/changes/%s", change_id); if (!send_request ("GET", path, NULL, macaroon, discharges, &status_code, &reason_phrase, &response_type, &response, NULL, cancellable, error)) return NULL; if (status_code != SOUP_STATUS_OK) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "snapd returned status code %u: %s", status_code, reason_phrase); return NULL; } parser = parse_result (response, response_type, error); if (parser == NULL) return NULL; root = json_node_get_object (json_parser_get_root (parser)); result = json_object_get_object_member (root, "result"); if (result == NULL) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "snapd returned no result"); return NULL; } return json_object_ref (result); }
static void skypeweb_got_vm_download_info(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) { PurpleConversation *conv = user_data; PurpleXfer *xfer; JsonObject *obj, *file; JsonArray *files; gint64 fileSize; const gchar *url, *assetId, *status; gchar *filename; if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) return; obj = json_node_get_object(node); files = json_object_get_array_member(obj, "files"); file = json_array_get_object_element(files, 0); if (file != NULL) { status = json_object_get_string_member(file, "status"); if (status && g_str_equal(status, "ok")) { assetId = json_object_get_string_member(obj, "assetId"); fileSize = json_object_get_int_member(file, "fileSize"); url = json_object_get_string_member(file, "url"); (void) url; filename = g_strconcat(assetId, ".mp4", NULL); xfer = purple_xfer_new(sa->account, PURPLE_XFER_RECEIVE, conv->name); purple_xfer_set_size(xfer, fileSize); purple_xfer_set_filename(xfer, filename); json_object_ref(file); purple_xfer_set_protocol_data(xfer, file); purple_xfer_set_init_fnc(xfer, skypeweb_init_vm_download); purple_xfer_set_cancel_recv_fnc(xfer, skypeweb_cancel_vm_download); purple_xfer_add(xfer); g_free(filename); } else if (status && g_str_equal(status, "running")) { //skypeweb_download_video_message(sa, sid??????, conv); } } }
/** * json_builder_begin_object: * @builder: a #JsonBuilder * * Opens a subobject inside the given @builder. When done adding members to * the subobject, json_builder_end_object() must be called. * * Can be called for first or only if the call is associated to an object member * or an array element. * * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent */ JsonBuilder * json_builder_begin_object (JsonBuilder *builder) { JsonObject *object; JsonBuilderState *state; JsonBuilderState *cur_state; g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); g_return_val_if_fail (builder->priv->root == NULL, NULL); g_return_val_if_fail (g_queue_is_empty (builder->priv->stack) || json_builder_is_valid_add_mode (builder), NULL); object = json_object_new (); cur_state = g_queue_peek_head (builder->priv->stack); if (cur_state) { switch (cur_state->mode) { case JSON_BUILDER_MODE_ARRAY: json_array_add_object_element (cur_state->data.array, json_object_ref (object)); break; case JSON_BUILDER_MODE_MEMBER: json_object_set_object_member (cur_state->data.object, cur_state->member_name, json_object_ref (object)); g_free (cur_state->member_name); cur_state->member_name = NULL; cur_state->mode = JSON_BUILDER_MODE_OBJECT; break; default: g_assert_not_reached (); } } state = g_slice_new (JsonBuilderState); state->data.object = object; state->member_name = NULL; state->mode = JSON_BUILDER_MODE_OBJECT; g_queue_push_head (builder->priv->stack, state); return builder; }
static const gchar * process_transport_init (CockpitWebService *self, CockpitTransport *transport, JsonObject *options) { JsonObject *object; GBytes *payload; gint64 version; if (!cockpit_json_get_int (options, "version", -1, &version)) { g_warning ("invalid version field in init message"); return "protocol-error"; } if (version == 1) { g_debug ("received init message"); self->init_received = TRUE; g_object_set_data_full (G_OBJECT (transport), "init", json_object_ref (options), (GDestroyNotify) json_object_unref); /* Always send an init message down the new transport */ object = cockpit_transport_build_json ("command", "init", NULL); json_object_set_int_member (object, "version", 1); json_object_set_string_member (object, "host", "localhost"); payload = cockpit_json_write_bytes (object); json_object_unref (object); cockpit_transport_send (transport, NULL, payload); g_bytes_unref (payload); } else { g_message ("unsupported version of cockpit protocol: %" G_GINT64_FORMAT, version); return "not-supported"; } g_signal_emit (self, sig_transport_init, 0); return NULL; }
/** * json_builder_end_object: * @builder: a #JsonBuilder * * Closes the subobject inside the given @builder that was opened by the most * recent call to json_builder_begin_object(). * * Cannot be called after json_builder_set_member_name(). * * Return value: (transfer none): the #JsonBuilder, or %NULL if the call was inconsistent */ JsonBuilder * json_builder_end_object (JsonBuilder *builder) { JsonBuilderState *state; g_return_val_if_fail (JSON_IS_BUILDER (builder), NULL); g_return_val_if_fail (!g_queue_is_empty (builder->priv->stack), NULL); g_return_val_if_fail (json_builder_current_mode (builder) == JSON_BUILDER_MODE_OBJECT, NULL); state = g_queue_pop_head (builder->priv->stack); if (g_queue_is_empty (builder->priv->stack)) { builder->priv->root = json_node_new (JSON_NODE_OBJECT); json_node_take_object (builder->priv->root, json_object_ref (state->data.object)); } json_builder_state_free (state); return builder; }
void push_gcm_message_set_data (PushGcmMessage *message, JsonObject *data) { PushGcmMessagePrivate *priv; g_return_if_fail(PUSH_IS_GCM_MESSAGE(message)); priv = message->priv; if (priv->data) { json_object_unref(priv->data); priv->data = NULL; } if (data) { priv->data = json_object_ref(data); } g_object_notify_by_pspec(G_OBJECT(message), gParamSpecs[PROP_DATA]); }
static gboolean process_ping (CockpitChannel *self, JsonObject *ping) { GBytes *payload; if (self->priv->throttled) { g_debug ("%s: received ping while throttled", self->priv->id); g_queue_push_tail (self->priv->throttled, json_object_ref (ping)); return FALSE; } else { g_debug ("%s: replying to ping with pong", self->priv->id); json_object_set_string_member (ping, "command", "pong"); payload = cockpit_json_write_bytes (ping); cockpit_transport_send (self->priv->transport, NULL, payload); g_bytes_unref (payload); return TRUE; } }
static void send_login_response (CockpitWebResponse *response, CockpitCreds *creds, GHashTable *headers) { JsonObject *object; JsonObject *login_data; GBytes *content; object = json_object_new (); json_object_set_string_member (object, "user", cockpit_creds_get_user (creds)); json_object_set_string_member (object, "csrf-token", cockpit_creds_get_csrf_token (creds)); login_data = cockpit_creds_get_login_data (creds); if (login_data) json_object_set_object_member (object, "login-data", json_object_ref (login_data)); content = cockpit_json_write_bytes (object); json_object_unref (object); g_hash_table_replace (headers, g_strdup ("Content-Type"), g_strdup ("application/json")); cockpit_web_response_content (response, headers, content, NULL); g_bytes_unref (content); }
static void skypeweb_got_file_info(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message) { JsonObject *obj; PurpleXfer *xfer; SkypeWebFileTransfer *swft = user_data; SkypeWebAccount *sa = swft->sa; JsonParser *parser; JsonNode *node; sa->url_datas = g_slist_remove(sa->url_datas, url_data); parser = json_parser_new(); if (!json_parser_load_from_data(parser, url_text, len, NULL)) { g_free(swft->url); g_free(swft->from); g_free(swft); g_object_unref(parser); return; } node = json_parser_get_root(parser); if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) { g_free(swft->url); g_free(swft->from); g_free(swft); g_object_unref(parser); return; } obj = json_node_get_object(node); /* { "content_length": 40708, "content_full_length": 40708, "view_length": 40708, "content_state": "ready", "view_state": "ready", "view_location": "uri/views/original", "status_location": "uri/views/original/status", "scan": { "status": "passed" }, "original_filename": "filename" } */ purple_debug_info("skypeweb", "File info: %s\n", url_text); if (!json_object_has_member(obj, "content_state") || !g_str_equal(json_object_get_string_member(obj, "content_state"), "ready")) { skypeweb_present_uri_as_filetransfer(sa, json_object_get_string_member(obj, "status_location"), swft->from); g_free(swft->url); g_free(swft->from); g_free(swft); g_object_unref(parser); return; } json_object_ref(obj); swft->info = obj; xfer = purple_xfer_new(sa->account, PURPLE_XFER_RECEIVE, swft->from); purple_xfer_set_size(xfer, json_object_get_int_member(obj, "content_full_length")); purple_xfer_set_filename(xfer, json_object_get_string_member(obj, "original_filename")); purple_xfer_set_init_fnc(xfer, skypeweb_init_file_download); purple_xfer_set_cancel_recv_fnc(xfer, skypeweb_free_xfer); swft->xfer = xfer; purple_xfer_set_protocol_data(xfer, swft); purple_xfer_request(xfer); g_object_unref(parser); }
static GBytes * build_environment (CockpitWebService *service, JsonObject *modules) { const gchar *user; CockpitCreds *creds; JsonObject *env; JsonObject *localhost; JsonObject *languages; JsonObject *language; struct passwd *pwd; gchar *hostname; GBytes *bytes; guint n; const struct { const gchar *name; const gchar *code; } supported_languages[] = { { NC_("display-language", "English"), "" }, { NC_("display-language", "Danish"), "da" }, { NC_("display-language", "German"), "de" }, }; env = json_object_new (); if (service) { creds = cockpit_web_service_get_creds (service); user = cockpit_creds_get_user (creds); json_object_set_string_member (env, "user", user); pwd = cockpit_getpwnam_a (user, NULL); if (pwd) { json_object_set_string_member (env, "name", pwd->pw_gecos); free (pwd); } } localhost = json_object_new (); /* This awkwardly takes the localhost reference */ json_object_set_object_member (env, "localhost", localhost); hostname = g_malloc0 (HOST_NAME_MAX + 1); gethostname (hostname, HOST_NAME_MAX); hostname[HOST_NAME_MAX] = '\0'; json_object_set_string_member (env, "hostname", hostname); /* Only include version info if logged in */ if (service) { json_object_set_string_member (localhost, "version", PACKAGE_VERSION); json_object_set_string_member (localhost, "build_info", COCKPIT_BUILD_INFO); } languages = json_object_new (); /* This awkwardly takes the languages reference */ json_object_set_object_member (localhost, "languages", languages); for (n = 0; n < G_N_ELEMENTS (supported_languages); n++) { language = json_object_new (); json_object_set_object_member (languages, supported_languages[n].code, language); json_object_set_string_member (language, "name", supported_languages[n].name); } if (modules) json_object_set_object_member (localhost, "modules", json_object_ref (modules)); bytes = cockpit_json_write_bytes (env); json_object_unref (env); return bytes; }
GHashTable * cockpit_package_listing (JsonArray **json) { JsonArray *root = NULL; GHashTable *listing; CockpitPackage *package; GHashTable *ids; JsonObject *object; JsonArray *id; GList *names, *l; GList *packages; const gchar *name; JsonNode *node; JsonArray *array; guint i, length; listing = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, cockpit_package_unref); build_package_listing (listing); /* Add aliases to the listing */ packages = g_hash_table_get_values (listing); packages = g_list_sort (packages, compar_packages); g_list_foreach (packages, (GFunc)cockpit_package_ref, NULL); for (l = packages; l != NULL; l = g_list_next (l)) { package = l->data; node = json_object_get_member (package->manifest, "alias"); if (node) { /* * Process and remove "alias" from the manifest, as it results in * confusing and duplicated information for the front end. */ package->alias = node = json_node_copy (node); json_object_remove_member (package->manifest, "alias"); if (JSON_NODE_HOLDS_ARRAY (node)) { array = json_node_get_array (node); length = json_array_get_length (array); for (i = 0; i < length; i++) add_alias_to_listing (listing, package, json_array_get_element (array, i)); } else { add_alias_to_listing (listing, package, node); } } } g_list_free_full (packages, (GDestroyNotify)cockpit_package_unref); /* Now wrap up the checksums */ finish_checksums (listing); /* Add checksums to the listing */ packages = g_hash_table_get_values (listing); g_list_foreach (packages, (GFunc)cockpit_package_ref, NULL); for (l = packages; l != NULL; l = g_list_next (l)) { package = l->data; if (package->checksum && !g_hash_table_contains (listing, package->checksum)) { g_hash_table_replace (listing, package->checksum, cockpit_package_ref (package)); g_debug ("%s: package has checksum: %s", package->name, package->checksum); } } g_list_free_full (packages, (GDestroyNotify)cockpit_package_unref); /* Build JSON packages block */ if (json) { *json = root = json_array_new (); ids = g_hash_table_new (g_direct_hash, g_direct_equal); names = g_hash_table_get_keys (listing); names = g_list_sort (names, (GCompareFunc)strcmp); for (l = names; l != NULL; l = g_list_next (l)) { name = l->data; package = g_hash_table_lookup (listing, name); id = g_hash_table_lookup (ids, package); if (!id) { object = json_object_new (); id = json_array_new(); /* The actual package name always comes first */ json_object_set_array_member (object, "id", id); json_array_add_string_element (id, package->name); g_hash_table_insert (ids, package, id); json_object_set_object_member (object, "manifest", json_object_ref (package->manifest)); json_array_add_object_element (root, object); } /* Other ways to refer to the package */ if (!g_str_equal (name, package->name)) json_array_add_string_element (id, name); } g_list_free (names); g_hash_table_destroy (ids); } return listing; }
static gpointer _json_object_ref0 (gpointer self) { return self ? json_object_ref (self) : NULL; }