#1171: Use the ical.js implementation for foldline

According to [RFC5545](https://www.rfc-editor.org/rfc/rfc5545#section-3.1):

```
  Note: It is possible for very simple implementations to generate
  improperly folded lines in the middle of a UTF-8 multi-octet
  sequence.  For this reason, implementations need to unfold lines
  in such a way to properly restore the original sequence.
```

It actually happens when an emoji takes the 75th and 76th bit.
This commit is contained in:
Fabrice Mouhartem 2023-10-20 14:41:00 +02:00
parent b9e698ef14
commit 6b7eedde22
1 changed files with 39 additions and 3 deletions

View File

@ -96,6 +96,41 @@ define([
return rrule; return rrule;
}; };
// XXX Below function: from ical.js, should be imported instead.
// XXX However, if it's done, it would be better to refactor the
// XXX export module to directly use ical.js for exporting ICS.
var foldline = function(aLine) {
var foldLength = 75;
var newLineChar = '\r\n';
let result = "";
let line = aLine || "", pos = 0, line_length = 0;
//pos counts position in line for the UTF-16 presentation
//line_length counts the bytes for the UTF-8 presentation
while (line.length) {
let cp = line.codePointAt(pos);
if (cp < 128) {
++line_length;
}
else if (cp < 2048) {
line_length += 2;//needs 2 UTF-8 bytes
}
else if (cp < 65536) {
line_length += 3;
}
else {
line_length += 4; //cp is less than 1114112
}
if (line_length < foldLength + 1) {
pos += cp > 65535 ? 2 : 1;
}
else {
result += newLineChar + " " + line.slice(0, Math.max(0, pos));
line = line.slice(Math.max(0, pos));
pos = line_length = 0;
}
}
return result.slice(newLineChar.length + 1);
};
var addEvent = function (arr, data, recId) { var addEvent = function (arr, data, recId) {
var uid = data.id; var uid = data.id;
@ -105,11 +140,12 @@ define([
var rrule = getRRule(data); var rrule = getRRule(data);
var formatDescription = function(str) { var formatDescription = function(str) {
var result = str.replace(/\n/g, ["\\n"]); var componentName = 'DESCRIPTION:';
var result = componentName + str.replace(/\n/g, ["\\n"]);
// XXX Should use ical.js helper foldline instead ↓ // XXX Should use ical.js helper foldline instead ↓
// XXX https://kewisch.github.io/ical.js/api/ICAL.module_helpers.html#.foldline // XXX https://kewisch.github.io/ical.js/api/ICAL.module_helpers.html#.foldline
// In RFC5545: https://www.rfc-editor.org/rfc/rfc5545#section-3.1 // In RFC5545: https://www.rfc-editor.org/rfc/rfc5545#section-3.1
result = result.replace(/([^\n]{1,74})/g, '$1\n '); result = foldline(result);
return result; return result;
}; };
@ -123,7 +159,7 @@ define([
rrule, rrule,
'SUMMARY:'+ data.title, 'SUMMARY:'+ data.title,
'LOCATION:'+ data.location, 'LOCATION:'+ data.location,
'DESCRIPTION:' + formatDescription(data.body), formatDescription(data.body),
].filter(Boolean)); ].filter(Boolean));
if (Array.isArray(data.reminders)) { if (Array.isArray(data.reminders)) {