Skip to content

Commit c5392c7

Browse files
committedAug 11, 2024·
fix csv escapes
·
v0.35.2v0.3.0
1 parent b6bb982 commit c5392c7

File tree

3 files changed

+19
-4
lines changed

3 files changed

+19
-4
lines changed
 

‎CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- 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.
88
- 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.
99
- fixed a bug where the CSV component would break when the data contained a `#` character.
10+
- properly escape fields in the CSV component to avoid generating invalid CSV files.
1011

1112
## 0.26.0 (2024-08-06)
1213
### Components

‎sqlpage/templates/csv.handlebars

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
{{~#each_row~}}
44
{{~#if (eq @row_index 0)~}}{{! header }}
55
{{~#each this~}}
6-
%22{{! %22 = double-quote}}
7-
{{~url_encode @key~}}
8-
%22
6+
{{~url_encode (csv_escape @key ../../separator)~}}
97
{{~default ../../separator ","~}}
108
{{~/each~}}
119
%0A{{! %0A = newline}}
1210
{{~/if~}}
1311
{{~#each this~}}
14-
%22{{url_encode this}}%22{{default ../../separator ","}}
12+
{{~url_encode (csv_escape this ../../separator)~}}
13+
{{~default ../../separator ","~}}
1514
{{~/each~}}
1615
%0A
1716
{{~/each_row~}}

‎src/template_helpers.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub fn register_all_helpers(h: &mut Handlebars<'_>, config: &AppConfig) {
5252
register_helper(h, "typeof", typeof_helper as H);
5353
register_helper(h, "rfc2822_date", rfc2822_date_helper as EH);
5454
register_helper(h, "url_encode", url_encode_helper as H);
55+
register_helper(h, "csv_escape", csv_escape_helper as HH);
5556
}
5657

5758
fn stringify_helper(v: &JsonValue) -> JsonValue {
@@ -282,6 +283,20 @@ fn url_encode_helper(v: &JsonValue) -> JsonValue {
282283
.into()
283284
}
284285

286+
// Percent-encode a string
287+
fn csv_escape_helper(v: &JsonValue, separator: &JsonValue) -> JsonValue {
288+
let as_str = match v {
289+
JsonValue::String(s) => s,
290+
other => &other.to_string(),
291+
};
292+
let separator = separator.as_str().unwrap_or(",");
293+
if as_str.contains(separator) || as_str.contains('"') || as_str.contains('\n') {
294+
format!(r#""{}""#, as_str.replace('"', r#""""#)).into()
295+
} else {
296+
as_str.to_owned().into()
297+
}
298+
}
299+
285300
fn with_each_block<'a, 'reg, 'rc>(
286301
rc: &'a mut handlebars::RenderContext<'reg, 'rc>,
287302
mut action: impl FnMut(&mut handlebars::BlockContext<'rc>, bool) -> Result<(), RenderError>,

0 commit comments

Comments
 (0)
Please sign in to comment.