Bug 124820

Summary: Calender iCal file renders corrupt when changing the items time
Product: [Applications] korganizer Reporter: Paul Koster <p.koster>
Component: generalAssignee: Reinhold Kainhofer <reinhold>
Status: RESOLVED FIXED    
Severity: crash    
Priority: NOR    
Version: 3.5   
Target Milestone: ---   
Platform: Fedora RPMs   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Paul Koster 2006-04-03 11:53:53 UTC
Version:           3.5 (using KDE KDE 3.5.1)
Installed from:    Fedora RPMs
Compiler:          gcc 4.1.0 
OS:                Linux

When changing a calender item's time, the resulting VEVENT block contains an invalid DTEND clause.

Example of corrupt rendered item: 

BEGIN:VEVENT
DTSTAMP:20060403T105525Z
ORGANIZER;CN=Paul Koster:MAILTO:p.koster@mailcss.com
CREATED:20060127T142851Z
UID:libkcal-2061410872.1011
SEQUENCE:1
LAST-MODIFIED:20060403T105524Z
SUMMARY:KEMA Audit
CLASS:PUBLIC
PRIORITY:5
DTSTART:20060407T090000Z
DTEND;VALUE=DATE:00090029
TRANSP:OPAQUE
END:VEVENT

The resulting console message when starting korganizer is:

QDate::setYMD: Invalid date 1754-00-29

One has to manually change the corresponding item to correct the issue.
Comment 1 Reinhold Kainhofer 2006-04-03 12:07:41 UTC
Am Montag, 3. April 2006 11:53 schrieb Paul Koster:
> When changing a calender item's time, the resulting VEVENT block contains
> an invalid DTEND clause.


1) Do you have the original event from the .ics file, too? 
2) How exactly do you change the time (i.e. do you move the item in the agenda 
view, do you resize it , do you drag it to a different day in the small 
calendar on the left, do you use the editor dialog, etc.?)

Cheers,
Reinhold

BTW: Here  I don't have any problems...
Comment 2 Paul Koster 2006-04-03 12:25:37 UTC
I can reproduce the bug by performing the following steps:

1) Create new calender in local file, iCal type
2) Create an item with NO time associated to it, the file looks like:

BEGIN:VCALENDAR
PRODID:-//K Desktop Environment//NONSGML libkcal 3.5//EN
VERSION:2.0
BEGIN:VEVENT
DTSTAMP:20060403T122200Z
ORGANIZER;CN=Paul Koster:MAILTO:p.koster@mailcss.com
CREATED:20060403T122158Z
UID:libkcal-1337979303.941
SEQUENCE:0
LAST-MODIFIED:20060403T122158Z
SUMMARY:test event
CLASS:PUBLIC
PRIORITY:5
DTSTART;VALUE=DATE:20060405
DTEND;VALUE=DATE:20060406
TRANSP:OPAQUE
END:VEVENT

END:VCALENDAR

3) Edit the item in the editor and associate a time with it, e.g. 9:00 AM. The file looks then:

BEGIN:VCALENDAR
PRODID:-//K Desktop Environment//NONSGML libkcal 3.5//EN
VERSION:2.0
BEGIN:VEVENT
DTSTAMP:20060403T122331Z
ORGANIZER;CN=Paul Koster:MAILTO:p.koster@mailcss.com
CREATED:20060403T122158Z
UID:libkcal-1337979303.941
SEQUENCE:1
LAST-MODIFIED:20060403T122330Z
SUMMARY:test event
CLASS:PUBLIC
PRIORITY:5
DTSTART:20060405T090000Z
DTEND;VALUE=DATE:00090016
TRANSP:OPAQUE
END:VEVENT

END:VCALENDAR

Which results in an invalid 'date' interpretation upon restart of korganizer.
Comment 3 Reinhold Kainhofer 2006-04-03 12:36:42 UTC
Ah, can reproduce it now. The crucial thing is that the item didn't have a time associated before the change.

Cheers,
Reinhold
Comment 4 Bram Schoenmakers 2006-10-29 20:42:01 UTC
SVN commit 600170 by bram:

Fix commit 429762 by djarvie: do not write bogus data as DTEND value, but skip the property altogether.

The readEvent() has been adapted in case when the DTEND is not in the event, it will be initialized with the same value as DTSTART then.

BUG:124820



 M  +11 -1     icalformatimpl.cpp  


--- branches/KDE/3.5/kdepim/libkcal/icalformatimpl.cpp #600169:600170
@@ -195,14 +195,15 @@
 //      if (event->dtEnd().date() != event->dtStart().date()) {
         // +1 day because end date is non-inclusive.
         end = writeICalDate( event->dtEnd().date().addDays( 1 ) );
+        icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
 //      }
     } else {
 //      kdDebug(5800) << " Event " << event->summary() << " has time." << endl;
       if (event->dtEnd() != event->dtStart()) {
         end = writeICalDateTime(event->dtEnd());
+        icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
       }
     }
-    icalcomponent_add_property(vevent,icalproperty_new_dtend(end));
   }
 
 // TODO: resources
@@ -950,6 +951,8 @@
   QStringList categories;
   icalproperty_transp transparency;
 
+  bool dtEndProcessed = false;
+
   while (p) {
     icalproperty_kind kind = icalproperty_isa(p);
     switch (kind) {
@@ -968,6 +971,7 @@
           event->setDtEnd(readICalDateTime(icaltime, tz));
           event->setFloats( false );
         }
+        dtEndProcessed = true;
         break;
 
       case ICAL_RELATEDTO_PROPERTY:  // related event (parent)
@@ -993,6 +997,12 @@
     p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY);
   }
 
+  // according to rfc2445 the dtend shouldn't be written when it equals
+  // start date. so assign one equal to start date.
+  if ( !dtEndProcessed ) {
+    event->setDtEnd( event->dtStart() );
+  }
+
   QString msade = event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT");
   if (!msade.isNull()) {
     bool floats = (msade == QString::fromLatin1("TRUE"));
Comment 5 David Jarvie 2006-10-29 23:16:24 UTC
On Sunday 29 October 2006 19:41, Bram Schoenmakers wrote:
> SVN commit 600170 by bram:
>
> The readEvent() has been adapted in case when the DTEND is not in the
> event, it will be initialized with the same value as DTSTART then.
>
> BUG:124820
>
>
>
>  M  +11 -1     icalformatimpl.cpp
>
>
> --- branches/KDE/3.5/kdepim/libkcal/icalformatimpl.cpp #600169:600170
> @@ -950,6 +951,8 @@
>    QStringList categories;
>    icalproperty_transp transparency;
>
> +  bool dtEndProcessed = false;
> +
>    while (p) {
>      icalproperty_kind kind = icalproperty_isa(p);
>      switch (kind) {
> @@ -968,6 +971,7 @@
>            event->setDtEnd(readICalDateTime(icaltime, tz));
>            event->setFloats( false );
>          }
> +        dtEndProcessed = true;
>          break;
>
>        case ICAL_RELATEDTO_PROPERTY:  // related event (parent)
> @@ -993,6 +997,12 @@
>      p = icalcomponent_get_next_property(vevent,ICAL_ANY_PROPERTY);
>    }
>
> +  // according to rfc2445 the dtend shouldn't be written when it equals
> +  // start date. so assign one equal to start date.
> +  if ( !dtEndProcessed ) {
> +    event->setDtEnd( event->dtStart() );
> +  }
> +
>    QString msade =
> event->nonKDECustomProperty("X-MICROSOFT-CDO-ALLDAYEVENT"); if
> (!msade.isNull()) {
>      bool floats = (msade == QString::fromLatin1("TRUE"));


You have to check whether a duration is specified before calling setDtEnd(), 
since the latter overrides any duration which was set in readIncidence().