--- a/libpurple/protocols/novell/nmconn.c Sat Nov 02 23:02:26 2019 -0400 +++ b/libpurple/protocols/novell/nmconn.c Sun Nov 03 20:27:37 2019 -0500 @@ -36,27 +36,6 @@ #define NO_ESCAPE(ch) ((ch == 0x20) || (ch >= 0x30 && ch <= 0x39) || \ (ch >= 0x41 && ch <= 0x5a) || (ch >= 0x61 && ch <= 0x7a)) -/* Read data from conn until the end of a line */ -static NMERR_T -read_line(NMConn * conn, char *buff, int len) -{ - NMERR_T rc = NM_OK; - int total_bytes = 0; - - while ((rc == NM_OK) && (total_bytes < (len - 1))) { - rc = nm_read_all(conn, &buff[total_bytes], 1); - if (rc == NM_OK) { - total_bytes += 1; - if (buff[total_bytes - 1] == '\n') { - break; - } - } - } - buff[total_bytes] = '\0'; - - return rc; -} - static char * url_escape_string(char *src) { @@ -188,8 +167,8 @@ conn->requests = NULL; if (conn->input) { - purple_gio_graceful_close(conn->stream, conn->input, - conn->output); + purple_gio_graceful_close(conn->stream, G_INPUT_STREAM(conn->input), + conn->output); } g_clear_object(&conn->input); g_clear_object(&conn->output); @@ -199,68 +178,10 @@ g_free(conn); } -int -nm_tcp_write(NMConn * conn, const void *buff, int len) -{ - if (conn == NULL || buff == NULL) - return -1; - - return g_output_stream_write(conn->output, buff, len, NULL, NULL); -} - -int -nm_tcp_read(NMConn * conn, void *buff, int len) -{ - if (conn == NULL || buff == NULL) - return -1; - - return g_input_stream_read(conn->input, buff, len, NULL, NULL); -} - NMERR_T -nm_read_all(NMConn * conn, char *buff, int len) +nm_write_fields(NMUser *user, NMField *fields) { - NMERR_T rc = NM_OK; - - if (conn == NULL || buff == NULL) - return NMERR_BAD_PARM; - - if (!g_input_stream_read_all(conn->input, buff, len, NULL, NULL, NULL)) { - rc = NMERR_TCP_READ; - } - - return rc; -} - -NMERR_T -nm_read_uint32(NMConn *conn, guint32 *val) -{ - NMERR_T rc = NM_OK; - - rc = nm_read_all(conn, (char *)val, sizeof(*val)); - if (rc == NM_OK) { - *val = GUINT32_FROM_LE(*val); - } - - return rc; -} - -NMERR_T -nm_read_uint16(NMConn *conn, guint16 *val) -{ - NMERR_T rc = NM_OK; - - rc = nm_read_all(conn, (char *)val, sizeof(*val)); - if (rc == NM_OK) { - *val = GUINT16_FROM_LE(*val); - } - - return rc; -} - -NMERR_T -nm_write_fields(NMConn * conn, NMField * fields) -{ + NMConn *conn; NMERR_T rc = NM_OK; NMField *field; char *value = NULL; @@ -270,9 +191,10 @@ int bytes_to_send; int val = 0; - if (conn == NULL || fields == NULL) { - return NMERR_BAD_PARM; - } + g_return_val_if_fail(user != NULL, NMERR_BAD_PARM); + conn = user->conn; + g_return_val_if_fail(conn != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(fields != NULL, NMERR_BAD_PARM); /* Format each field as valid "post" data and write it out */ for (field = fields; (rc == NM_OK) && (field->tag); field++) { @@ -285,7 +207,8 @@ /* Write the field tag */ bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&tag=%s", field->tag); - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } @@ -294,7 +217,8 @@ if (rc == NM_OK) { method = encode_method(field->method); bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&cmd=%s", method); - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } @@ -310,9 +234,13 @@ bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&val=%s", value); if (bytes_to_send > (int)sizeof(buffer)) { - ret = nm_tcp_write(conn, buffer, sizeof(buffer)); + ret = g_output_stream_write(conn->output, buffer, + sizeof(buffer), + user->cancellable, NULL); } else { - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, + bytes_to_send, + user->cancellable, NULL); } if (ret < 0) { @@ -329,7 +257,9 @@ val = nm_count_fields((NMField *) field->ptr_value); bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&val=%u", val); - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, + bytes_to_send, + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } @@ -340,7 +270,9 @@ bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&val=%u", field->value); - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, + bytes_to_send, + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } @@ -353,7 +285,8 @@ if (rc == NM_OK) { bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&type=%u", field->type); - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } @@ -364,8 +297,7 @@ if (field->type == NMFIELD_TYPE_ARRAY || field->type == NMFIELD_TYPE_MV) { - rc = nm_write_fields(conn, (NMField *) field->ptr_value); - + rc = nm_write_fields(user, (NMField *)field->ptr_value); } } } @@ -374,9 +306,10 @@ } NMERR_T -nm_send_request(NMConn *conn, char *cmd, NMField *fields, - nm_response_cb cb, gpointer data, NMRequest **request) +nm_send_request(NMUser *user, char *cmd, NMField *fields, nm_response_cb cb, + gpointer data, NMRequest **request) { + NMConn *conn; NMERR_T rc = NM_OK; char buffer[512]; int bytes_to_send; @@ -384,13 +317,16 @@ NMField *request_fields = NULL; char *str = NULL; - if (conn == NULL || cmd == NULL) - return NMERR_BAD_PARM; + g_return_val_if_fail(user != NULL, NMERR_BAD_PARM); + conn = user->conn; + g_return_val_if_fail(conn != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(cmd != NULL, NMERR_BAD_PARM); /* Write the post */ bytes_to_send = g_snprintf(buffer, sizeof(buffer), "POST /%s HTTP/1.0\r\n", cmd); - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } @@ -400,13 +336,15 @@ if (purple_strequal("login", cmd)) { bytes_to_send = g_snprintf(buffer, sizeof(buffer), "Host: %s:%d\r\n\r\n", conn->addr, conn->port); - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } } else { bytes_to_send = g_snprintf(buffer, sizeof(buffer), "\r\n"); - ret = nm_tcp_write(conn, buffer, bytes_to_send); + ret = g_output_stream_write(conn->output, buffer, bytes_to_send, + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } @@ -426,12 +364,13 @@ /* Send the request to the server */ if (rc == NM_OK) { - rc = nm_write_fields(conn, request_fields); + rc = nm_write_fields(user, request_fields); } /* Write the CRLF to terminate the data */ if (rc == NM_OK) { - ret = nm_tcp_write(conn, "\r\n", strlen("\r\n")); + ret = g_output_stream_write(conn->output, "\r\n", strlen("\r\n"), + user->cancellable, NULL); if (ret < 0) { rc = NMERR_TCP_WRITE; } @@ -457,22 +396,24 @@ } NMERR_T -nm_read_header(NMConn * conn) +nm_read_header(NMUser *user) { + NMConn *conn; NMERR_T rc = NM_OK; - char buffer[512]; + gchar *buffer; char *ptr = NULL; int i; char rtn_buf[8]; int rtn_code = 0; - - if (conn == NULL) - return NMERR_BAD_PARM; + GError *error = NULL; - *buffer = '\0'; - rc = read_line(conn, buffer, sizeof(buffer)); - if (rc == NM_OK) { + g_return_val_if_fail(user != NULL, NMERR_BAD_PARM); + conn = user->conn; + g_return_val_if_fail(conn != NULL, NMERR_BAD_PARM); + buffer = g_data_input_stream_read_line(conn->input, NULL, user->cancellable, + &error); + if (error == NULL) { /* Find the return code */ ptr = strchr(buffer, ' '); if (ptr != NULL) { @@ -493,8 +434,19 @@ /* Finish reading header, in the future we might want to do more processing here */ /* TODO: handle more general redirects in the future */ - while ((rc == NM_OK) && (!purple_strequal(buffer, "\r\n"))) { - rc = read_line(conn, buffer, sizeof(buffer)); + while ((error == NULL) && !purple_strequal(buffer, "\r")) { + g_free(buffer); + buffer = g_data_input_stream_read_line(conn->input, NULL, + user->cancellable, &error); + } + g_free(buffer); + + if (error != NULL) { + if (error->code != G_IO_ERROR_WOULD_BLOCK && + error->code != G_IO_ERROR_CANCELLED) { + rc = NMERR_TCP_READ; + } + g_error_free(error); } if (rc == NM_OK && rtn_code == 301) @@ -504,8 +456,9 @@ } NMERR_T -nm_read_fields(NMConn * conn, int count, NMField ** fields) +nm_read_fields(NMUser *user, int count, NMField **fields) { + NMConn *conn; NMERR_T rc = NM_OK; guint8 type; guint8 method; @@ -513,9 +466,12 @@ char tag[64]; NMField *sub_fields = NULL; char *str = NULL; + GError *error = NULL; - if (conn == NULL || fields == NULL) - return NMERR_BAD_PARM; + g_return_val_if_fail(user != NULL, NMERR_BAD_PARM); + conn = user->conn; + g_return_val_if_fail(conn != NULL, NMERR_BAD_PARM); + g_return_val_if_fail(fields != NULL, NMERR_BAD_PARM); do { if (count > 0) { @@ -523,36 +479,46 @@ } /* Read the field type, method, and tag */ - rc = nm_read_all(conn, (char *)&type, sizeof(type)); - if (rc != NM_OK || type == 0) + type = g_data_input_stream_read_byte(conn->input, user->cancellable, + &error); + if (error != NULL || type == 0) { break; + } - rc = nm_read_all(conn, (char *)&method, sizeof(method)); - if (rc != NM_OK) + method = g_data_input_stream_read_byte(conn->input, user->cancellable, + &error); + if (error != NULL) { break; + } - rc = nm_read_uint32(conn, &val); - if (rc != NM_OK) + val = g_data_input_stream_read_uint32(conn->input, user->cancellable, + &error); + if (error != NULL) { break; + } if (val > sizeof(tag)) { rc = NMERR_PROTOCOL; break; } - rc = nm_read_all(conn, tag, val); - if (rc != NM_OK) + g_input_stream_read_all(G_INPUT_STREAM(conn->input), tag, val, NULL, + user->cancellable, &error); + if (error != NULL) { break; + } if (type == NMFIELD_TYPE_MV || type == NMFIELD_TYPE_ARRAY) { /* Read the subarray (first read the number of items in the array) */ - rc = nm_read_uint32(conn, &val); - if (rc != NM_OK) + val = g_data_input_stream_read_uint32(conn->input, + user->cancellable, &error); + if (error != NULL) { break; + } if (val > 0) { - rc = nm_read_fields(conn, val, &sub_fields); + rc = nm_read_fields(user, val, &sub_fields); if (rc != NM_OK) break; } @@ -565,9 +531,11 @@ } else if (type == NMFIELD_TYPE_UTF8 || type == NMFIELD_TYPE_DN) { /* Read the string (first read the length) */ - rc = nm_read_uint32(conn, &val); - if (rc != NM_OK) + val = g_data_input_stream_read_uint32(conn->input, + user->cancellable, &error); + if (error != NULL) { break; + } if (val >= NMFIELD_MAX_STR_LENGTH) { rc = NMERR_PROTOCOL; @@ -577,9 +545,11 @@ if (val > 0) { str = g_new0(char, val + 1); - rc = nm_read_all(conn, str, val); - if (rc != NM_OK) + g_input_stream_read_all(G_INPUT_STREAM(conn->input), str, val, + NULL, user->cancellable, &error); + if (error != NULL) { break; + } *fields = nm_field_add_pointer(*fields, tag, 0, method, 0, str, type); @@ -589,9 +559,11 @@ } else { /* Read the numerical value */ - rc = nm_read_uint32(conn, &val); - if (rc != NM_OK) + val = g_data_input_stream_read_uint32(conn->input, + user->cancellable, &error); + if (error != NULL) { break; + } *fields = nm_field_add_number(*fields, tag, 0, method, 0, val, type); @@ -605,6 +577,13 @@ nm_free_fields(&sub_fields); } + if (error != NULL) { + if (error->code != G_IO_ERROR_WOULD_BLOCK && error->code != G_IO_ERROR_CANCELLED) { + rc = NMERR_TCP_READ; + } + g_error_free(error); + } + return rc; }