winevent.cpp

来自「funambol window mobile客户端源代码」· C++ 代码 · 共 878 行 · 第 1/2 页

CPP
878
字号
    //
    // Conversion: vObject -> WinEvent.
    // --------------------------------
    // Note: properties found are added to the propertyMap, so that the 
    //       map will contain only parsed properties after this process.
    //
    if(element = getVObjectPropertyValue(vo, L"SUMMARY")) {
        setProperty(L"Subject", element);
    }
    if(element = getVObjectPropertyValue(vo, L"LOCATION")) {
        setProperty(L"Location", element);
    }
    if(element = getVObjectPropertyValue(vo, L"DESCRIPTION")) {
        setProperty(L"Body", element);
    }
    if(element = getVObjectPropertyValue(vo, L"X-FUNAMBOL-FOLDER")) {
        setProperty(L"Folder", element);
    }

    //
    // DTSTART, DTEND:
    // Set the start and end date. If the start is 00:00 and end is 23:59 the appointment is decided to be
    // an all day event. So the AllDayEvent property is set to '1' in the propertyMap.
    //
    if(element = getVObjectPropertyValue(vo, L"DTSTART")){
        startDateValue = element;
        stringTimeToDouble(element, &startDate);            // 'startDate' will be used also for RRULE parsing
    }
    if(element = getVObjectPropertyValue(vo, L"DTEND")) {
        endDateValue = element;
        stringTimeToDouble(element, &endDate);
    }

    if (startDate && endDate) {
        // ALL-DAY EVENT
        bool isAllDay = false;
        if(element = getVObjectPropertyValue(vo, L"X-FUNAMBOL-ALLDAY")){
            isAllDay = wcscmp(element, L"1")?  false : true;
        }
        if (!isAllDay) {
            // All-day check #2: interval [00:00 - 23:59]
            isAllDay = isAllDayInterval(startDate, endDate);
        }
        if (!isAllDay) {
            // All-day check #3: format "yyyyMMdd"
            if (startDateValue.size() == 8 && endDateValue.size() == 8 ) {
                isAllDay = true;
            }
        }

        if (isAllDay) {
            // Safe check on endDate: min value is 'startDate + 1'
            if (endDate <= startDate) {
                endDate = startDate + 1;
            }
            
            // for EndDates like "20071121T235900": we convert into "20071122"
            double endDateTime = endDate - (int)endDate;
            if (endDateTime > 0.9) {
                endDate = (int)endDate + 1;
            }

            // Format dates like: "yyyyMMdd"
            doubleToStringTime(endDateValue,   endDate,   true);
            doubleToStringTime(startDateValue, startDate, true);

        }
        setProperty(L"Start",       startDateValue       );
        setProperty(L"End",         endDateValue         );
        setProperty(L"AllDayEvent", isAllDay? L"1" : L"0");
    }


    if(element = getVObjectPropertyValue(vo, L"X-MICROSOFT-CDO-BUSYSTATUS")) {
        setProperty(L"BusyStatus", element);
    }
    if(element = getVObjectPropertyValue(vo, L"CATEGORIES")) {
        setProperty(L"Categories", element);
    }
    if (element = getVObjectPropertyValue(vo, L"CLASS")) {
        WCHAR tmp[10];
        if (!wcscmp(element, TEXT("CONFIDENTIAL")) ) {
            wsprintf(tmp, TEXT("%i"), winConfidential);     // Confidential = 3
        }
        else if (!wcscmp(element, TEXT("PRIVATE")) ) {
            wsprintf(tmp, TEXT("%i"), winPrivate);          // Private = 2
        }
        else {
            wsprintf(tmp, TEXT("%i"), winNormal);           // Normal = 0
        }
        setProperty(L"Sensitivity", tmp);
    }
    if(element = getVObjectPropertyValue(vo, L"PRIORITY")) {
        setProperty(L"Importance", element);
    }
    if(element = getVObjectPropertyValue(vo, L"STATUS")) {
        setProperty(L"MeetingStatus", element);
    }
    if(element = getVObjectPropertyValue(vo, L"X-MICROSOFT-CDO-REPLYTIME")) {
        setProperty(L"ReplyTime", element);
    }


    // AALARM
    // The value consists of: RunTime, SnoozeTime, RepeatCount, AudioContent
    if(element = getVObjectPropertyValue(vo, L"AALARM")) {
        WCHAR tmp[10];
        WCHAR* runTimeValue = vo->getProperty(TEXT("AALARM"))->getPropComponent(1);
        if (wcslen(runTimeValue) > 0) {
            setProperty(L"ReminderSet", L"1");
            DATE runTime = 0;
            stringTimeToDouble(runTimeValue, &runTime);

            long minBeforeEvent = round((startDate - runTime) * 1440);
            // Safety check: values < 0 not accepted.
            if (minBeforeEvent < 0) {
                minBeforeEvent = 0;
            }
            wsprintf(tmp, TEXT("%i"), minBeforeEvent);
            setProperty(L"ReminderMinutesBeforeStart", tmp);

            // Reminder sound file path
            WCHAR* filePath = vo->getProperty(TEXT("AALARM"))->getPropComponent(4);
            if (filePath && wcslen(filePath)>0) {
                setProperty(L"ReminderSoundFile", filePath);
            }
            else {
                setProperty(L"ReminderSoundFile", L"");
            }
        }
        else {
            // RunTime not found -> no reminder
            setProperty(L"ReminderSet", L"0");
        }
    }
    else {
        // AALARM not found -> reset reminder!
        // Note: this is done for compatibility with most devices: if alarm not set
        //       AALARM property is not sent.
        setProperty(L"ReminderSet", L"0");
    }


    if ( (element = getVObjectPropertyValue(vo, L"RRULE")) && 
         (wcslen(element) > 0) ) {
        setProperty(L"IsRecurring", L"1");

        // RRULE -> Recurrence pattern
        // Fill recPattern propertyMap.
        recPattern.setStartDate(startDate);
        recPattern.parse(element);

        // EXDATE -> fill excludeDate list
        VProperty* vprop = vo->getProperty(L"EXDATE");
        if(vprop) {
            for (int i=0; element = vprop->getValue(i); i++) {
                if (wcslen(element) > 0) {
                    excludeDate.push_back(element);
                }
            }
        }
        // RDATE -> fill includeDate list
        vprop = vo->getProperty(L"RDATE");
        if(vprop) {
            for (int i=0; element = vprop->getValue(i); i++) {
                if (wcslen(element) > 0) {
                    includeDate.push_back(element);
                }
            }
        }

        // TIMEZONE
        bool tzFound = parseTimezone(vo);
        useTimezone = tzFound;
        getRecPattern()->setUseTimezone(tzFound);

    }
    else {
        // Not recurring.
        setProperty(L"IsRecurring", L"0");
    }

    //
    // TODO: parse ATTENDEES and fill recipients list
    //

    //
    // ---- Other Funambol defined properties ----
    // Support for other fields that don't have a
    // specific correspondence in vCalendar.
    if (element = getVObjectPropertyValue(vo, L"X-FUNAMBOL-BILLINGINFO")) {
        setProperty(TEXT("BillingInformation"), element);
    }
    if(element = getVObjectPropertyValue(vo, L"X-FUNAMBOL-COMPANIES")) {
        setProperty(L"Companies", element);
    }
    if(element = getVObjectPropertyValue(vo, L"X-FUNAMBOL-MILEAGE")) {
        setProperty(L"Mileage", element);
    }
    if(element = getVObjectPropertyValue(vo, L"X-FUNAMBOL-NOAGING")) {
        setProperty(L"NoAging", element);
    }
    if(element = getVObjectPropertyValue(vo, L"X-FUNAMBOL-AALARMOPTIONS")) {
        setProperty(L"ReminderOptions", element);
    }

    return 0;
}


// Utility to check the productID and version of VObject passed.
bool WinEvent::checkVCalendarTypeAndVersion(VObject* vo) {

    WCHAR* prodID  = vo->getProdID();
    WCHAR* version = vo->getVersion();
    
    if (!prodID) {
        LOG.error(ERR_ITEM_VOBJ_TYPE_NOTFOUND, L"VCALENDAR");
        return false;
    }
    if (wcscmp(prodID, L"VCALENDAR")) {
        LOG.error(ERR_ITEM_VOBJ_WRONG_TYPE, prodID, L"VCALENDAR");
        return false;
    }

    if (!version) {
        // Just log a warning...
        LOG.info(INFO_ITEM_VOBJ_VERSION_NOTFOUND, VCALENDAR_VERSION);
    }
    else if (wcscmp(version, VCALENDAR_VERSION)) {
        // Just log a warning...
        LOG.info(INFO_ITEM_VOBJ_WRONG_VERSION, version, VCALENDAR_VERSION);
    }
    return true;
}



WinRecurrence* WinEvent::getRecPattern() {
    return &recPattern;
}

exceptionList* WinEvent::getExcludeDates() {
    return &excludeDate;
}

exceptionList* WinEvent::getIncludeDates() {
    return &includeDate;
}

recipientList* WinEvent::getRecipients() {
    return &recipients;
}



const TIME_ZONE_INFORMATION* WinEvent::getTimezone() {
    
    if (useTimezone) {
        return &tzInfo;
    }
    return NULL;
}

void WinEvent::setTimezone(const TIME_ZONE_INFORMATION* tz) {
    
    if (tz) {
        // Copy all values.
        tzInfo.Bias         = tz->Bias;
        tzInfo.DaylightBias = tz->DaylightBias;
        tzInfo.DaylightDate = tz->DaylightDate;
        tzInfo.StandardBias = tz->StandardBias;
        tzInfo.StandardDate = tz->StandardDate;
        
        //wsprintf(tzInfo.DaylightName, TEXT("%s"), tz->DaylightName);
        //wsprintf(tzInfo.StandardName, TEXT("%s"), tz->StandardName);
        wcsncpy(tzInfo.DaylightName, tz->DaylightName, 32);
        wcsncpy(tzInfo.StandardName, tz->StandardName, 32);

        // use the method, to access right specialized object.
        WinRecurrence* rec = getRecPattern();
        if (rec) { rec->setUseTimezone(true); }
        useTimezone = true;
    }
}

bool WinEvent::hasTimezone() {
    return useTimezone;
}



bool WinEvent::parseTimezone(VObject* vo) {

    bool found = false;
    WCHAR* element = NULL;

    if ((element = getVObjectPropertyValue(vo, L"TZ")) && wcslen(element) > 0) {
        
        int bias = parseBias(element);

        wstring dstFlag, dstOffset, standardName, daylightName;
        list<wstring> daylightDates;
        list<wstring> standardDates;

        //
        // Search all DAYLIGHT properties (one for every year)
        //
        for(int i=0; i < vo->propertiesCount(); i++) {

            VProperty* vp = vo->getProperty(i);
            if (!wcscmp(vp->getName(), TEXT("DAYLIGHT"))) {
                // Found a DAYLIGHT property. Many props are redundant, now are overwritten.
                if (element = vp->getPropComponent(1)) { dstFlag   = element;              }
                if (element = vp->getPropComponent(2)) { dstOffset = element;              }
                if (element = vp->getPropComponent(3)) { daylightDates.push_back(element); }
                if (element = vp->getPropComponent(4)) { standardDates.push_back(element); }
                if (element = vp->getPropComponent(5)) { standardName = element;           }
                if (element = vp->getPropComponent(6)) { daylightName = element;           }
            }
            // - to be faster? -
            //else if (!wcscmp(vp->getName(), TEXT("VEVENT"))) {
            //    break;
            //}
        }

        //
        // If we have all required data, fill the tzInfo structure.
        //
        if (dstFlag == TEXT("FALSE")) {
            // Easy timezone, no DST
            found = true;
            tzInfo.Bias         = bias;
            tzInfo.StandardBias = 0;        // Cannot retrieve it, assume = 0 (usually is 0)
            tzInfo.DaylightBias = -60;     // most of the tiemzone is -60. only 1 is not (baghdad)
            memset((void*)(&tzInfo.DaylightDate), 0, sizeof(SYSTEMTIME));
            memset((void*)(&tzInfo.StandardDate) , 0, sizeof(SYSTEMTIME));                                  
            wcsncpy(tzInfo.StandardName, standardName.c_str(), 32);
            wcsncpy(tzInfo.DaylightName, daylightName.c_str(), 32);
        }
        else if (dstFlag.size() && dstOffset.size() && daylightDates.size() && standardDates.size() ) {
            // Standard timezone, the DST rules are extracted from list of dates
            // >> Bias = -TZ
            // >> StandardBias = 0  (Cannot retrieve it, assume = 0 as usually is 0)
            // >> DaylightBias = - (DSTOffset + Bias)
            bool rightValue = true;
            found = true;
            tzInfo.Bias         = bias;
            tzInfo.StandardBias = 0;
            tzInfo.DaylightBias = parseBias(dstOffset.c_str()) - bias;
            tzInfo.DaylightDate = getTzRuleFromDates(daylightDates, &rightValue);
            tzInfo.StandardDate = getTzRuleFromDates(standardDates, &rightValue);
            wcsncpy(tzInfo.StandardName, standardName.c_str(), 32);
            wcsncpy(tzInfo.DaylightName, daylightName.c_str(), 32);
        }
    }
    else {
        // No timezone received.
        found = false;
    }

    return found;
}


void WinEvent::getIntervalOfRecurrence(int* yearBegin, int* yearEnd) {

    wstring element;
    if (getProperty(L"Start", element)) {
        if (element.size() >= 4) {
            swscanf(element.c_str(), L"%4d", yearBegin);
        }

        if (getRecPattern()->getProperty(L"NoEndDate", element) && (element == L"0")) {
            if (getRecPattern()->getProperty(L"PatternEndDate", element)) {
                if (element.size() >= 4) {
                    swscanf(element.c_str(), L"%4d", yearEnd);
                }
            }
        }
    }
}



long WinEvent::getCRC() {

    wstring values;

    // Event props
    mapIterator it = propertyMap.begin();
    while (it != propertyMap.end()) {
        values.append(it->second);
        it ++;
    }

    // Append rec props only if recurring
    wstring isRec;
    if (getProperty(TEXT("IsRecurring"), isRec)) {
        if (isRec == TEXT("1")) {

            // note: use 'getRecPattern()' to retrieve the correct recPattern object
            it = getRecPattern()->propertyMap.begin();
            while (it != getRecPattern()->propertyMap.end()) {
                values.append(it->second);
                it ++;
            }

            // Exceptions
            exceptionsIterator ex = excludeDate.begin();
            while (ex != excludeDate.end()) {
                values.append(*ex);
                ex ++;
            }
            ex = includeDate.begin();
            while (ex != includeDate.end()) {
                values.append(*ex);
                ex ++;
            }
        }
    }


    const WCHAR* s = values.c_str();
    unsigned long crc32 = 0;
    unsigned long dwErrorCode = NO_ERROR;
    unsigned char byte = 0;

    crc32 = 0xFFFFFFFF;
    while(*s != TEXT('\0')) {
        byte = (unsigned char) *s;
        crc32 = ((crc32) >> 8) ^ crc32Table[(byte) ^ ((crc32) & 0x000000FF)];
        s++;
    }
    crc32 = ~crc32;

    return crc32;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?