From c5392c7f9056c81ea4fc553095eb977fc31e9e46 Mon Sep 17 00:00:00 2001 From: lovasoa Date: Sun, 11 Aug 2024 18:37:52 +0200 Subject: [PATCH] fix csv escapes --- CHANGELOG.md | 1 + sqlpage/templates/csv.handlebars | 7 +++---- src/template_helpers.rs | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e47fbd89..3b944800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Fixed a bug where in very specific conditions, sqlpage functions could mess up the order of the arguments passed to a sql query. This would happen when a sqlpage function was called with both a column from the database and a sqlpage variable in its arguments, and the query also contained references to other sqlpage variables **after** the sqlpage function call. An example would be `select sqlpage.exec('xxx', some_column = $a) as a, $b as b from t`. A test was added for this case. - added a new `url_encode` helper for [custom components](https://sql.ophir.dev/custom_components.sql) to encode a string for use in a URL. - fixed a bug where the CSV component would break when the data contained a `#` character. +- properly escape fields in the CSV component to avoid generating invalid CSV files. ## 0.26.0 (2024-08-06) ### Components diff --git a/sqlpage/templates/csv.handlebars b/sqlpage/templates/csv.handlebars index 842ee420..be4daabc 100644 --- a/sqlpage/templates/csv.handlebars +++ b/sqlpage/templates/csv.handlebars @@ -3,15 +3,14 @@ {{~#each_row~}} {{~#if (eq @row_index 0)~}}{{! header }} {{~#each this~}} - %22{{! %22 = double-quote}} - {{~url_encode @key~}} - %22 + {{~url_encode (csv_escape @key ../../separator)~}} {{~default ../../separator ","~}} {{~/each~}} %0A{{! %0A = newline}} {{~/if~}} {{~#each this~}} - %22{{url_encode this}}%22{{default ../../separator ","}} + {{~url_encode (csv_escape this ../../separator)~}} + {{~default ../../separator ","~}} {{~/each~}} %0A {{~/each_row~}} diff --git a/src/template_helpers.rs b/src/template_helpers.rs index 42f26a29..e7de3b1e 100644 --- a/src/template_helpers.rs +++ b/src/template_helpers.rs @@ -52,6 +52,7 @@ pub fn register_all_helpers(h: &mut Handlebars<'_>, config: &AppConfig) { register_helper(h, "typeof", typeof_helper as H); register_helper(h, "rfc2822_date", rfc2822_date_helper as EH); register_helper(h, "url_encode", url_encode_helper as H); + register_helper(h, "csv_escape", csv_escape_helper as HH); } fn stringify_helper(v: &JsonValue) -> JsonValue { @@ -282,6 +283,20 @@ fn url_encode_helper(v: &JsonValue) -> JsonValue { .into() } +// Percent-encode a string +fn csv_escape_helper(v: &JsonValue, separator: &JsonValue) -> JsonValue { + let as_str = match v { + JsonValue::String(s) => s, + other => &other.to_string(), + }; + let separator = separator.as_str().unwrap_or(","); + if as_str.contains(separator) || as_str.contains('"') || as_str.contains('\n') { + format!(r#""{}""#, as_str.replace('"', r#""""#)).into() + } else { + as_str.to_owned().into() + } +} + fn with_each_block<'a, 'reg, 'rc>( rc: &'a mut handlebars::RenderContext<'reg, 'rc>, mut action: impl FnMut(&mut handlebars::BlockContext<'rc>, bool) -> Result<(), RenderError>,