On Tue, 2014-05-06 at 13:29 +0200, Patrick Ohly wrote:
> On Mon, 2014-05-05 at 14:42 +0200, Patrick Ohly wrote:
> > On Fri, 2014-05-02 at 11:59 +0200, Lukas Zeller wrote:
> > > On 02.05.2014, at 10:38, Patrick Ohly <[email protected]> wrote:
> > > > I noticed another problem with the "use X-ABLabel parameter" approach:
> > > > storing complex strings (spaces, quotation marks) in a parameter value
> > > > is harder.
> > >
> > > That's probably why Apple chose the X-ABLabel property approach. An
> > > unparseable parameter could ruin the real data, a unknown property is
> > > less dangerous.
> > >
> > > > The EDS vCard parser gets it wrong and fails to parse:
> > > >
> > > > X-ABRELATEDNAMES;X-ABLabel=domestic partner:domestic partner
> > > >
> > > > That is valid according to http://tools.ietf.org/html/rfc2425#page-5
> > > > because the space is a SAFE-CHAR and thus may appear in a ptext, but the
> > > > EDS parser does not expect the space. To work around this, we could
> > > > voluntarily quote the string even though it is not required.
> > > >
> > > > Now, the conceptual problem with "X-ABLabel parameter" is that a quoted
> > > > string cannot contain double quotes. It is probably rare that a user
> > > > enters double quotes as part of a label, but it cannot be ruled out
> > > > either. Line breaks are also only allowed in property values and not
> > > > parameter values.
> >
> > I've looked into TMimeDirProfileHandler::generateValue() some more to
> > understand under which circumstances libsynthesis uses quoted strings
> > (with double quotes at start and end) as parameter value. At first
> > glance it doesn't seem to do that at all. Instead special values are
> > escaped with backslash.
> >
> > item29.X-ABLabel:custom-label5\nUmlaut-ä\nSemicolon\;
> > ->
> > X-ABRELATEDNAMES;X-ABLabel=custom-label5\nUmlaut-ä\nSemicolon\;:custom
> > relationship
> >
> > Where is it specified that the backslash escape mechanism can be used in
> > parameter values?
> >
> > http://tools.ietf.org/html/rfc2425#page-5 says:
> >
> >
> > param = param-name "=" param-value *("," param-value)
> >
> > param-name = x-name / iana-token
> >
> > param-value = ptext / quoted-string
> >
> > ptext = *SAFE-CHAR
> >
> > SAFE-CHAR = WSP / %x21 / %x23-2B / %x2D-39 / %x3C-7E / NON-ASCII
> > ; Any character except CTLs, DQUOTE, ";", ":", ","
> >
> > My reading of that is that special characters must not appear in a ptext
> > at all, not even when escaped with backslash. One has to use a quoted
> > string, which (unfortunately) cannot hold all characters either.
>
> Furthermore, folding is not described for parameter values, is it?
>
> X-ABRELATEDNAMES;X-ABLabel="custom-label5 Umlaut ä Semicolon ; Backslash \
> newline tab \t end of label":custom relationship
>
> This is what libsynthesis produces for a long parameter value. The \t
> was part of the original value. With the revised parser/generator it
> just gets passed through.
>
> I think the generator should be changed to not fold a line unless the
> property value has started.
I'm not sure about that anymore. The EDS parser/generator has no
problems with folding inside parameters.
Attached is a patch which does what I had in mind, but we can probably
ignore it unless folding inside parameters really turns out to be wrong
and/or cause problems.
--
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.
diff --git a/src/sysync/mimedirprofile.cpp b/src/sysync/mimedirprofile.cpp
index 83acbca..929ef5c 100644
--- a/src/sysync/mimedirprofile.cpp
+++ b/src/sysync/mimedirprofile.cpp
@@ -2101,6 +2101,7 @@ static void finalizeProperty(
const char *proptext,
string &aString,
TMimeDirMode aMimeMode, // MIME mode (older or newer vXXX format compatibility)
+ size_t foldStartingAt, // First byte offset where folding is allowed.
bool aDoNotFold, // set to prevent folding
bool aDoSoftBreak // set to insert QP-softbreaks when \r is encountered, otherwise do a full hard break (which essentially inserts a space for mimo_old)
)
@@ -2112,6 +2113,7 @@ static void finalizeProperty(
ssize_t foldLoc = -1; // possible break location - linear white space or explicit break indicator
bool explf;
cAppCharP firstunwritten=proptext; // none written yet
+ const char *start = proptext;
while (proptext && (c=*proptext)!=0) {
// remember position of last lwsp (space or TAB)
if (aMimeMode==mimo_old && (c==' ' || c==0x09))
@@ -2142,8 +2144,8 @@ static void finalizeProperty(
llen++;
// explicit linefeed flag
explf=(c=='\n' || c=='\r');
- if (aDoNotFold) {
- // prohibit folding for ugly devices like V3i
+ if (aDoNotFold || (proptext && (proptext - start) < foldStartingAt)) {
+ // prohibit folding for ugly devices like V3i or in the middle of the parameters
if (explf) {
// append what we have until here
n--; // explicit \n or \r is ignored
@@ -3083,9 +3085,11 @@ sInt16 TMimeDirProfileHandler::generateProperty(
// - separate value from property text
proptext+=':';
// - append (probably encoded) values now, always in UTF-8
+ size_t foldStartingAt = proptext.size();
encodeValues(encoding,fDefaultOutCharset,elemtext,proptext,fDoNotFoldContent);
// - fold, copy and terminate (CRLF) property into aString output
- finalizeProperty(proptext.c_str(),aString,aMimeMode,fDoNotFoldContent,encoding==enc_quoted_printable);
+ finalizeProperty(proptext.c_str(),aString,aMimeMode,
+ foldStartingAt, fDoNotFoldContent,encoding==enc_quoted_printable);
// - special case: base64 (but not B) encoded value must have an extra CRLF even if folding is
// disabled, so we need to insert it here (because non-folding mode eliminates it from being
// generated automatically in encodeValues/finalizeProperty)
@@ -3158,7 +3162,7 @@ void TMimeDirProfileHandler::generateMimeDir(TMultiFieldItem &aItem, string &aSt
// - lead-in
s="BEGIN:";
s.append(fVTimeZonePendingProfileP->levelName);
- finalizeProperty(s.c_str(),vtz,fMimeDirMode,false,false);
+ finalizeProperty(s.c_str(),vtz,fMimeDirMode,0,false,false);
// - generate raw string
//%%% endYear is not yet implemented in internalToVTIMEZONE(), fTzIdGenMode has only the olson option for now
internalToVTIMEZONE(*pos, val, getSessionZones(), NULL, startYear, endYear, fProfileCfgP->fTzIdGenMode==tzidgen_olson ? "o" : NULL);
@@ -3170,7 +3174,7 @@ void TMimeDirProfileHandler::generateMimeDir(TMultiFieldItem &aItem, string &aSt
// more than one char = not only a trailing line end
s.assign(val,n,i-n);
// finalize and add property
- finalizeProperty(s.c_str(),vtz,fMimeDirMode,false,false);
+ finalizeProperty(s.c_str(),vtz,fMimeDirMode,0,false,false);
// advance cursor beyond terminating LF
n=i+1;
}
@@ -3178,7 +3182,7 @@ void TMimeDirProfileHandler::generateMimeDir(TMultiFieldItem &aItem, string &aSt
// - lead out
s="END:";
s.append(fVTimeZonePendingProfileP->levelName);
- finalizeProperty(s.c_str(),vtz,fMimeDirMode,false,false);
+ finalizeProperty(s.c_str(),vtz,fMimeDirMode,0,false,false);
} // for
// now insert the VTIMEZONE into the output string (so possibly making it appear BEFORE the
// properties that use TZIDs)
@@ -3231,7 +3235,7 @@ void TMimeDirProfileHandler::generateLevels(
// standard custom level
s="BEGIN:";
s.append(aProfileP->levelName);
- finalizeProperty(s.c_str(),aString,fMimeDirMode,false,false);
+ finalizeProperty(s.c_str(),aString,fMimeDirMode,0,false,false);
// loop through all properties of that level
const TPropertyDefinition *propP = aProfileP->propertyDefs;
#ifndef NO_REMOTE_RULES
@@ -3324,7 +3328,7 @@ void TMimeDirProfileHandler::generateLevels(
// generate level end
s="END:";
s.append(aProfileP->levelName);
- finalizeProperty(s.c_str(),aString,fMimeDirMode,false,false);
+ finalizeProperty(s.c_str(),aString,fMimeDirMode,0,false,false);
} // normal level
} // if level must be generated
} // TMimeDirProfileHandler::generateLevels
_______________________________________________
os-libsynthesis mailing list
[email protected]
http://lists.synthesis.ch/mailman/listinfo/os-libsynthesis