static void send_login_html (CockpitWebResponse *response, CockpitHandlerData *ws) { GHashTable *headers = NULL; GList *l, *output = NULL; gchar *login_html; GMappedFile *file; GError *error = NULL; GBytes *body = NULL; gsize length; login_html = g_build_filename (ws->static_roots[0], "login.html", NULL); file = g_mapped_file_new (login_html, FALSE, &error); if (file == NULL) { g_warning ("%s: %s", login_html, error->message); cockpit_web_response_error (response, 500, NULL, NULL); g_clear_error (&error); goto out; } body = g_mapped_file_get_bytes (file); output = cockpit_template_expand (body, substitute_environment, ws->os_release); length = 0; for (l = output; l != NULL; l = g_list_next (l)) length += g_bytes_get_size (l->data); headers = cockpit_web_server_new_table (); g_hash_table_insert (headers, g_strdup ("Content-Type"), g_strdup ("text/html; charset=utf8")); cockpit_web_response_headers_full (response, 200, "OK", length, headers); for (l = output; l != NULL; l = g_list_next (l)) { if (!cockpit_web_response_queue (response, l->data)) break; } if (l == NULL) cockpit_web_response_complete (response); out: g_list_free_full (output, (GDestroyNotify)g_bytes_unref); if (headers) g_hash_table_unref (headers); g_free (login_html); if (body) g_bytes_unref (body); if (file) g_mapped_file_unref (file); }
void cockpit_package_expand (GHashTable *listing, const gchar *host, GBytes *input, GQueue *output) { ExpandInfo expand = { listing, host }; GList *blocks; GList *l; gsize size; gsize length; gsize offset; if (is_binary_data (input)) { /* If binary data, no variable expansion takes place */ blocks = g_list_prepend (NULL, g_bytes_ref (input)); } else { /* Expand all variables */ blocks = cockpit_template_expand (input, expand_variables, &expand); } /* Also break data into blocks */ for (l = blocks; l != NULL; l = g_list_next (l)) { size = g_bytes_get_size (l->data); if (size < 8192) { g_queue_push_tail (output, l->data); } else { for (offset = 0; offset < size; offset += 4096) { length = MIN (4096, size - offset); g_queue_push_tail (output, g_bytes_new_from_bytes (l->data, offset, length)); } g_bytes_unref (l->data); } } g_list_free (blocks); }
static void add_dynamic_args_to_array (gchar ***key, gchar **config_args, JsonObject *options) { GPtrArray *arr = NULL; gint length; gint i; g_assert (config_args != NULL); g_assert (key != NULL); arr = g_ptr_array_new (); length = g_strv_length (config_args); for (i = 0; i < length; i++) { GString *s = g_string_new (""); GBytes *input = g_bytes_new_static (config_args[i], strlen(config_args[i]) + 1); GList *output = cockpit_template_expand (input, substitute_json_string, "${", "}", options); GList *l; for (l = output; l != NULL; l = g_list_next (l)) { gsize size; gconstpointer data = g_bytes_get_data (l->data, &size); g_string_append_len (s, data, size); } g_ptr_array_add (arr, g_string_free (s, FALSE)); g_bytes_unref (input); g_list_free_full (output, (GDestroyNotify) g_bytes_unref); } g_ptr_array_add (arr, NULL); *key = (gchar **)g_ptr_array_free (arr, FALSE); }
/** * cockpit_web_response_error: * @self: the response * @status: the HTTP status code * @headers: headers to include or NULL * @format: printf format of error message * * Send an error message with a basic HTML page containing * the error. */ void cockpit_web_response_error (CockpitWebResponse *self, guint code, GHashTable *headers, const gchar *format, ...) { va_list var_args; gchar *reason = NULL; const gchar *message; GBytes *input = NULL; GList *output, *l; GError *error = NULL; g_return_if_fail (COCKPIT_IS_WEB_RESPONSE (self)); if (format) { va_start (var_args, format); reason = g_strdup_vprintf (format, var_args); va_end (var_args); message = reason; } else { switch (code) { case 400: message = "Bad request"; break; case 401: message = "Not Authorized"; break; case 403: message = "Forbidden"; break; case 404: message = "Not Found"; break; case 405: message = "Method Not Allowed"; break; case 413: message = "Request Entity Too Large"; break; case 502: message = "Remote Page is Unavailable"; break; case 500: message = "Internal Server Error"; break; default: if (code < 100) reason = g_strdup_printf ("%u Continue", code); else if (code < 200) reason = g_strdup_printf ("%u OK", code); else if (code < 300) reason = g_strdup_printf ("%u Moved", code); else reason = g_strdup_printf ("%u Failed", code); message = reason; break; } } g_debug ("%s: returning error: %u %s", self->logname, code, message); if (cockpit_web_failure_resource) { input = g_resources_lookup_data (cockpit_web_failure_resource, G_RESOURCE_LOOKUP_FLAGS_NONE, &error); if (input == NULL) { g_critical ("couldn't load: %s: %s", cockpit_web_failure_resource, error->message); g_error_free (error); } } if (!input) input = g_bytes_new_static (default_failure_template, strlen (default_failure_template)); if (headers) { if (!g_hash_table_lookup (headers, "Content-Type")) g_hash_table_replace (headers, g_strdup ("Content-Type"), g_strdup ("text/html; charset=utf8")); cockpit_web_response_headers_full (self, code, message, -1, headers); } else { cockpit_web_response_headers (self, code, message, -1, "Content-Type", "text/html; charset=utf8", NULL); } output = cockpit_template_expand (input, substitute_message, (gpointer)message); g_bytes_unref (input); for (l = output; l != NULL; l = g_list_next (l)) { if (!cockpit_web_response_queue (self, l->data)) break; } if (l == NULL) cockpit_web_response_complete (self); g_list_free_full (output, (GDestroyNotify)g_bytes_unref); g_free (reason); }
static gboolean package_checksum_file (GChecksum *checksum, GHashTable *depends, const gchar *root, const gchar *filename) { gchar *path = NULL; const gchar *string; GError *error = NULL; GChecksum *inner = NULL; GMappedFile *mapped = NULL; gboolean ret = FALSE; GList *output = NULL; GBytes *bytes; GList *l; if (!validate_path (filename)) { g_warning ("package has an invalid path name: %s", filename); goto out; } path = g_build_filename (root, filename, NULL); if (g_file_test (path, G_FILE_TEST_IS_DIR)) { ret = package_checksum_directory (checksum, depends, root, filename); goto out; } mapped = g_mapped_file_new (path, FALSE, &error); if (error) { g_warning ("couldn't open file: %s: %s", path, error->message); g_error_free (error); goto out; } bytes = g_mapped_file_get_bytes (mapped); output = cockpit_template_expand (bytes, gather_depends, depends); g_bytes_unref (bytes); inner = g_checksum_new (G_CHECKSUM_SHA1); for (l = output; l != NULL; l = g_list_next (l)) { g_checksum_update (inner, g_bytes_get_data (l->data, NULL), g_bytes_get_size (l->data)); } string = g_checksum_get_string (inner); /* * Place file name and hex checksum into checksum, * include the null terminators so these values * cannot be accidentally have a boundary discrepancy. */ g_checksum_update (checksum, (const guchar *)filename, strlen (filename) + 1); g_checksum_update (checksum, (const guchar *)string, strlen (string) + 1); ret = TRUE; out: g_list_free_full (output, (GDestroyNotify)g_bytes_unref); g_checksum_free (inner); if (mapped) g_mapped_file_unref (mapped); g_free (path); return ret; }