char * g_vfs_afp_command_get_data (GVfsAfpCommand *comm) { GMemoryOutputStream *mem_stream; mem_stream = G_MEMORY_OUTPUT_STREAM (g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (comm))); return g_memory_output_stream_get_data (mem_stream); }
static gboolean emfe_text_enriched_format (EMailFormatterExtension *extension, EMailFormatter *formatter, EMailFormatterContext *context, EMailPart *part, GOutputStream *stream, GCancellable *cancellable) { GOutputStream *filtered_stream; CamelMimeFilter *filter; const gchar *mime_type; const gchar *string; gchar *str; guint32 filter_flags = 0; if (g_cancellable_is_cancelled (cancellable)) return FALSE; mime_type = e_mail_part_get_mime_type (part); if (g_strcmp0 (mime_type, "text/richtext") == 0) filter_flags = CAMEL_MIME_FILTER_ENRICHED_IS_RICHTEXT; filter = camel_mime_filter_enriched_new (filter_flags); filtered_stream = camel_filter_output_stream_new (stream, filter); g_filter_output_stream_set_close_base_stream ( G_FILTER_OUTPUT_STREAM (filtered_stream), FALSE); g_object_unref (filter); str = g_strdup_printf ( "<div class=\"part-container -e-mail-formatter-frame-color %s" "-e-web-view-background-color -e-web-view-text-color\">" "<div class=\"part-container-inner-margin\">\n", e_mail_part_get_frame_security_style (part)); g_output_stream_write_all ( stream, str, strlen (str), NULL, cancellable, NULL); g_free (str); e_mail_formatter_format_text ( formatter, part, filtered_stream, cancellable); g_output_stream_flush (filtered_stream, cancellable, NULL); g_object_unref (filtered_stream); string = "</div></div>"; g_output_stream_write_all ( stream, string, strlen (string), NULL, cancellable, NULL); return TRUE; }
static void g_filter_output_stream_dispose (GObject *object) { GFilterOutputStream *stream; stream = G_FILTER_OUTPUT_STREAM (object); G_OBJECT_CLASS (g_filter_output_stream_parent_class)->dispose (object); if (stream->base_stream) { g_object_unref (stream->base_stream); stream->base_stream = NULL; } }
static gboolean g_filter_output_stream_close_finish (GOutputStream *stream, GAsyncResult *result, GError **error) { GFilterOutputStream *filter_stream; gboolean res; filter_stream = G_FILTER_OUTPUT_STREAM (stream); res = g_output_stream_close_finish (filter_stream->base_stream, result, error); return res; }
static gssize g_filter_output_stream_write_finish (GOutputStream *stream, GAsyncResult *result, GError **error) { GFilterOutputStream *filter_stream; gssize nwritten; filter_stream = G_FILTER_OUTPUT_STREAM (stream); nwritten = g_output_stream_write_finish (filter_stream->base_stream, result, error); return nwritten; }
static gboolean g_filter_output_stream_close (GOutputStream *stream, GCancellable *cancellable, GError **error) { GFilterOutputStream *filter_stream; gboolean res; filter_stream = G_FILTER_OUTPUT_STREAM (stream); res = g_output_stream_close (filter_stream->base_stream, cancellable, error); return res; }
static void g_filter_output_stream_close_async (GOutputStream *stream, int io_priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer data) { GFilterOutputStream *filter_stream; filter_stream = G_FILTER_OUTPUT_STREAM (stream); g_output_stream_close_async (filter_stream->base_stream, io_priority, cancellable, callback, data); }
static gboolean emqfe_text_html_format (EMailFormatterExtension *extension, EMailFormatter *formatter, EMailFormatterContext *context, EMailPart *part, GOutputStream *stream, GCancellable *cancellable) { EMailFormatterQuoteContext *qf_context; GOutputStream *filtered_stream; const gchar *string; qf_context = (EMailFormatterQuoteContext *) context; string = "<!-- text/html -->"; g_output_stream_write_all ( stream, string, strlen (string), NULL, cancellable, NULL); filtered_stream = g_object_ref (stream); if ((qf_context->qf_flags & E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG) == 0) { CamelMimeFilter *filter; GOutputStream *temp_stream; filter = e_mail_stripsig_filter_new (FALSE); temp_stream = camel_filter_output_stream_new ( filtered_stream, filter); g_filter_output_stream_set_close_base_stream ( G_FILTER_OUTPUT_STREAM (temp_stream), FALSE); g_object_unref (filtered_stream); filtered_stream = temp_stream; g_object_unref (filter); } e_mail_formatter_format_text ( formatter, part, filtered_stream, cancellable); g_output_stream_flush (filtered_stream, cancellable, NULL); g_object_unref (filtered_stream); return TRUE; }
static gssize g_filter_output_stream_write (GOutputStream *stream, const void *buffer, gsize count, GCancellable *cancellable, GError **error) { GFilterOutputStream *filter_stream; gssize nwritten; filter_stream = G_FILTER_OUTPUT_STREAM (stream); nwritten = g_output_stream_write (filter_stream->base_stream, buffer, count, cancellable, error); return nwritten; }
static void g_filter_output_stream_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { GFilterOutputStream *filter_stream; filter_stream = G_FILTER_OUTPUT_STREAM (object); switch (prop_id) { case PROP_BASE_STREAM: g_value_set_object (value, filter_stream->base_stream); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } }
static gboolean emqfe_text_plain_format (EMailFormatterExtension *extension, EMailFormatter *formatter, EMailFormatterContext *context, EMailPart *part, GOutputStream *stream, GCancellable *cancellable) { GOutputStream *filtered_stream; GOutputStream *temp_stream; CamelMimeFilter *filter; CamelMimePart *mime_part; CamelContentType *type; EMailFormatterQuoteContext *qf_context; CamelMimeFilterToHTMLFlags text_flags; const gchar *format; guint32 rgb = 0x737373; mime_part = e_mail_part_ref_mime_part (part); if (mime_part == NULL) return FALSE; qf_context = (EMailFormatterQuoteContext *) context; text_flags = CAMEL_MIME_FILTER_TOHTML_PRE | CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS | CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES; /* XXX Should we define a separate EMailFormatter property * for using CAMEL_MIME_FILTER_TOHTML_QUOTE_CITATION? */ if (e_mail_formatter_get_mark_citations (formatter)) text_flags |= CAMEL_MIME_FILTER_TOHTML_QUOTE_CITATION; /* Check for RFC 2646 flowed text. */ type = camel_mime_part_get_content_type (mime_part); if (camel_content_type_is (type, "text", "plain") && (format = camel_content_type_param (type, "format")) && !g_ascii_strcasecmp (format, "flowed")) text_flags |= CAMEL_MIME_FILTER_TOHTML_FORMAT_FLOWED; filtered_stream = g_object_ref (stream); if ((qf_context->qf_flags & E_MAIL_FORMATTER_QUOTE_FLAG_KEEP_SIG) == 0) { filter = e_mail_stripsig_filter_new (TRUE); temp_stream = camel_filter_output_stream_new ( filtered_stream, filter); g_filter_output_stream_set_close_base_stream ( G_FILTER_OUTPUT_STREAM (temp_stream), FALSE); g_object_unref (filtered_stream); filtered_stream = temp_stream; g_object_unref (filter); } filter = camel_mime_filter_tohtml_new (text_flags, rgb); temp_stream = camel_filter_output_stream_new (filtered_stream, filter); g_filter_output_stream_set_close_base_stream ( G_FILTER_OUTPUT_STREAM (temp_stream), FALSE); g_object_unref (filtered_stream); filtered_stream = temp_stream; g_object_unref (filter); e_mail_formatter_format_text ( formatter, part, filtered_stream, cancellable); g_output_stream_flush (filtered_stream, cancellable, NULL); g_object_unref (filtered_stream); g_object_unref (mime_part); return TRUE; }
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; }
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; }