/* * This function will be called when our CGI is accessed. */ static void request_handler(const gchar *path, const gchar *method, const gchar *query, GHashTable *params, GOutputStream *output_stream, gpointer user_data) { GDataOutputStream *dos; guint *timer = (guint*) user_data; gchar msg[128]; dos = g_data_output_stream_new(output_stream); /* Send out the HTTP response status code */ g_data_output_stream_put_string(dos,"Content-Type: text/plain\r\n", NULL, NULL); g_data_output_stream_put_string(dos,"Status: 200 OK\r\n\r\n", NULL, NULL); /* Our custom message */ g_snprintf(msg, sizeof(msg),"You have accessed '%s'\n", path ? path:"(NULL)"); g_data_output_stream_put_string(dos, msg, NULL, NULL); g_snprintf(msg, sizeof(msg), "\n%s() [%s:%d] \n\n" "- Hello World! -\n" "I've been running for %d seconds\n", __FUNCTION__, __FILE__, __LINE__, *timer ); g_data_output_stream_put_string(dos, msg, NULL, NULL); g_object_unref(dos); }
static void gspeechd_client_read_speak_data_cb (GInputStream *stream, GAsyncResult *res, gpointer user_data) { GSpeechdClient *client = user_data; gchar *s, *response; gsize len; SsipStatus status; gboolean ret; GError *error = NULL; s = g_data_input_stream_read_line_finish (G_DATA_INPUT_STREAM(stream), res, &len, &error); g_printf ("--->%s\n",s); #define END_SPEAK_DATA_STR ".\xD" #define END_SPEAK_DATA_RESPONSE "225-1\r\n" if (g_strcmp0 (s, END_SPEAK_DATA_STR) != 0) { g_data_input_stream_read_line_async(client->input, G_PRIORITY_DEFAULT, client->cancellable, (GAsyncReadyCallback)gspeechd_client_read_speak_data_cb, gspeechd_client_ref (client)); return; } ret = g_data_output_stream_put_string (client->output, END_SPEAK_DATA_RESPONSE, client->cancellable, NULL); g_printf ("%d %s\n", ret, END_SPEAK_DATA_RESPONSE); status = OK_MESSAGE_QUEUED; response = ssip_response (status); ret = g_data_output_stream_put_string (client->output, response, client->cancellable, NULL); g_printf ("%d %s\n", ret, response); /* parse commands again */ g_data_input_stream_read_line_async(client->input, G_PRIORITY_DEFAULT, client->cancellable, (GAsyncReadyCallback)gspeechd_client_read_line_cb, gspeechd_client_ref (client)); }
static gboolean _j4status_io_stream_put_string(J4statusIOStream *self, const gchar *string) { if ( string == NULL ) return TRUE; if ( self->out == NULL ) return FALSE; GError *error = NULL; if ( g_data_output_stream_put_string(self->out, string, NULL, &error) ) return TRUE; /* * We do not output on broken pipe * because this is what we get on disconnect. * Too frequent to warrant a warning. */ if ( ! g_error_matches(error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE) ) g_warning("Couldn't write line: %s", error->message); g_clear_error(&error); _j4status_io_stream_reconnect_maybe(self); return FALSE; }
static gboolean write_escaped (GDataOutputStream *stream, const char *str, GError **error) { gboolean ret; char *quoted = g_markup_escape_text (str, -1); ret = g_data_output_stream_put_string (stream, quoted, NULL, error); g_free (quoted); return ret; }
static VALUE stream_put_string(int argc, VALUE *argv, VALUE self) { VALUE value, cancellable; GError *error = NULL; rb_scan_args(argc, argv, "11", &value, &cancellable); if (!g_data_output_stream_put_string(_SELF(self), RVAL2CSTR(value), RVAL2GCANCELLABLE(cancellable), &error)) rbgio_raise_io_error(error); return self; }
static void disabled_repos_free (GHashTable *disabled) { GHashTableIter iter; GFile *file; GFileOutputStream *file_stream; GDataOutputStream *data_stream; const gchar *line = PACMAN_REPO_LIST_HEADER "\n"; g_return_if_fail (disabled != NULL); g_debug ("pacman: storing disabled repos in %s", PACMAN_REPO_LIST); file = g_file_new_for_path (PACMAN_REPO_LIST); file_stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL); if (file_stream == NULL) { g_object_unref (file); g_hash_table_unref (disabled); return; } g_hash_table_iter_init (&iter, disabled); data_stream = g_data_output_stream_new (G_OUTPUT_STREAM (file_stream)); /* write header, then all disabled repos line by line */ if (g_data_output_stream_put_string (data_stream, line, NULL, NULL)) { while (g_hash_table_iter_next (&iter, (gpointer *) &line, NULL) && g_data_output_stream_put_string (data_stream, line, NULL, NULL) && g_data_output_stream_put_string (data_stream, "\n", NULL, NULL)); } g_object_unref (data_stream); g_object_unref (file_stream); g_object_unref (file); g_hash_table_unref (disabled); }
static VALUE put_value(int argc, VALUE *argv, VALUE self) { VALUE value, cancellable; gboolean success; GError *error = NULL; rb_scan_args(argc, argv, "11", &value, &cancellable); /* TODO: How do we convert from a Number to uint64 through byte in a * reliable manner? Is it even sane to do so? */ switch (TYPE(value)) { case T_STRING: success = g_data_output_stream_put_string(_SELF(self), RVAL2CSTR(value), cancellable, &error); break; if (!success) rbgio_raise_io_error(error); return self; } #endif void Init_gdataoutputstream(VALUE glib) { VALUE dataoutputstream = G_DEF_CLASS(G_TYPE_DATA_OUTPUT_STREAM, "DataOutputStream", glib); rb_define_method(dataoutputstream, "initialize", stream_initialize, -1); rb_define_method(dataoutputstream, "byte_order", stream_byte_order, 0); rb_define_method(dataoutputstream, "set_byte_order", stream_set_byte_order, 1); G_DEF_SETTER(dataoutputstream, "byte_order"); rb_define_method(dataoutputstream, "put_byte", stream_put_byte, -1); rb_define_method(dataoutputstream, "put_int16", stream_put_int16, -1); rb_define_method(dataoutputstream, "put_uint16", stream_put_uint16, -1); rb_define_method(dataoutputstream, "put_int32", stream_put_int32, -1); rb_define_method(dataoutputstream, "put_uint32", stream_put_uint32, -1); rb_define_method(dataoutputstream, "put_int64", stream_put_int64, -1); rb_define_method(dataoutputstream, "put_uint64", stream_put_uint64, -1); rb_define_method(dataoutputstream, "put_string", stream_put_string, -1); rb_define_alias(dataoutputstream, "<<", "put_string"); rb_define_alias(dataoutputstream, "write", "put_string"); /* TODO: Should we add #put_value/#put? */ }
static gboolean write_attribute_string (GDataOutputStream *stream, const char *elt_name, const char *str, GError **error) { gboolean ret = FALSE; char *elt; elt = g_strdup_printf (" %s=\"", elt_name); ret = g_data_output_stream_put_string (stream, elt, NULL, error); g_free (elt); if (!ret) goto out; ret = write_escaped (stream, str, error); if (!ret) goto out; ret = g_data_output_stream_put_string (stream, "\"", NULL, error); out: return ret; }
static void put_string (GDataOutputStream *out, const char *str) { gsize len; len = strlen (str); if (len > G_MAXUINT16) { g_warning ("GFileInfo string to large, (%d bytes)\n", (int)len); len = 0; str = ""; } g_data_output_stream_put_uint16 (out, len, NULL, NULL); g_data_output_stream_put_string (out, str, NULL, NULL); }
static void disabled_repos_free (GHashTable *table) { GHashTableIter iter; GFile *file; GFileOutputStream *os; GDataOutputStream *output; const gchar *line; g_return_if_fail (table != NULL); g_debug ("storing disabled repos in %s", PK_BACKEND_REPO_FILE); file = g_file_new_for_path (PK_BACKEND_REPO_FILE); os = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL); if (os == NULL) { g_object_unref (file); g_hash_table_unref (table); return; } g_hash_table_iter_init (&iter, table); output = g_data_output_stream_new (G_OUTPUT_STREAM (os)); /* write all disabled repos line by line */ while (g_hash_table_iter_next (&iter, (gpointer *) &line, NULL) && g_data_output_stream_put_string (output, line, NULL, NULL) && g_data_output_stream_put_byte (output, '\n', NULL, NULL)); g_object_unref (output); g_object_unref (os); g_object_unref (file); g_hash_table_unref (table); }
static gboolean test_client_do (TestClient *client, GError **error, ...) { GString *command = g_string_new (NULL); char *line = NULL; va_list vap; va_start (vap, error); while (TRUE) { char *word = va_arg (vap, char *); if (word == NULL) break; if (command->len > 0) g_string_append_c (command, ' '); char *quoted = g_shell_quote (word); g_string_append (command, quoted); g_free (quoted); } va_end (vap); g_string_append_c (command, '\n'); if (!g_data_output_stream_put_string (client->in, command->str, client->cancellable, error)) goto out; g_data_input_stream_read_line_async (client->out, G_PRIORITY_DEFAULT, client->cancellable, test_client_line_read, client); client->error = error; g_main_loop_run (client->loop); line = client->line; client->line = NULL; client->error = NULL; if (!line) { if (*error == NULL) g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_RUNTIME_ERROR, "test client exited"); goto out; } if (strcmp (line, "OK") != 0) { g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_RUNTIME_ERROR, "%s", line); goto out; } out: g_string_free (command, TRUE); g_free (line); return *error == NULL; }
static void _j4status_core_debug_log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { GDataOutputStream *stream = user_data; g_log_default_handler(log_domain, log_level, message, NULL); const gchar *prg_name; gchar pid[128]; prg_name = g_get_prgname(); g_sprintf(pid, "%lu", (gulong) getpid()); g_data_output_stream_put_string(stream, "(", NULL, NULL); if ( prg_name != NULL ) { g_data_output_stream_put_string(stream, prg_name, NULL, NULL); g_data_output_stream_put_string(stream, ":", NULL, NULL); } else g_data_output_stream_put_string(stream, "process:", NULL, NULL); g_data_output_stream_put_string(stream, pid, NULL, NULL); g_data_output_stream_put_string(stream, ") ", NULL, NULL); const gchar *log_level_message = ""; switch ( log_level & G_LOG_LEVEL_MASK ) { case G_LOG_LEVEL_ERROR: log_level_message = "ERROR"; break; case G_LOG_LEVEL_CRITICAL: log_level_message = "CRITICAL"; break; case G_LOG_LEVEL_WARNING: log_level_message = "WARNING"; break; case G_LOG_LEVEL_MESSAGE: log_level_message = "MESSAGE"; break; case G_LOG_LEVEL_INFO: log_level_message = "INFO"; break; case G_LOG_LEVEL_DEBUG: log_level_message = "DEBUG"; break; } g_data_output_stream_put_string(stream, log_level_message, NULL, NULL); if ( log_domain != NULL ) { g_data_output_stream_put_string(stream, " [", NULL, NULL); g_data_output_stream_put_string(stream, log_domain, NULL, NULL); g_data_output_stream_put_string(stream, "]", NULL, NULL); } g_data_output_stream_put_string(stream, ": ", NULL, NULL); g_data_output_stream_put_string(stream, message, NULL, NULL); g_data_output_stream_put_byte(stream, '\n', NULL, NULL); }
static gboolean goa_smtp_auth_starttls_sync (GoaMailAuth *auth, GCancellable *cancellable, GError **error) { GoaSmtpAuth *self = GOA_SMTP_AUTH (auth); GDataInputStream *input; GDataOutputStream *output; gboolean ret; gboolean starttls_supported; gchar *domain; gchar *request; gchar *response; starttls_supported = FALSE; domain = NULL; request = NULL; response = NULL; ret = FALSE; domain = smtp_auth_get_domain (self, error); if (domain == NULL) goto out; input = goa_mail_auth_get_input (auth); output = goa_mail_auth_get_output (auth); /* Check the greeting */ if (!smtp_auth_check_greeting (input, cancellable, error)) goto out; /* Send EHLO */ request = g_strdup_printf ("EHLO %s\r\n", domain); g_debug ("> %s", request); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); /* Check if STARTTLS is supported or not */ ehlo_again: response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_421 (response, error)) goto out; if (smtp_auth_check_not_250 (response, error)) goto out; if (g_str_has_prefix (response + 4, "STARTTLS")) starttls_supported = TRUE; if (response[3] == '-') { g_free (response); goto ehlo_again; } else if (!starttls_supported) { g_set_error (error, GOA_ERROR, GOA_ERROR_NOT_SUPPORTED, _("Server does not support STARTTLS")); goto out; } g_clear_pointer (&response, g_free); /* Send STARTTLS */ request = g_strdup ("STARTTLS\r\n"); g_debug ("> %s", request); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_454 (response, error)) goto out; if (smtp_auth_check_not_220 (response, error)) goto out; g_clear_pointer (&response, g_free); /* There won't be a greeting after this */ self->greeting_absent = TRUE; ret = TRUE; out: g_free (domain); g_free (response); g_free (request); return ret; }
static gboolean goa_smtp_auth_run_sync (GoaMailAuth *auth, GCancellable *cancellable, GError **error) { GoaSmtpAuth *self = GOA_SMTP_AUTH (auth); GDataInputStream *input; GDataOutputStream *output; gboolean ret; gchar *auth_arg_base64; gchar *auth_arg_plain; gchar *domain; gchar *password; gchar *request; gchar *response; gsize auth_arg_plain_len; auth_arg_base64 = NULL; auth_arg_plain = NULL; domain = NULL; password = NULL; request = NULL; response = NULL; ret = FALSE; password = smtp_auth_get_password (self, cancellable, error); if (password == NULL) goto out; domain = smtp_auth_get_domain (self, error); if (domain == NULL) goto out; input = goa_mail_auth_get_input (auth); output = goa_mail_auth_get_output (auth); /* Check the greeting, if there is one */ if (!self->greeting_absent) { if (!smtp_auth_check_greeting (input, cancellable, error)) goto out; } /* Send EHLO */ request = g_strdup_printf ("EHLO %s\r\n", domain); g_debug ("> %s", request); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); /* Check which SASL mechanisms are supported */ ehlo_again: response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_421 (response, error)) goto out; if (smtp_auth_check_not_250 (response, error)) goto out; if (g_str_has_prefix (response + 4, "AUTH")) { self->auth_supported = TRUE; if (strstr (response, "PLAIN") != NULL) self->plain_supported = TRUE; else if (strstr (response, "LOGIN") != NULL) self->login_supported = TRUE; } if (response[3] == '-') { g_free (response); goto ehlo_again; } else if (!self->auth_supported) { ret = TRUE; goto out; } else if (!self->login_supported && !self->plain_supported) { g_set_error (error, GOA_ERROR, GOA_ERROR_NOT_SUPPORTED, _("Unknown authentication mechanism")); goto out; } g_clear_pointer (&response, g_free); /* Try different SASL mechanisms */ if (self->plain_supported) { /* AUTH PLAIN */ auth_arg_plain = g_strdup_printf ("%s%c%s%c%s", self->username, '\0', self->username, '\0', password); auth_arg_plain_len = 2 * strlen (self->username) + 2 + strlen (password); auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len); request = g_strdup_printf ("AUTH PLAIN %s\r\n", auth_arg_base64); g_debug ("> AUTH PLAIN ********************"); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); } else { /* AUTH LOGIN */ auth_arg_plain = g_strdup (self->username); auth_arg_plain_len = strlen (self->username); auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len); request = g_strdup_printf ("AUTH LOGIN %s\r\n", auth_arg_base64); g_debug ("> AUTH LOGIN ********************"); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_not_334_login_password (response, error)) goto out; g_free (auth_arg_plain); g_free (auth_arg_base64); auth_arg_plain = g_strdup (password); auth_arg_plain_len = strlen (password); auth_arg_base64 = g_base64_encode ((guchar *) auth_arg_plain, auth_arg_plain_len); request = g_strdup_printf ("%s\r\n", auth_arg_base64); g_debug ("> ********************"); if (!g_data_output_stream_put_string (output, request, cancellable, error)) goto out; g_clear_pointer (&request, g_free); } response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error); if (response == NULL) goto out; g_debug ("< %s", response); if (smtp_auth_check_not_235 (response, error)) goto out; g_clear_pointer (&response, g_free); ret = TRUE; out: g_free (auth_arg_base64); g_free (auth_arg_plain); g_free (domain); g_free (password); g_free (response); g_free (request); return ret; }
gchar * _g_dbus_auth_run_client (GDBusAuth *auth, GDBusCapabilityFlags offered_capabilities, GDBusCapabilityFlags *out_negotiated_capabilities, GCancellable *cancellable, GError **error) { gchar *s; GDataInputStream *dis; GDataOutputStream *dos; GCredentials *credentials; gchar *ret_guid; gchar *line; gsize line_length; gchar **supported_auth_mechs; GPtrArray *attempted_auth_mechs; GDBusAuthMechanism *mech; ClientState state; GDBusCapabilityFlags negotiated_capabilities; debug_print ("CLIENT: initiating"); ret_guid = NULL; supported_auth_mechs = NULL; attempted_auth_mechs = g_ptr_array_new (); mech = NULL; negotiated_capabilities = 0; credentials = NULL; dis = G_DATA_INPUT_STREAM (g_data_input_stream_new (g_io_stream_get_input_stream (auth->priv->stream))); dos = G_DATA_OUTPUT_STREAM (g_data_output_stream_new (g_io_stream_get_output_stream (auth->priv->stream))); g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (dis), FALSE); g_filter_output_stream_set_close_base_stream (G_FILTER_OUTPUT_STREAM (dos), FALSE); g_data_input_stream_set_newline_type (dis, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); #ifdef G_OS_UNIX if (G_IS_UNIX_CONNECTION (auth->priv->stream) && g_unix_credentials_message_is_supported ()) { credentials = g_credentials_new (); if (!g_unix_connection_send_credentials (G_UNIX_CONNECTION (auth->priv->stream), cancellable, error)) goto out; } else { if (!g_data_output_stream_put_byte (dos, '\0', cancellable, error)) goto out; } #else if (!g_data_output_stream_put_byte (dos, '\0', cancellable, error)) goto out; #endif if (credentials != NULL) { if (G_UNLIKELY (_g_dbus_debug_authentication ())) { s = g_credentials_to_string (credentials); debug_print ("CLIENT: sent credentials `%s'", s); g_free (s); } } else { debug_print ("CLIENT: didn't send any credentials"); } /* TODO: to reduce roundtrips, try to pick an auth mechanism to start with */ /* Get list of supported authentication mechanisms */ s = "AUTH\r\n"; debug_print ("CLIENT: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) goto out; state = CLIENT_STATE_WAITING_FOR_REJECT; while (TRUE) { switch (state) { case CLIENT_STATE_WAITING_FOR_REJECT: debug_print ("CLIENT: WaitingForReject"); line = _my_g_data_input_stream_read_line (dis, &line_length, cancellable, error); if (line == NULL) goto out; debug_print ("CLIENT: WaitingForReject, read '%s'", line); foobar: if (!g_str_has_prefix (line, "REJECTED ")) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "In WaitingForReject: Expected `REJECTED am1 am2 ... amN', got `%s'", line); g_free (line); goto out; } if (supported_auth_mechs == NULL) { supported_auth_mechs = g_strsplit (line + sizeof ("REJECTED ") - 1, " ", 0); #if 0 for (n = 0; supported_auth_mechs != NULL && supported_auth_mechs[n] != NULL; n++) g_printerr ("supported_auth_mechs[%d] = `%s'\n", n, supported_auth_mechs[n]); #endif } g_free (line); mech = client_choose_mech_and_send_initial_response (auth, credentials, (const gchar* const *) supported_auth_mechs, attempted_auth_mechs, dos, cancellable, error); if (mech == NULL) goto out; if (_g_dbus_auth_mechanism_client_get_state (mech) == G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA) state = CLIENT_STATE_WAITING_FOR_DATA; else state = CLIENT_STATE_WAITING_FOR_OK; break; case CLIENT_STATE_WAITING_FOR_OK: debug_print ("CLIENT: WaitingForOK"); line = _my_g_data_input_stream_read_line (dis, &line_length, cancellable, error); if (line == NULL) goto out; debug_print ("CLIENT: WaitingForOK, read `%s'", line); if (g_str_has_prefix (line, "OK ")) { if (!g_dbus_is_guid (line + 3)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid OK response `%s'", line); g_free (line); goto out; } ret_guid = g_strdup (line + 3); g_free (line); if (offered_capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING) { s = "NEGOTIATE_UNIX_FD\r\n"; debug_print ("CLIENT: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) goto out; state = CLIENT_STATE_WAITING_FOR_AGREE_UNIX_FD; } else { s = "BEGIN\r\n"; debug_print ("CLIENT: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) goto out; /* and we're done! */ goto out; } } else if (g_str_has_prefix (line, "REJECTED ")) { goto foobar; } else { /* TODO: handle other valid responses */ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "In WaitingForOk: unexpected response `%s'", line); g_free (line); goto out; } break; case CLIENT_STATE_WAITING_FOR_AGREE_UNIX_FD: debug_print ("CLIENT: WaitingForAgreeUnixFD"); line = _my_g_data_input_stream_read_line (dis, &line_length, cancellable, error); if (line == NULL) goto out; debug_print ("CLIENT: WaitingForAgreeUnixFD, read=`%s'", line); if (g_strcmp0 (line, "AGREE_UNIX_FD") == 0) { g_free (line); negotiated_capabilities |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING; s = "BEGIN\r\n"; debug_print ("CLIENT: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) goto out; /* and we're done! */ goto out; } else if (g_str_has_prefix (line, "ERROR") && (line[5] == 0 || g_ascii_isspace (line[5]))) { //g_strstrip (line + 5); g_debug ("bah, no unix_fd: `%s'", line + 5); g_free (line); s = "BEGIN\r\n"; debug_print ("CLIENT: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) goto out; /* and we're done! */ goto out; } else { /* TODO: handle other valid responses */ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "In WaitingForAgreeUnixFd: unexpected response `%s'", line); g_free (line); goto out; } break; case CLIENT_STATE_WAITING_FOR_DATA: debug_print ("CLIENT: WaitingForData"); line = _my_g_data_input_stream_read_line (dis, &line_length, cancellable, error); if (line == NULL) goto out; debug_print ("CLIENT: WaitingForData, read=`%s'", line); if (g_str_has_prefix (line, "DATA ")) { gchar *encoded; gchar *decoded_data; gsize decoded_data_len; encoded = g_strdup (line + 5); g_free (line); g_strstrip (encoded); decoded_data = hexdecode (encoded, &decoded_data_len, error); g_free (encoded); if (decoded_data == NULL) { g_prefix_error (error, "DATA response is malformed: "); /* invalid encoding, disconnect! */ goto out; } _g_dbus_auth_mechanism_client_data_receive (mech, decoded_data, decoded_data_len); g_free (decoded_data); if (_g_dbus_auth_mechanism_client_get_state (mech) == G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND) { gchar *data; gsize data_len; gchar *encoded_data; data = _g_dbus_auth_mechanism_client_data_send (mech, &data_len); encoded_data = hexencode (data); s = g_strdup_printf ("DATA %s\r\n", encoded_data); g_free (encoded_data); g_free (data); debug_print ("CLIENT: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) { g_free (s); goto out; } g_free (s); } state = CLIENT_STATE_WAITING_FOR_OK; } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "In WaitingForData: unexpected response `%s'", line); g_free (line); goto out; } break; default: g_assert_not_reached (); break; } }; /* main authentication client loop */ out: if (mech != NULL) g_object_unref (mech); g_ptr_array_unref (attempted_auth_mechs); g_strfreev (supported_auth_mechs); g_object_unref (dis); g_object_unref (dos); /* ensure return value is NULL if error is set */ if (error != NULL && *error != NULL) { g_free (ret_guid); ret_guid = NULL; } if (ret_guid != NULL) { if (out_negotiated_capabilities != NULL) *out_negotiated_capabilities = negotiated_capabilities; } if (credentials != NULL) g_object_unref (credentials); debug_print ("CLIENT: Done, authenticated=%d", ret_guid != NULL); return ret_guid; }
static void gspeechd_client_read_line_cb (GInputStream *stream, GAsyncResult *res, gpointer user_data) { GSpeechdClient *client = user_data; gchar *s, *response; gsize len; gboolean ret; GError *error = NULL; SsipCommand *cmd; SsipStatus status; /* read lines and removes newline */ s = g_data_input_stream_read_line_finish (G_DATA_INPUT_STREAM(stream), res, &len, &error); if (error != NULL ) { g_printf ("-->%s\n", error->message); g_error_free (error); return; } if (s == NULL) { /* client has closed a connection */ g_printf ("-->connection closed\n"); return; } g_printf ("-->%s\n", s); /* parse SSIP command */ cmd = ssip_command_new (s); /* TODO remove history */ client->history = g_list_append (client->history, s); /* process command */ switch (ssip_cmd_get (cmd)) { case SSIP_CMD_SET: switch (ssip_set_param_get (cmd)) { case SSIP_SET_PARAM_CLIENT_NAME: /* TODO free previous name before */ client->name = g_strdup (ssip_set_param_value_get (cmd)); /* TODO emit event to the server */ status = OK_CLIENT_NAME_SET; break; case SSIP_SET_PARAM_PRIORITY: status = OK_PRIORITY_SET; break; default: break; } break; case SSIP_CMD_SPEAK: status = OK_RECEIVE_DATA; response = ssip_response (status); ret = g_data_output_stream_put_string (client->output, response, client->cancellable, NULL); g_printf ("%d %s\n", ret, response); g_data_input_stream_read_line_async(client->input, G_PRIORITY_DEFAULT, client->cancellable, (GAsyncReadyCallback)gspeechd_client_read_speak_data_cb, gspeechd_client_ref (client)); return; case SSIP_CMD_HELP: default: break; } response = ssip_response (status); ret = g_data_output_stream_put_string (client->output, response, client->cancellable, NULL); g_printf ("%d %s\n", ret, response); /* when QUIT received, send an event connection_closed */ g_data_input_stream_read_line_async(client->input, G_PRIORITY_DEFAULT, client->cancellable, (GAsyncReadyCallback)gspeechd_client_read_line_cb, gspeechd_client_ref (client)); }
gboolean _g_dbus_auth_run_server (GDBusAuth *auth, GDBusAuthObserver *observer, const gchar *guid, gboolean allow_anonymous, GDBusCapabilityFlags offered_capabilities, GDBusCapabilityFlags *out_negotiated_capabilities, GCredentials **out_received_credentials, GCancellable *cancellable, GError **error) { gboolean ret; ServerState state; GDataInputStream *dis; GDataOutputStream *dos; GError *local_error; guchar byte; gchar *line; gsize line_length; GDBusAuthMechanism *mech; gchar *s; GDBusCapabilityFlags negotiated_capabilities; GCredentials *credentials; debug_print ("SERVER: initiating"); ret = FALSE; dis = NULL; dos = NULL; mech = NULL; negotiated_capabilities = 0; credentials = NULL; if (!g_dbus_is_guid (guid)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "The given guid `%s' is not valid", guid); goto out; } dis = G_DATA_INPUT_STREAM (g_data_input_stream_new (g_io_stream_get_input_stream (auth->priv->stream))); dos = G_DATA_OUTPUT_STREAM (g_data_output_stream_new (g_io_stream_get_output_stream (auth->priv->stream))); g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (dis), FALSE); g_filter_output_stream_set_close_base_stream (G_FILTER_OUTPUT_STREAM (dos), FALSE); g_data_input_stream_set_newline_type (dis, G_DATA_STREAM_NEWLINE_TYPE_CR_LF); /* first read the NUL-byte (TODO: read credentials if using a unix domain socket) */ #ifdef G_OS_UNIX if (G_IS_UNIX_CONNECTION (auth->priv->stream) && g_unix_credentials_message_is_supported ()) { local_error = NULL; credentials = g_unix_connection_receive_credentials (G_UNIX_CONNECTION (auth->priv->stream), cancellable, &local_error); if (credentials == NULL) { g_propagate_error (error, local_error); goto out; } } else { local_error = NULL; byte = g_data_input_stream_read_byte (dis, cancellable, &local_error); if (local_error != NULL) { g_propagate_error (error, local_error); goto out; } } #else local_error = NULL; byte = g_data_input_stream_read_byte (dis, cancellable, &local_error); if (local_error != NULL) { g_propagate_error (error, local_error); goto out; } #endif if (credentials != NULL) { if (G_UNLIKELY (_g_dbus_debug_authentication ())) { s = g_credentials_to_string (credentials); debug_print ("SERVER: received credentials `%s'", s); g_free (s); } } else { debug_print ("SERVER: didn't receive any credentials"); } state = SERVER_STATE_WAITING_FOR_AUTH; while (TRUE) { switch (state) { case SERVER_STATE_WAITING_FOR_AUTH: debug_print ("SERVER: WaitingForAuth"); line = _my_g_data_input_stream_read_line (dis, &line_length, cancellable, error); debug_print ("SERVER: WaitingForAuth, read `%s'", line); if (line == NULL) goto out; if (g_strcmp0 (line, "AUTH") == 0) { s = get_auth_mechanisms (auth, allow_anonymous, "REJECTED ", "\r\n", " "); debug_print ("SERVER: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) { g_free (s); goto out; } g_free (s); g_free (line); } else if (g_str_has_prefix (line, "AUTH ")) { gchar **tokens; const gchar *encoded; const gchar *mech_name; GType auth_mech_to_use_gtype; tokens = g_strsplit (line, " ", 0); g_free (line); switch (g_strv_length (tokens)) { case 2: /* no initial response */ mech_name = tokens[1]; encoded = NULL; break; case 3: /* initial response */ mech_name = tokens[1]; encoded = tokens[2]; break; default: g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unexpected line `%s' while in WaitingForAuth state", line); g_strfreev (tokens); goto out; } /* TODO: record that the client has attempted to use this mechanism */ //g_debug ("client is trying `%s'", mech_name); auth_mech_to_use_gtype = find_mech_by_name (auth, mech_name); if ((auth_mech_to_use_gtype == (GType) 0) || (!allow_anonymous && g_strcmp0 (mech_name, "ANONYMOUS") == 0)) { /* We don't support this auth mechanism */ g_strfreev (tokens); s = get_auth_mechanisms (auth, allow_anonymous, "REJECTED ", "\r\n", " "); debug_print ("SERVER: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) { g_free (s); goto out; } g_free (s); /* stay in WAITING FOR AUTH */ state = SERVER_STATE_WAITING_FOR_AUTH; } else { gchar *initial_response; gsize initial_response_len; mech = g_object_new (auth_mech_to_use_gtype, "stream", auth->priv->stream, "credentials", credentials, NULL); initial_response = NULL; initial_response_len = 0; if (encoded != NULL) { initial_response = hexdecode (encoded, &initial_response_len, error); if (initial_response == NULL) { g_prefix_error (error, "Initial response is malformed: "); /* invalid encoding, disconnect! */ g_strfreev (tokens); goto out; } } _g_dbus_auth_mechanism_server_initiate (mech, initial_response, initial_response_len); g_free (initial_response); g_strfreev (tokens); change_state: switch (_g_dbus_auth_mechanism_server_get_state (mech)) { case G_DBUS_AUTH_MECHANISM_STATE_ACCEPTED: if (observer != NULL && !g_dbus_auth_observer_authorize_authenticated_peer (observer, auth->priv->stream, credentials)) { /* disconnect */ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cancelled via GDBusAuthObserver::authorize-authenticated-peer")); goto out; } else { s = g_strdup_printf ("OK %s\r\n", guid); debug_print ("SERVER: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) { g_free (s); goto out; } g_free (s); state = SERVER_STATE_WAITING_FOR_BEGIN; } break; case G_DBUS_AUTH_MECHANISM_STATE_REJECTED: s = get_auth_mechanisms (auth, allow_anonymous, "REJECTED ", "\r\n", " "); debug_print ("SERVER: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) { g_free (s); goto out; } g_free (s); state = SERVER_STATE_WAITING_FOR_AUTH; break; case G_DBUS_AUTH_MECHANISM_STATE_WAITING_FOR_DATA: state = SERVER_STATE_WAITING_FOR_DATA; break; case G_DBUS_AUTH_MECHANISM_STATE_HAVE_DATA_TO_SEND: { gchar *data; gsize data_len; gchar *encoded_data; data = _g_dbus_auth_mechanism_server_data_send (mech, &data_len); encoded_data = hexencode (data); s = g_strdup_printf ("DATA %s\r\n", encoded_data); g_free (encoded_data); g_free (data); debug_print ("SERVER: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) { g_free (s); goto out; } g_free (s); } goto change_state; break; default: /* TODO */ g_assert_not_reached (); break; } } } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unexpected line `%s' while in WaitingForAuth state", line); g_free (line); goto out; } break; case SERVER_STATE_WAITING_FOR_DATA: debug_print ("SERVER: WaitingForData"); line = _my_g_data_input_stream_read_line (dis, &line_length, cancellable, error); debug_print ("SERVER: WaitingForData, read `%s'", line); if (line == NULL) goto out; if (g_str_has_prefix (line, "DATA ")) { gchar *encoded; gchar *decoded_data; gsize decoded_data_len; encoded = g_strdup (line + 5); g_free (line); g_strstrip (encoded); decoded_data = hexdecode (encoded, &decoded_data_len, error); g_free (encoded); if (decoded_data == NULL) { g_prefix_error (error, "DATA response is malformed: "); /* invalid encoding, disconnect! */ goto out; } _g_dbus_auth_mechanism_server_data_receive (mech, decoded_data, decoded_data_len); g_free (decoded_data); /* oh man, this goto-crap is so ugly.. really need to rewrite the state machine */ goto change_state; } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unexpected line `%s' while in WaitingForData state", line); g_free (line); } goto out; case SERVER_STATE_WAITING_FOR_BEGIN: debug_print ("SERVER: WaitingForBegin"); /* Use extremely slow (but reliable) line reader - this basically * does a recvfrom() system call per character * * (the problem with using GDataInputStream's read_line is that because of * buffering it might start reading into the first D-Bus message that * appears after "BEGIN\r\n"....) */ line = _my_g_input_stream_read_line_safe (g_io_stream_get_input_stream (auth->priv->stream), &line_length, cancellable, error); debug_print ("SERVER: WaitingForBegin, read `%s'", line); if (line == NULL) goto out; if (g_strcmp0 (line, "BEGIN") == 0) { /* YAY, done! */ ret = TRUE; g_free (line); goto out; } else if (g_strcmp0 (line, "NEGOTIATE_UNIX_FD") == 0) { g_free (line); if (offered_capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING) { negotiated_capabilities |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING; s = "AGREE_UNIX_FD\r\n"; debug_print ("SERVER: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) goto out; } else { s = "ERROR \"fd passing not offered\"\r\n"; debug_print ("SERVER: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) goto out; } } else { g_debug ("Unexpected line `%s' while in WaitingForBegin state", line); g_free (line); s = "ERROR \"Unknown Command\"\r\n"; debug_print ("SERVER: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) goto out; } break; default: g_assert_not_reached (); break; } } g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Not implemented (server)"); out: if (mech != NULL) g_object_unref (mech); if (dis != NULL) g_object_unref (dis); if (dos != NULL) g_object_unref (dos); /* ensure return value is FALSE if error is set */ if (error != NULL && *error != NULL) { ret = FALSE; } if (ret) { if (out_negotiated_capabilities != NULL) *out_negotiated_capabilities = negotiated_capabilities; if (out_received_credentials != NULL) *out_received_credentials = credentials != NULL ? g_object_ref (credentials) : NULL; } if (credentials != NULL) g_object_unref (credentials); debug_print ("SERVER: Done, authenticated=%d", ret); return ret; }
/* Save app data lists to file */ static gboolean idle_save_application_usage (gpointer data) { ShellAppUsage *self = SHELL_APP_USAGE (data); UsageIterator iter; const char *current_context; const char *context; const char *id; UsageData *usage; GFileOutputStream *output; GOutputStream *buffered_output; GDataOutputStream *data_output; GError *error = NULL; self->save_id = 0; /* Parent directory is already created by shell-global */ output = g_file_replace (self->configfile, NULL, FALSE, G_FILE_CREATE_NONE, NULL, &error); if (!output) { g_debug ("Could not save applications usage data: %s", error->message); g_error_free (error); return FALSE; } buffered_output = g_buffered_output_stream_new (G_OUTPUT_STREAM (output)); g_object_unref (output); data_output = g_data_output_stream_new (G_OUTPUT_STREAM (buffered_output)); g_object_unref (buffered_output); if (!g_data_output_stream_put_string (data_output, "<?xml version=\"1.0\"?>\n<application-state>\n", NULL, &error)) goto out; usage_iterator_init (self, &iter); current_context = NULL; while (usage_iterator_next (self, &iter, &context, &id, &usage)) { ShellApp *app; app = shell_app_system_lookup_app (shell_app_system_get_default(), id); if (!app) continue; if (context != current_context) { if (current_context != NULL) { if (!g_data_output_stream_put_string (data_output, " </context>", NULL, &error)) goto out; } current_context = context; if (!g_data_output_stream_put_string (data_output, " <context", NULL, &error)) goto out; if (!write_attribute_string (data_output, "id", context, &error)) goto out; if (!g_data_output_stream_put_string (data_output, ">\n", NULL, &error)) goto out; } if (!g_data_output_stream_put_string (data_output, " <application", NULL, &error)) goto out; if (!write_attribute_string (data_output, "id", id, &error)) goto out; if (!write_attribute_uint (data_output, "open-window-count", shell_app_get_n_windows (app), &error)) goto out; if (!write_attribute_double (data_output, "score", usage->score, &error)) goto out; if (!write_attribute_uint (data_output, "last-seen", usage->last_seen, &error)) goto out; if (!g_data_output_stream_put_string (data_output, "/>\n", NULL, &error)) goto out; } if (current_context != NULL) { if (!g_data_output_stream_put_string (data_output, " </context>\n", NULL, &error)) goto out; } if (!g_data_output_stream_put_string (data_output, "</application-state>\n", NULL, &error)) goto out; out: if (!error) g_output_stream_close_async (G_OUTPUT_STREAM (data_output), 0, NULL, NULL, NULL); g_object_unref (data_output); if (error) { g_debug ("Could not save applications usage data: %s", error->message); g_error_free (error); } return FALSE; }
static GDBusAuthMechanism * client_choose_mech_and_send_initial_response (GDBusAuth *auth, GCredentials *credentials_that_were_sent, const gchar* const *supported_auth_mechs, GPtrArray *attempted_auth_mechs, GDataOutputStream *dos, GCancellable *cancellable, GError **error) { GDBusAuthMechanism *mech; GType auth_mech_to_use_gtype; guint n; guint m; gchar *initial_response; gsize initial_response_len; gchar *encoded; gchar *s; again: mech = NULL; debug_print ("CLIENT: Trying to choose mechanism"); /* find an authentication mechanism to try, if any */ auth_mech_to_use_gtype = (GType) 0; for (n = 0; supported_auth_mechs[n] != NULL; n++) { gboolean attempted_already; attempted_already = FALSE; for (m = 0; m < attempted_auth_mechs->len; m++) { if (g_strcmp0 (supported_auth_mechs[n], attempted_auth_mechs->pdata[m]) == 0) { attempted_already = TRUE; break; } } if (!attempted_already) { auth_mech_to_use_gtype = find_mech_by_name (auth, supported_auth_mechs[n]); if (auth_mech_to_use_gtype != (GType) 0) break; } } if (auth_mech_to_use_gtype == (GType) 0) { guint n; gchar *available; GString *tried_str; debug_print ("CLIENT: Exhausted all available mechanisms"); available = g_strjoinv (", ", (gchar **) supported_auth_mechs); tried_str = g_string_new (NULL); for (n = 0; n < attempted_auth_mechs->len; n++) { if (n > 0) g_string_append (tried_str, ", "); g_string_append (tried_str, attempted_auth_mechs->pdata[n]); } g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Exhausted all available authentication mechanisms (tried: %s) (available: %s)"), tried_str->str, available); g_string_free (tried_str, TRUE); g_free (available); goto out; } /* OK, decided on a mechanism - let's do this thing */ mech = g_object_new (auth_mech_to_use_gtype, "stream", auth->priv->stream, "credentials", credentials_that_were_sent, NULL); debug_print ("CLIENT: Trying mechanism `%s'", _g_dbus_auth_mechanism_get_name (auth_mech_to_use_gtype)); g_ptr_array_add (attempted_auth_mechs, (gpointer) _g_dbus_auth_mechanism_get_name (auth_mech_to_use_gtype)); /* the auth mechanism may not be supported * (for example, EXTERNAL only works if credentials were exchanged) */ if (!_g_dbus_auth_mechanism_is_supported (mech)) { debug_print ("CLIENT: Mechanism `%s' says it is not supported", _g_dbus_auth_mechanism_get_name (auth_mech_to_use_gtype)); g_object_unref (mech); mech = NULL; goto again; } initial_response_len = -1; initial_response = _g_dbus_auth_mechanism_client_initiate (mech, &initial_response_len); #if 0 g_printerr ("using auth mechanism with name `%s' of type `%s' with initial response `%s'\n", _g_dbus_auth_mechanism_get_name (auth_mech_to_use_gtype), g_type_name (G_TYPE_FROM_INSTANCE (mech)), initial_response); #endif if (initial_response != NULL) { //g_printerr ("initial_response = `%s'\n", initial_response); encoded = hexencode (initial_response); s = g_strdup_printf ("AUTH %s %s\r\n", _g_dbus_auth_mechanism_get_name (auth_mech_to_use_gtype), encoded); g_free (initial_response); g_free (encoded); } else { s = g_strdup_printf ("AUTH %s\r\n", _g_dbus_auth_mechanism_get_name (auth_mech_to_use_gtype)); } debug_print ("CLIENT: writing `%s'", s); if (!g_data_output_stream_put_string (dos, s, cancellable, error)) { g_object_unref (mech); mech = NULL; g_free (s); goto out; } g_free (s); out: return mech; }