void ExchangeDownload::slotPropFindResult(KIO::Job *job)
{
    kdDebug() << "slotPropFindResult" << endl;

    int error = job->error();
    if(error)
    {
        job->showErrorDialog(0);
        finishUp(ExchangeClient::CommunicationError, job);
        return;
    }

    QDomDocument response = static_cast<KIO::DavJob *>(job)->response();
    kdDebug() << "Response: " << endl;
    kdDebug() << response.toString() << endl;

    QDomElement prop = response.documentElement().namedItem("response")
                       .namedItem("propstat").namedItem("prop").toElement();

    KCal::Event *event = new KCal::Event();

    QDomElement uidElement = prop.namedItem("uid").toElement();
    if(uidElement.isNull())
    {
        kdError() << "Error: no uid in Exchange server reply" << endl;
        finishUp(ExchangeClient::IllegalAppointmentError,
                 "WebDAV server response:\n" + response.toString());
        return;
    }
    event->setUid(uidElement.text());
    // kdDebug() << "Got UID: " << uidElement.text() << endl;

    QString timezoneid = prop.namedItem("timezoneid").toElement().text();
    // kdDebug() << "DEBUG: timezoneid = " << timezoneid << endl;

    QString timezone = prop.namedItem("timezone").toElement().text();
    // kdDebug() << "DEBUG: timezone = " << timezone << endl;

    // mFormat is used for parsing recurrence rules.
    QString localTimeZoneId;
    if(mCalendar)
    {
        mFormat->setTimeZone(mCalendar->timeZoneId(), !mCalendar->isLocalTime());
        localTimeZoneId = mCalendar->timeZoneId();
    }
    else
    {
        localTimeZoneId = "UTC";
        // If no mCalendar, stay in UTC
    }

    QString lastModified = prop.namedItem("lastmodified").toElement().text();
    if(!lastModified.isEmpty())
    {
        QDateTime dt = utcAsZone(QDateTime::fromString(lastModified, Qt::ISODate), localTimeZoneId);
        event->setLastModified(dt);
        kdDebug() << "Got lastModified:" << lastModified << ", " << dt.toString() << endl;
    }

    QString organizer = prop.namedItem("organizer").toElement().text();
    // TODO: Does outlook have a common name? Or does the organizer already contain both?
    event->setOrganizer(organizer);
    // kdDebug() << "Got organizer: " << organizer << endl;

    // Trying to find attendees, not working yet
    QString contact = prop.namedItem("contact").toElement().text();
    //  event->setOrganizer( organizer );
    // kdDebug() << "DEBUG: Got contact: " << contact << endl;

    // This looks promising for finding attendees
    // FIXME: get this to work
    QString to = prop.namedItem("to").toElement().text();
    // kdDebug() << "DEBUG: Got to: " << to << endl;
    QStringList attn = QStringList::split(",", to);   // This doesn't work: there can be commas between ""
    QStringList::iterator it;
    for(it = attn.begin(); it != attn.end(); ++it)
    {
        // kdDebug() << "    attendee: " << (*it) << endl;
        QString name = "";
        // KCal::Attendee* a = new KCal::Attendee( name, email );

        // event->addAttendee( a );
    }

    QString readonly = prop.namedItem("isreadonly").toElement().text();
    event->setReadOnly(readonly == "1");
    kdDebug() << "Got readonly: " << readonly << ":" << (readonly != "0") << endl;

    QString created = prop.namedItem("created").toElement().text();
    if(!created.isEmpty())
    {
        QDateTime dt = utcAsZone(QDateTime::fromString(created, Qt::ISODate),
                                 localTimeZoneId);
        event->setCreated(dt);
        kdDebug() << "got created: " << dt.toString() << endl;
    }

    QString dtstart = prop.namedItem("dtstart").toElement().text();
    if(!dtstart.isEmpty())
    {
        QDateTime dt = utcAsZone(QDateTime::fromString(dtstart, Qt::ISODate),
                                 localTimeZoneId);
        event->setDtStart(dt);
        kdDebug() << "got dtstart: " << dtstart << " becomes in timezone " << dt.toString() << endl;
    }

    QString alldayevent = prop.namedItem("alldayevent").toElement().text();
    bool floats = alldayevent.toInt() != 0;
    event->setFloats(floats);
    kdDebug() << "Got alldayevent: \"" << alldayevent << "\":" << floats << endl;

    QString dtend = prop.namedItem("dtend").toElement().text();
    if(!dtend.isEmpty())
    {
        QDateTime dt = utcAsZone(QDateTime::fromString(dtend, Qt::ISODate),
                                 localTimeZoneId);
        // Outlook thinks differently about floating event timing than libkcal
        if(floats) dt = dt.addDays(-1);
        event->setDtEnd(dt);
        kdDebug() << "got dtend: " << dtend << " becomes in timezone " << dt.toString() << endl;
    }

    QString transparent = prop.namedItem("transparent").toElement().text();
    event->setTransparency(transparent.toInt() > 0 ? KCal::Event::Transparent
                           : KCal::Event::Opaque);
    // kdDebug() << "Got transparent: " << transparent << endl;

    QString description = prop.namedItem("textdescription").toElement().text();
    event->setDescription(description);
    kdDebug() << "Got description: " << description << endl;

    QString subject = prop.namedItem("subject").toElement().text();
    event->setSummary(subject);
    kdDebug() << "Got summary: " << subject << endl;

    QString location =  prop.namedItem("location").toElement().text();
    event->setLocation(location);
    // kdDebug() << "Got location: " << location << endl;

    QString rrule = prop.namedItem("rrule").toElement().text();
    kdDebug() << "Got rrule: " << rrule << endl;
    if(!rrule.isEmpty())
    {
        // Timezone should be handled automatically
        // because we used mFormat->setTimeZone() earlier
        KCal::RecurrenceRule *rr = event->recurrence()->defaultRRule(true);

        if(!rr || !mFormat->fromString(rr, rrule))
        {
            kdError() << "ERROR parsing rrule " << rrule << endl;
        }
    }

    QDomElement keywords = prop.namedItem("Keywords").toElement();
    QStringList categories;
    QDomNodeList list = keywords.elementsByTagNameNS("xml:", "v");
    for(uint i = 0; i < list.count(); i++)
    {
        QDomElement item = list.item(i).toElement();
        categories.append(item.text());
    }
    event->setCategories(categories);
    // kdDebug() << "Got categories: " << categories.join( ", " ) << endl;


    QDomElement exdate = prop.namedItem("exdate").toElement();
    KCal::DateList exdates;
    list = exdate.elementsByTagNameNS("xml:", "v");
    for(uint i = 0; i < list.count(); i++)
    {
        QDomElement item = list.item(i).toElement();
        QDate date = utcAsZone(QDateTime::fromString(item.text(), Qt::ISODate), localTimeZoneId).date();
        exdates.append(date);
        // kdDebug() << "Got exdate: " << date.toString() << endl;
    }
    event->recurrence()->setExDates(exdates);

    // Exchange sentitivity values:
    // 0 None
    // 1 Personal
    // 2 Private
    // 3 Company Confidential
    QString sensitivity = prop.namedItem("sensitivity").toElement().text();
    if(! sensitivity.isNull())
        switch(sensitivity.toInt())
        {
            case 0:
                event->setSecrecy(KCal::Incidence::SecrecyPublic);
                break;
            case 1:
                event->setSecrecy(KCal::Incidence::SecrecyPrivate);
                break;
            case 2:
                event->setSecrecy(KCal::Incidence::SecrecyPrivate);
                break;
            case 3:
                event->setSecrecy(KCal::Incidence::SecrecyConfidential);
                break;
            default:
                kdWarning() << "Unknown sensitivity: " << sensitivity << endl;
        }
    // kdDebug() << "Got sensitivity: " << sensitivity << endl;


    QString reminder = prop.namedItem("reminderoffset").toElement().text();
    // kdDebug() << "Reminder offset: " << reminder << endl;
    if(!reminder.isEmpty())
    {
        // Duration before event in seconds
        KCal::Duration offset(- reminder.toInt());
        KCal::Alarm *alarm = event->newAlarm();
        alarm->setStartOffset(offset);
        alarm->setDisplayAlarm("");
        alarm->setEnabled(true);
        // TODO: multiple alarms; alarm->setType( KCal::Alarm::xxxx );
    }
    /** Create a new alarm which is associated with this incidence */
    //Alarm* newAlarm();
    /** Add an alarm which is associated with this incidence */
    //void addAlarm(Alarm*);

    /** point at some other event to which the event relates */
    //void setRelatedTo(Incidence *relatedTo);
    /** Add an event which is related to this event */
    //void addRelation(Incidence *);

    /** set the list of attachments/associated files for this event */
    //void setAttachments(const QStringList &attachments);

    /** set resources used, such as Office, Car, etc. */
    //void setResources(const QStringList &resources);

    /** set the event's priority, 0 is undefined, 1 highest (decreasing order) */
    //void setPriority(int priority);

    /**
      Add Attendee to this incidence. IncidenceBase takes ownership of the
      Attendee object.
    */

    //void addAttendee(Attendee *a, bool doupdate=true );

    // THE FOLLOWING EVENT PROPERTIES ARE NOT READ

    // Revision ID in webdav is a String, not an int
    /** set the number of revisions this event has seen */
    //void setRevision(int rev);

    // Problem: When you sync Outlook to a Palm, the conduit splits up
    // multi-day events into single-day events WITH ALL THE SAME UID
    // Grrrrrrr.
    if(mCalendar)
    {
        KCal::Event *oldEvent = mCalendar->event(event->uid());
        if(oldEvent)
        {
            kdWarning() << "Already got his event, replace it..." << endl;
            mCalendar->deleteEvent(oldEvent);
        }
        kdDebug() << "ADD EVENT" << endl;
        mCalendar->addEvent(event);
    }
    else
    {
        kdDebug() << "EMIT gotEvent" << endl;
        emit gotEvent(event, static_cast<KIO::DavJob *>(job)->url());
        //    mEvents->append( event );
    }

    decreaseDownloads();
}
void IncidenceConverter::setRecurrence(KCal::Incidence *incidence, ngwt__CalendarItem *item)
{
    kdDebug() << k_funcinfo << endl;
    ngwt__Frequency *freq = 0;
    const KCal::Recurrence *recur = incidence->recurrence();

    if(incidence->doesRecur())
    {
        item->rrule = soap_new_ngwt__RecurrenceRule(soap(), -1);
        item->rrule->frequency = 0; //
        item->rrule->count = 0;
        item->rrule->until = 0; //
        item->rrule->interval = 0; //
        item->rrule->byDay = 0;
        item->rrule->byYearDay = 0;
        item->rrule->byMonthDay = 0;
        item->rrule->byMonth = 0;
        freq = (ngwt__Frequency *)soap_malloc(soap(), sizeof(ngwt__Frequency));
        // interval
        if(recur->frequency() > 1)
        {
            item->rrule->interval = (unsigned long *)soap_malloc(soap(), sizeof(unsigned long *));
            *item->rrule->interval = recur->frequency();
        }
        // end date
        if(recur->duration() > 0)        // number of recurrences. If end date is set we don't use this.
        {
            item->rrule->count = (long unsigned int *)soap_malloc(soap(), sizeof(long unsigned int *));
            *item->rrule->count = recur->duration();
        }
#if LIBKCAL_IS_VERSION( 1, 3, 0 )
        else if(recur->endDateTime().isValid())
#else
        else if(recur->endDate().isValid())
#endif
            item->rrule->until = qDateToString(recur->endDate());
        else // GROUPWISE doesn't accept infinite recurrence so end after GW_MAX_RECURRENCES recurrences
        {
            item->rrule->count = (long unsigned int *)soap_malloc(soap(), sizeof(long unsigned int *));
            *item->rrule->count = GW_MAX_RECURRENCES;
        }

        // recurrence date - try setting it using the recurrence start date - didn't help
        /*    std::string startDate;
            startDate.append( recur->recurStart().date().toString( Qt::ISODate ).utf8() );
            item->rdate = soap_new_ngwt__RecurrenceDateType( soap(), -1 );
            item->rdate->date.push_back( startDate );*/
        // exceptions list - try sending empty list even if no exceptions
#if LIBKCAL_IS_VERSION( 1, 3, 0 )
        KCal::DateList exceptions = recur->exDates();
#else
        KCal::DateList exceptions = incidence->exDates();
#endif
        if(!exceptions.isEmpty())
        {
            item->exdate = soap_new_ngwt__RecurrenceDateType(soap(), -1);
            for(KCal::DateList::ConstIterator it = exceptions.begin(); it != exceptions.end(); ++it)
            {
                std::string startDate;
                startDate.append((*it).toString(Qt::ISODate).utf8());
                item->exdate->date.push_back(startDate);
            }
        }
    }
void IncidenceConverter::setRecurrence( KCal::Incidence * incidence, ngwt__CalendarItem * item )
{
  kDebug() ;
  ngwt__Frequency * freq = 0;
  const KCal::Recurrence * recur = incidence->recurrence();

  if ( incidence->recurs() )
  {
    item->rrule = soap_new_ngwt__RecurrenceRule( soap(), -1 );
    item->rrule->frequency = 0; //
    item->rrule->count = 0;
    item->rrule->until = 0; //
    item->rrule->interval = 0; //
    item->rrule->byDay = 0;
    item->rrule->byYearDay = 0;
    item->rrule->byMonthDay = 0;
    item->rrule->byMonth = 0;
    freq = (ngwt__Frequency *)soap_malloc( soap(), sizeof( ngwt__Frequency ) );
    // interval
    if ( recur->frequency() > 1 ) {
      item->rrule->interval = (unsigned long *)soap_malloc( soap(), sizeof( unsigned long * ) );
      *item->rrule->interval = recur->frequency();
    }
    // end date
    if ( recur->duration() > 0 )     // number of recurrences. If end date is set we don't use this.
    {
      item->rrule->count = (long unsigned int *)soap_malloc( soap(), sizeof( long unsigned int * ) );
      *item->rrule->count = recur->duration();
    }
    else if ( recur->endDateTime().isValid() )
      item->rrule->until = qDateToString( recur->endDate() );
    else // GROUPWISE doesn't accept infinite recurrence so end after GW_MAX_RECURRENCES recurrences
    {
      item->rrule->count = (long unsigned int *)soap_malloc( soap(), sizeof( long unsigned int * ) );
      *item->rrule->count = GW_MAX_RECURRENCES;
    }

    // recurrence date - try setting it using the recurrence start date - didn't help
/*    std::string startDate;
    startDate.append( recur->recurStart().date().toString( Qt::ISODate ).toUtf8().data() );
    item->rdate = soap_new_ngwt__RecurrenceDateType( soap(), -1 );
    item->rdate->date.push_back( startDate );*/
    // exceptions list - try sending empty list even if no exceptions
    KCal::DateList exceptions = recur->exDates();
    if ( !exceptions.isEmpty() )
    {
      item->exdate = soap_new_ngwt__RecurrenceDateType( soap(), -1 );
      for ( KCal::DateList::ConstIterator it = exceptions.constBegin(); it != exceptions.constEnd(); ++it )
      {
        std::string startDate;
        startDate.append( (*it).toString( Qt::ISODate ).toUtf8().data() );
        item->exdate->date.push_back( startDate );
      }
    }
  }

  if ( incidence->recurrenceType() == KCal::Recurrence::rDaily )
  {
    kDebug() <<"incidence recurs daily";
    *freq = Daily;
    item->rrule->frequency = freq;
  }
  else if ( incidence->recurrenceType() == KCal::Recurrence::rWeekly )
  {
    kDebug() <<"incidence recurs weekly";
#if 1 //trying out byDay recurrence
    *freq = Weekly;
    item->rrule->frequency = freq;
    // now change the bitArray of the days of the week that it recurs on to a ngwt__DayOfWeekList *
    QBitArray ba = recur->days();
    ngwt__DayOfYearWeekList * weeklyDays = soap_new_ngwt__DayOfYearWeekList( soap(), -1 );
    for ( int i = 0; i < 7; ++i )
    {
      if ( ba[i] )
      {
        ngwt__DayOfYearWeek * day = soap_new_ngwt__DayOfYearWeek( soap(), -1 );
        day->occurrence = 0;
        switch( i )
        {
          case 0:
            day->__item = Monday;
            break;
          case 1:
            day->__item = Tuesday;
            break;
          case 2:
            day->__item = Wednesday;
            break;
          case 3:
            day->__item = Thursday;
            break;
          case 4:
            day->__item = Friday;
            break;
          case 5:
            day->__item = Saturday;
            break;
          case 6:
            day->__item = Sunday;
            break;
        }
        weeklyDays->day.push_back( day );
      }
    }
    // add the list of days to the recurrence rule
    item->rrule->byDay = weeklyDays;
#endif
  }
  else if ( incidence->recurrenceType() == KCal::Recurrence::rMonthlyDay )
  {
    kDebug() <<"incidence recurs monthly";
    ;
    *freq = Monthly;
    item->rrule->frequency = freq;

    // TODO: translate '3rd wednesday of month' etc into rdates
  }
  else if ( incidence->recurrenceType() == KCal::Recurrence::rYearlyDay )
  {
    kDebug() <<"incidence recurs yearly on day #";
    *freq = Yearly;
    item->rrule->frequency = freq;
    // TODO: translate '1st sunday in may'
    ngwt__DayOfYearList * daysOfYear = soap_new_ngwt__DayOfYearList( soap(), -1 );
    QList<int> rmd;
    rmd = recur->yearMonths();
    daysOfYear->day.push_back( rmd.first() );

    item->rrule->byYearDay = daysOfYear;
    // no need to do MonthList recurrence as these will appear as separate instances when fetched from GW
  }
  else if ( incidence->recurrenceType() == KCal::Recurrence::rYearlyMonth )
  {
    kDebug() <<"incidence recurs yearly on monthday";
    *freq = Yearly;
    item->rrule->frequency = freq;
  }
}