diff --git a/src/common/cfgfiles.c b/src/common/cfgfiles.c index b18a4357..c1bef23f 100644 --- a/src/common/cfgfiles.c +++ b/src/common/cfgfiles.c @@ -170,6 +170,116 @@ list_delentry (GSList ** list, char *name) return 0; } +/* +* Unescapes \\r and \\n as \r and \n. +* Returns newly allocated string. +* +* Modified version of gkeyfile's unescaping. +*/ +char * +unescape_newlines (const gchar *value) +{ + gchar *string_value, *p, *q0, *q; + + string_value = g_new (gchar, strlen (value) + 1); + + p = (gchar *) value; + q0 = q = string_value; + while (*p) + { + if (*p == '\\') + { + p++; + + switch (*p) + { + case 'n': + *q = '\n'; + break; + case 'r': + *q = '\r'; + break; + case '\\': + *q = '\\'; + break; + case '\0': + g_warning ("Escaped character at end of string."); + break; + default: + *q++ = '\\'; + *q = *p; + g_warning ("Invalid escape sequence."); + break; + } + } + else + { + *q = *p; + } + + if (*p == '\0') + break; + + q++; + p++; + } + + *q = '\0'; + + return string_value; +} + +/* + * Escapes \r and \n as \\r and \\n. + * Returns newly allocated string. + * + * Modified version of gkeyfile's escaping. + */ +char * +escape_newlines (const char *str) +{ + gchar *value, *p, *q; + gsize len; + + len = strlen (str) + 1; + value = g_new (gchar, 2 * len); + + p = (gchar*)str; + q = value; + + while (p < (str + len - 1)) + { + gchar escaped_character[3] = { '\\', 0, 0 }; + + switch (*p) + { + case '\n': + escaped_character[1] = 'n'; + strcpy (q, escaped_character); + q += 2; + break; + case '\r': + escaped_character[1] = 'r'; + strcpy (q, escaped_character); + q += 2; + break; + case '\\': + escaped_character[1] = '\\'; + strcpy (q, escaped_character); + q += 2; + break; + default: + *q = *p; + q++; + break; + } + p++; + } + *q = '\0'; + + return value; +} + char * cfg_get_str (char *cfg, const char *var, char *dest, int dest_len) { diff --git a/src/common/cfgfiles.h b/src/common/cfgfiles.h index 229e6cfd..eeba014d 100644 --- a/src/common/cfgfiles.h +++ b/src/common/cfgfiles.h @@ -54,6 +54,9 @@ FILE *hexchat_fopen_file (const char *file, const char *mode, int xof_flags); GFile *hexchat_open_gfile (const char *filename); gsize stream_writef (GOutputStream *ostream, const char *fmt, ...) G_GNUC_PRINTF (2, 3); +char *unescape_newlines (const gchar *value); +char *escape_newlines (const gchar *value); + #define XOF_DOMODE 1 #define XOF_FULLPATH 2 diff --git a/src/common/plugin.c b/src/common/plugin.c index 296c7294..6178d779 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -1752,9 +1752,7 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char GDataInputStream *istream; GFileIOStream *tmpstream; gboolean ret; - char *confname; - char *line; - char *canon; + char *confname, *line, *canon, *escaped_value; canon = g_strdup (pl->name); canonalize_key (canon); @@ -1780,8 +1778,10 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char g_object_unref (file); return 0; } - - cfg_put_str (ostream, var, value); + + escaped_value = escape_newlines (value); + cfg_put_str (ostream, var, escaped_value); + g_free (escaped_value); return 1; } @@ -1810,7 +1810,9 @@ hexchat_pluginpref_set_str_real (hexchat_plugin *pl, const char *var, const char if (mode == 1) { /* Add new setting */ - cfg_put_str (ostream, var, value); + escaped_value = escape_newlines (value); + cfg_put_str (ostream, var, escaped_value); + g_free (escaped_value); } while ((line = g_data_input_stream_read_line_utf8 (istream, NULL, NULL, NULL))) @@ -1843,7 +1845,8 @@ static int hexchat_pluginpref_get_str_real (hexchat_plugin *pl, const char *var, char *dest, int dest_len) { GFile *file; - char *confname, *canon, *cfg; + char *confname, *canon, *cfg, *unescaped_value; + char buf[512], *bufp = buf; canon = g_strdup (pl->name); canonalize_key (canon); @@ -1860,11 +1863,15 @@ hexchat_pluginpref_get_str_real (hexchat_plugin *pl, const char *var, char *dest } g_object_unref (file); - if (!cfg_get_str (cfg, var, dest, dest_len)) + if (!cfg_get_str (cfg, var, buf, sizeof(buf))) { g_free (cfg); return 0; } + + unescaped_value = unescape_newlines (bufp); + g_strlcpy (dest, unescaped_value, dest_len); + g_free (unescaped_value); g_free (cfg); return 1;