modem-helpers: rework AT string quote operation and add unit tests
Rework the AT string quote operation to build the output with the GString helper, instead of manually calculating how many bytes we'll need in the output. It just makes it clearer.
This commit is contained in:
@@ -10897,7 +10897,7 @@ modem_3gpp_profile_manager_store_profile (MMIfaceModem3gppProfileManager *self,
|
||||
g_assert (pdp_type);
|
||||
|
||||
apn = mm_3gpp_profile_get_apn (profile);
|
||||
quoted_apn = mm_port_serial_at_quote_string (apn);
|
||||
quoted_apn = mm_at_quote_string (apn);
|
||||
|
||||
mm_obj_dbg (self, "storing profile '%d': apn '%s', ip type '%s'",
|
||||
profile_id, apn, ip_type_str);
|
||||
|
||||
@@ -454,6 +454,34 @@ mm_bcd_to_string (const guint8 *bcd, gsize bcd_len, gboolean low_nybble_first)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gchar *
|
||||
mm_at_quote_string (const gchar *input)
|
||||
{
|
||||
GString *str;
|
||||
gsize input_len;
|
||||
|
||||
input_len = input ? strlen (input) : 0;
|
||||
str = g_string_sized_new (3 + 3 * input_len); /* worst case */
|
||||
g_string_append_c (str, '"');
|
||||
|
||||
if (input) {
|
||||
gsize i, len;
|
||||
|
||||
len = strlen (input);
|
||||
for (i = 0 ; i < len; i++) {
|
||||
if (input[i] < 0x20 || input[i] == '"' || input[i] == '\\')
|
||||
g_string_append_printf (str, "\\%02X", input[i]);
|
||||
else
|
||||
g_string_append_c (str, input[i]);
|
||||
}
|
||||
}
|
||||
g_string_append_c (str, '"');
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
GRegex *
|
||||
mm_voice_ring_regex_get (void)
|
||||
{
|
||||
|
||||
@@ -79,6 +79,12 @@ gchar *mm_bcd_to_string (const guint8 *bcd,
|
||||
gsize bcd_len,
|
||||
gboolean low_nybble_first);
|
||||
|
||||
/*
|
||||
* Convert a string into a quoted and escaped string. Returns a new
|
||||
* allocated string. Follows ITU V.250 5.4.2.2 "String constants".
|
||||
*/
|
||||
gchar *mm_at_quote_string (const gchar *input);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* VOICE specific helpers and utilities */
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -54,32 +54,6 @@ struct _MMPortSerialAtPrivate {
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gchar *
|
||||
mm_port_serial_at_quote_string (const char *string)
|
||||
{
|
||||
int len, i;
|
||||
gchar *quoted, *pos;
|
||||
|
||||
if (string == NULL)
|
||||
len = 0;
|
||||
else
|
||||
len = strlen (string);
|
||||
quoted = g_malloc (3 + 3 * len); /* worst case */
|
||||
|
||||
pos = quoted;
|
||||
*pos++ = '"';
|
||||
for (i = 0 ; i < len; i++) {
|
||||
if (string[i] < 0x20 || string[i] == '"' || string[i] == '\\')
|
||||
pos += sprintf (pos, "\\%02X", string[i]);
|
||||
else
|
||||
*pos++ = string[i];
|
||||
}
|
||||
*pos++ = '"';
|
||||
*pos++ = '\0';
|
||||
|
||||
return quoted;
|
||||
}
|
||||
|
||||
void
|
||||
mm_port_serial_at_set_response_parser (MMPortSerialAt *self,
|
||||
MMPortSerialAtResponseParserFn fn,
|
||||
|
||||
@@ -112,12 +112,6 @@ gchar *mm_port_serial_at_command_finish (MMPortSerialAt *self,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
/*
|
||||
* Convert a string into a quoted and escaped string. Returns a new
|
||||
* allocated string. Follows ITU V.250 5.4.2.2 "String constants".
|
||||
*/
|
||||
gchar *mm_port_serial_at_quote_string (const char *string);
|
||||
|
||||
/* Just for unit tests */
|
||||
void mm_port_serial_at_remove_echo (GByteArray *response);
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ connect_3gpp (MMBroadbandBearer *self,
|
||||
g_task_set_task_data (task, ctx, (GDestroyNotify)detailed_connect_context_free);
|
||||
|
||||
config = mm_base_bearer_peek_config (MM_BASE_BEARER (self));
|
||||
apn = mm_port_serial_at_quote_string (mm_bearer_properties_get_apn (config));
|
||||
apn = mm_at_quote_string (mm_bearer_properties_get_apn (config));
|
||||
command = g_strdup_printf ("%%APNN=%s", apn);
|
||||
g_free (apn);
|
||||
mm_base_modem_at_command_full (ctx->modem,
|
||||
|
||||
@@ -1374,7 +1374,7 @@ set_initial_eps_step (GTask *task)
|
||||
apn = mm_bearer_properties_get_apn (ctx->properties);
|
||||
mm_obj_dbg (self, "context %d with APN '%s' and PDP type '%s'",
|
||||
self->priv->initial_eps_bearer_cid, apn, ip_family_str);
|
||||
quoted_apn = mm_port_serial_at_quote_string (apn);
|
||||
quoted_apn = mm_at_quote_string (apn);
|
||||
apn_cmd = g_strdup_printf ("+CGDCONT=%u,\"%s\",%s",
|
||||
self->priv->initial_eps_bearer_cid, ip_family_str, quoted_apn);
|
||||
mm_base_modem_at_command (
|
||||
|
||||
@@ -1855,8 +1855,8 @@ mm_cinterion_build_auth_string (gpointer log_object,
|
||||
return g_strdup_printf ("^SGAUTH=%u,%d", cid, encoded_auth);
|
||||
}
|
||||
|
||||
quoted_user = mm_port_serial_at_quote_string (user ? user : "");
|
||||
quoted_passwd = mm_port_serial_at_quote_string (passwd ? passwd : "");
|
||||
quoted_user = mm_at_quote_string (user ? user : "");
|
||||
quoted_passwd = mm_at_quote_string (passwd ? passwd : "");
|
||||
|
||||
if (modem_family == MM_CINTERION_MODEM_FAMILY_IMT)
|
||||
return g_strdup_printf ("^SGAUTH=%u,%d,%s,%s",
|
||||
|
||||
@@ -2052,8 +2052,8 @@ profile_manager_store_profile_auth_settings (GTask *task)
|
||||
return;
|
||||
}
|
||||
|
||||
quoted_user = mm_port_serial_at_quote_string (user);
|
||||
quoted_password = mm_port_serial_at_quote_string (password);
|
||||
quoted_user = mm_at_quote_string (user);
|
||||
quoted_password = mm_at_quote_string (password);
|
||||
ctx->cmd = g_strdup_printf ("%%IPDPCFG=%d,0,%u,%s,%s",
|
||||
ctx->profile_id,
|
||||
icera_auth,
|
||||
|
||||
@@ -299,9 +299,9 @@ connect_3gpp_authenticate (GTask *task)
|
||||
ctx = g_task_get_task_data (task);
|
||||
|
||||
config = mm_base_bearer_peek_config (MM_BASE_BEARER (self));
|
||||
apn = mm_port_serial_at_quote_string (mm_bearer_properties_get_apn (config));
|
||||
user = mm_port_serial_at_quote_string (mm_bearer_properties_get_user (config));
|
||||
password = mm_port_serial_at_quote_string (mm_bearer_properties_get_password (config));
|
||||
apn = mm_at_quote_string (mm_bearer_properties_get_apn (config));
|
||||
user = mm_at_quote_string (mm_bearer_properties_get_user (config));
|
||||
password = mm_at_quote_string (mm_bearer_properties_get_password (config));
|
||||
command = g_strdup_printf ("$NWQMICONNECT=,,,,,,%s,,,%s,%s",
|
||||
apn, user, password);
|
||||
g_free (apn);
|
||||
|
||||
@@ -557,8 +557,8 @@ authenticate (GTask *task)
|
||||
return;
|
||||
}
|
||||
|
||||
quoted_user = mm_port_serial_at_quote_string (user);
|
||||
quoted_password = mm_port_serial_at_quote_string (password);
|
||||
quoted_user = mm_at_quote_string (user);
|
||||
quoted_password = mm_at_quote_string (password);
|
||||
command = g_strdup_printf ("%s=%d,%u,%s,%s",
|
||||
auth_commands[ctx->auth_idx],
|
||||
ctx->cid,
|
||||
|
||||
@@ -361,8 +361,8 @@ dial_3gpp_context_step (GTask *task)
|
||||
return;
|
||||
}
|
||||
|
||||
quoted_user = mm_port_serial_at_quote_string (user);
|
||||
quoted_password = mm_port_serial_at_quote_string (password);
|
||||
quoted_user = mm_at_quote_string (user);
|
||||
quoted_password = mm_at_quote_string (password);
|
||||
if (self->priv->is_icera) {
|
||||
command = g_strdup_printf ("%%IPDPCFG=%d,0,%u,%s,%s",
|
||||
ctx->cid,
|
||||
|
||||
@@ -533,8 +533,8 @@ out:
|
||||
user = mm_bearer_properties_get_user (mm_base_bearer_peek_config (MM_BASE_BEARER (self)));
|
||||
password = mm_bearer_properties_get_password (mm_base_bearer_peek_config (MM_BASE_BEARER (self)));
|
||||
|
||||
quoted_user = mm_port_serial_at_quote_string (user);
|
||||
quoted_password = mm_port_serial_at_quote_string (password);
|
||||
quoted_user = mm_at_quote_string (user);
|
||||
quoted_password = mm_at_quote_string (password);
|
||||
|
||||
cmd = g_strdup_printf ("+UAUTHREQ=%u,%u,%s,%s",
|
||||
ctx->cid,
|
||||
|
||||
@@ -4545,6 +4545,34 @@ test_bcd_to_string (void *f, gpointer d)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const gchar *input;
|
||||
const gchar *expected;
|
||||
} AtQuoteStringTest;
|
||||
|
||||
static const AtQuoteStringTest at_quote_string_tests[] = {
|
||||
{ "", "\"\"" },
|
||||
{ "internet", "\"internet\"" },
|
||||
{ "\"internet", "\"\\22internet\"" }, /* double quote is \22 */
|
||||
{ "\r\ninternet", "\"\\0D\\0Ainternet\"" }, /* CRLF is \0D\0A */
|
||||
{ "\r\ninternet\r\n", "\"\\0D\\0Ainternet\\0D\\0A\"" }, /* CRLF is \0D\0A */
|
||||
};
|
||||
|
||||
static void
|
||||
test_at_quote_string (void *f, gpointer d)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (at_quote_string_tests); i++) {
|
||||
g_autofree gchar *str = NULL;
|
||||
|
||||
str = mm_at_quote_string (at_quote_string_tests[i].input);
|
||||
g_assert_cmpstr (str, ==, at_quote_string_tests[i].expected);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
const gchar *response;
|
||||
gboolean expected_error;
|
||||
@@ -4855,6 +4883,8 @@ int main (int argc, char **argv)
|
||||
|
||||
g_test_suite_add (suite, TESTCASE (test_bcd_to_string, NULL));
|
||||
|
||||
g_test_suite_add (suite, TESTCASE (test_at_quote_string, NULL));
|
||||
|
||||
g_test_suite_add (suite, TESTCASE (test_cpol_response, NULL));
|
||||
|
||||
result = g_test_run ();
|
||||
|
||||
Reference in New Issue
Block a user