/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is OEone Calendar Code, released October 31st, 2001. * * The Initial Developer of the Original Code is * OEone Corporation. * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): Mostafa Hosseini * Gary Frederick * ArentJan Banck * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include // for atol #include "oeICalEventImpl.h" #include "nsMemory.h" #include "nsCOMPtr.h" #include "plbase64.h" #include "nsMsgCompCID.h" #include "nsAbBaseCID.h" #include "nsIAbCard.h" #include "nsIMsgAttachment.h" #define strcasecmp strcmp #define RECUR_NONE 0 #define RECUR_DAILY 1 #define RECUR_WEEKLY 2 #define RECUR_MONTHLY_MDAY 3 #define RECUR_MONTHLY_WDAY 4 #define RECUR_YEARLY 5 #define XPROP_SYNCID "X-MOZILLA-SYNCID" #define XPROP_LASTALARMACK "X-MOZILLA-LASTALARMACK" #define XPROP_RECURUNITS "X-MOZILLA-RECUR-DEFAULT-UNITS" #define XPROP_RECURINTERVAL "X-MOZILLA-RECUR-DEFAULT-INTERVAL" #define XPROP_ALARMUNITS "X-MOZILLA-ALARM-DEFAULT-UNITS" #define XPROP_ALARMLENGTH "X-MOZILLA-ALARM-DEFAULT-LENGTH" #define DEFAULT_ALARM_UNITS "minutes" #define DEFAULT_ALARM_LENGTH 15 #define DEFAULT_RECUR_UNITS "weeks" char *EmptyReturn() { return (char*) nsMemory::Clone( "", 1 ); } icaltimetype ConvertFromPrtime( PRTime indate ) { icaltimetype outdate = icaltime_null_time(); PRExplodedTime ext; PRInt64 indateinusec, usecpermsec; LL_I2L( usecpermsec, PR_USEC_PER_MSEC ); LL_MUL( indateinusec, indate, usecpermsec ); PR_ExplodeTime( indateinusec, PR_LocalTimeParameters, &ext); outdate.year = ext.tm_year; outdate.month = ext.tm_month + 1; outdate.day = ext.tm_mday; outdate.hour = ext.tm_hour; outdate.minute = ext.tm_min; outdate.second = ext.tm_sec; if( ext.tm_year <= 1969 && ext.tm_params.tp_dst_offset == 3600 )//Assume that daylight time saving was not in effect before 1970 icaltime_adjust( &outdate, 0, -1, 0, 0 ); return outdate; } PRTime ConvertToPrtime ( icaltimetype indate ) { PRExplodedTime ext; ext.tm_year = indate.year; ext.tm_month = indate.month - 1; ext.tm_mday = indate.day; ext.tm_hour = indate.hour; ext.tm_min = indate.minute; ext.tm_sec = indate.second; ext.tm_usec = 0; ext.tm_params.tp_gmt_offset = 0; ext.tm_params.tp_dst_offset = 0; PRTime result = PR_ImplodeTime( &ext ); PR_ExplodeTime( result, PR_LocalTimeParameters, &ext); if( ext.tm_year <= 1969 && ext.tm_params.tp_dst_offset == 3600 ) //Assume that daylight time saving was not in effect before 1970 ext.tm_params.tp_dst_offset = 0; ext.tm_year = indate.year; ext.tm_month = indate.month - 1; ext.tm_mday = indate.day; ext.tm_hour = indate.hour; ext.tm_min = indate.minute; ext.tm_sec = indate.second; ext.tm_usec = 0; result = PR_ImplodeTime( &ext ); PRInt64 usecpermsec; LL_I2L( usecpermsec, PR_USEC_PER_MSEC ); LL_DIV( result, result, usecpermsec ); return result; } extern "C" { #include "token.h" } void GenerateUUID(char *output) { uuid_state state; uuid_t uuid; create_uuid_state(&state); create_token(&state, &uuid); format_token(output, &uuid); } ////////////////////////////////////////////////// // UTF-8 functions ////////////////////////////////////////////////// // IsValidUTF scans a string and checks if it is UTF-compliant // Most problems seem to come from 8-bit characters that are not ASCII with a value > 0x80 PRBool IsValidUTF8(const char* aBuffer) { const char *c = aBuffer; const char *end = aBuffer + strlen(aBuffer); const char *lastchar = c; // pre-initialize in case of 0-length buffer PRUint32 ucs2bytes = 0; PRUint32 utf8bytes = 0; while (c < end && *c) { lastchar = c; ucs2bytes++; if ( (*c & 0x80) == 0x00 ) // ASCII c++; else if ( (*c & 0xE0) == 0xC0 ) // 2 byte c += 2; else if ( (*c & 0xF0) == 0xE0 ) // 3 byte c += 3; else if ( (*c & 0xF8) == 0xF0 ) // 4 byte c += 4; else if ( (*c & 0xFC) == 0xF8 ) // 5 byte c += 5; else if ( (*c & 0xFE) == 0xFC ) // 6 byte c += 6; else { break; // Otherwise we go into an infinite loop. But what happens now? } } if (c != end) { #ifdef ICAL_DEBUG_ALL printf( "IsValidUTF8 Invalid UTF-8 string \"%s\"\n", aBuffer ); #endif utf8bytes = 0; return false; } utf8bytes = c - aBuffer; return true; } // strForceUTF8 checks if a string is UTF-8 encoded, and if not assumes it made from 8-bit characters. // If not UTF-8, all non-ASCII characters are replaced with '?' // TODO: write or hook a converter to convert non-ASCII to UTF-8 const char* strForceUTF8(const char * str) { #define CHAR_INVALID '?' const char* result = str; if (!IsValidUTF8( result ) ) { // make sure there are only ASCII chars in the string char *p = (char *)result; for( int i=0; '\0' != p[i]; i++ ) if(!( (p[i] & 0x80) == 0x00) ) p[i] = CHAR_INVALID; } return result; } #ifdef ICAL_DEBUG int gEventCount = 0; int gEventDisplayCount = 0; #endif ////////////////////////////////////////////////// // ICalEvent Factory ////////////////////////////////////////////////// /* Implementation file */ NS_IMPL_ISUPPORTS1(oeICalEventImpl, oeIICalEvent) nsresult NS_NewICalEvent( oeIICalEvent** inst ) { NS_PRECONDITION(inst != nsnull, "null ptr"); if (! inst) return NS_ERROR_NULL_POINTER; *inst = new oeICalEventImpl(); if (! *inst) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*inst); return NS_OK; } oeICalEventImpl::oeICalEventImpl() { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::oeICalEventImpl(): %d\n", ++gEventCount ); #endif /* member initializers and constructor code */ nsresult rv; if( NS_FAILED( rv = NS_NewDateTime((oeIDateTime**) &m_start ))) { m_start = nsnull; } if( NS_FAILED( rv = NS_NewDateTime((oeIDateTime**) &m_end ))) { m_end = nsnull; } if( NS_FAILED( rv = NS_NewDateTime((oeIDateTime**) &m_stamp ))) { m_stamp = nsnull; } if( NS_FAILED( rv = NS_NewDateTime((oeIDateTime**) &m_recurend ))) { m_recurend = nsnull; } if( m_stamp ) { PRInt64 nowinusec = PR_Now(); PRExplodedTime ext; PR_ExplodeTime( nowinusec, PR_GMTParameters, &ext); m_stamp->m_datetime.year = ext.tm_year; m_stamp->m_datetime.month = ext.tm_month + 1; m_stamp->m_datetime.day = ext.tm_mday; m_stamp->m_datetime.hour = ext.tm_hour; m_stamp->m_datetime.minute = ext.tm_min; m_stamp->m_datetime.second = ext.tm_sec; m_stamp->m_datetime.is_utc = true; } m_id = nsnull; m_title.SetIsVoid(true); m_description.SetIsVoid(true); m_location.SetIsVoid(true); m_category.SetIsVoid(true); m_url.SetIsVoid(true); m_priority = 0; m_method = 0; m_status = 0; m_isprivate = true; m_syncid = nsnull; m_allday = false; m_hasalarm = false; m_alarmlength = DEFAULT_ALARM_LENGTH; m_alarmemail = nsnull; m_inviteemail = nsnull; m_recurinterval = 1; m_recurcount = 0; m_recur = false; m_recurforever = true; m_alarmunits = nsnull; m_recurunits = nsnull; m_recurweekdays = 0; m_recurweeknumber = 0; m_lastalarmack = icaltime_null_time(); m_duration = icaldurationtype_null_duration(); SetAlarmUnits( DEFAULT_ALARM_UNITS ); SetRecurUnits( DEFAULT_RECUR_UNITS ); SetSyncId( "" ); NS_NewISupportsArray(getter_AddRefs(m_attachments)); NS_NewISupportsArray(getter_AddRefs(m_contacts)); } oeICalEventImpl::~oeICalEventImpl() { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::~oeICalEventImpl(): %d\n", --gEventCount ); #endif /* destructor code */ if( m_id ) nsMemory::Free( m_id ); if( m_alarmunits ) nsMemory::Free( m_alarmunits ); if( m_alarmemail ) nsMemory::Free( m_alarmemail ); if( m_inviteemail ) nsMemory::Free( m_inviteemail ); if( m_recurunits ) nsMemory::Free( m_recurunits ); if( m_syncid ) nsMemory::Free( m_syncid ); if( m_start ) m_start->Release(); if( m_end ) m_end->Release(); if( m_stamp ) m_stamp->Release(); if( m_recurend ) m_recurend->Release(); for( int i=0; im_datetime, before ) < 0 ) { *retval = ConvertToPrtime( m_start->m_datetime ); *isvalid = true; } return NS_OK; } //for recurring events icalcomponent *vcalendar = AsIcalComponent(); if ( !vcalendar ) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::GetPreviousOccurrence() failed!\n" ); #endif return NS_OK; } icalcomponent *vevent = icalcomponent_get_first_component( vcalendar, ICAL_VEVENT_COMPONENT ); icalproperty *prop = icalcomponent_get_first_property( vevent, ICAL_RRULE_PROPERTY ); if ( prop != 0) { struct icalrecurrencetype recur = icalproperty_get_rrule(prop); // printf("#### %s\n",icalrecurrencetype_as_string(&recur)); icalrecur_iterator* ritr = icalrecur_iterator_new(recur,m_start->m_datetime); struct icaltimetype next; for(next = icalrecur_iterator_next(ritr); !icaltime_is_null_time(next); next = icalrecur_iterator_next(ritr)){ next.is_date = false; next = icaltime_normalize( next ); // printf( "recur: %d-%d-%d %d:%d:%d\n" , next.year, next.month, next.day, next.hour, next.minute, next.second ); //quick fix for the recurrence getting out of the end of the month into the next month //like 31st of each month but when you get February if( recur.freq == ICAL_MONTHLY_RECURRENCE && !m_recurweeknumber && next.day != m_start->m_datetime.day) { //#ifdef ICAL_DEBUG // printf( "Wrong day in month\n" ); //#endif // continue; next.day = 0; icaltime_normalize( next ); } PRTime nextinms = ConvertToPrtime( next ); if( LL_CMP(nextinms, < ,beforethis) && !IsExcepted( nextinms ) ) { // printf( "Result: %d-%d-%d %d:%d\n" , next.year, next.month, next.day, next.hour, next.minute ); *retval = nextinms; *isvalid = true; } if( LL_CMP(nextinms, >= ,beforethis) ) { break; } } icalrecur_iterator_free(ritr); } icalcomponent_free( vcalendar ); return NS_OK; } icaltimetype oeICalEventImpl::GetNextRecurrence( icaltimetype begin, bool *isbeginning ) { icaltimetype result = icaltime_null_time(); if( isbeginning ) { *isbeginning = true; } if( icaltime_compare( m_start->m_datetime , begin ) > 0 ) { if( !m_recur ) return m_start->m_datetime; PRTime nextinms = ConvertToPrtime( m_start->m_datetime ); if( !IsExcepted( nextinms ) ) return m_start->m_datetime; } //for non recurring events if( !m_recur ) { if( icaltime_compare( m_end->m_datetime , begin ) <= 0 ) return result; struct icaltimetype nextday = begin; nextday.hour = 0; nextday.minute = 0; nextday.second = 0; icaltime_adjust( &nextday, 1, 0, 0, 0 ); if( icaltime_compare( nextday, m_end->m_datetime ) < 0 ) { struct icaltimetype afternextday = nextday; icaltime_adjust( &afternextday, 1, 0, 0, 0 ); if( icaltime_compare( afternextday, m_end->m_datetime ) < 0 ) { nextday.is_date = true; } if( isbeginning ) { *isbeginning = false; } return nextday; } return result; } //for recurring events icalcomponent *vcalendar = AsIcalComponent(); if ( !vcalendar ) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::GetNextRecurrence() failed!\n" ); #endif return result; } icalcomponent *vevent = icalcomponent_get_first_component( vcalendar, ICAL_VEVENT_COMPONENT ); icalproperty *prop = icalcomponent_get_first_property( vevent, ICAL_RRULE_PROPERTY ); if ( prop != 0) { struct icaltimetype next,nextpropagation=icaltime_null_time(); struct icalrecurrencetype recur = icalproperty_get_rrule(prop); //printf("#### %s\n",icalrecurrencetype_as_string(&recur)); icalrecur_iterator* ritr = icalrecur_iterator_new(recur,m_start->m_datetime); bool nextpropagationisdate = false; for(next = icalrecur_iterator_next(ritr); !icaltime_is_null_time(next); next = icalrecur_iterator_next(ritr)){ next.is_date = false; next = icaltime_normalize( next ); //printf( "recur: %d-%d-%d %d:%d:%d\n" , next.year, next.month, next.day, next.hour, next.minute, next.second ); //quick fix for the recurrence getting out of the end of the month into the next month //like 31st of each month but when you get February if( recur.freq == ICAL_MONTHLY_RECURRENCE && !m_recurweeknumber && next.day != m_start->m_datetime.day) { //#ifdef ICAL_DEBUG //printf( "Wrong day in month\n" ); //#endif //continue; next.day = 0; icaltime_normalize( next ); } if( icaltime_compare( next, begin ) > 0 ) { PRTime nextinms = ConvertToPrtime( next ); if( !IsExcepted( nextinms ) ) { //printf( "Result: %d-%d-%d %d:%d\n" , next.year, next.month, next.day, next.hour, next.minute ); result = next; break; } } if( icaltime_is_null_time( nextpropagation ) ) { struct icaldurationtype eventlength = icaltime_subtract( m_end->m_datetime, m_start->m_datetime ); struct icaltimetype end = icaltime_add( next, eventlength ); if( icaltime_compare( end , begin ) <= 0 ) continue; struct icaltimetype nextday = next; nextday.hour = 0; nextday.minute = 0; nextday.second = 0; icaltime_adjust( &nextday, 1, 0, 0, 0 ); if( icaltime_compare( nextday , begin ) > 0 && icaltime_compare( nextday, end ) < 0 ) { PRTime nextdayinms = ConvertToPrtime( nextday ); if( !IsExcepted( nextdayinms ) ) { nextpropagation = nextday; struct icaltimetype afternextday = nextday; icaltime_adjust( &afternextday, 1, 0, 0, 0 ); if( icaltime_compare( afternextday, end ) < 0 ) { nextpropagationisdate = true; } } } } } icalrecur_iterator_free(ritr); if( !icaltime_is_null_time( result ) ) { if( !icaltime_is_null_time( nextpropagation ) ) { if( icaltime_compare( nextpropagation , result ) < 0 ) { result = nextpropagation; result.is_date = nextpropagationisdate; if( isbeginning ) { *isbeginning = false; } } } } else if( !icaltime_is_null_time( nextpropagation ) ) { result = nextpropagation; result.is_date = nextpropagationisdate; if( isbeginning ) { *isbeginning = false; } } } icalcomponent_free( vcalendar ); return result; } icaltimetype oeICalEventImpl::GetPreviousOccurrence( icaltimetype beforethis ) { icaltimetype result = icaltime_null_time(); PRTime beforethisinms = ConvertToPrtime( beforethis ); PRTime resultinms; PRBool isvalid; GetPreviousOccurrence( beforethisinms ,&resultinms, &isvalid ); if( !isvalid ) return result; result = ConvertFromPrtime( resultinms ); return result; } icaltimetype oeICalEventImpl::GetNextAlarmTime( icaltimetype begin ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventImpl::GetNextAlarmTime()\n" ); #endif icaltimetype result = icaltime_null_time(); if( !m_hasalarm ) return result; icaltimetype starting = begin; if( !icaltime_is_null_time( m_lastalarmack ) && icaltime_compare( begin, m_lastalarmack ) < 0 ) starting = m_lastalarmack; icaltimetype checkloop = starting; do { checkloop = GetNextRecurrence( checkloop, nsnull ); checkloop.is_date = false; result = checkloop; if( icaltime_is_null_time( checkloop ) ) { break; } result = CalculateAlarmTime( result ); } while ( icaltime_compare( starting, result ) >= 0 ); for( int i=0; i 0 ) { result = snoozetime; } } } return result; } icaltimetype oeICalEventImpl::CalculateAlarmTime( icaltimetype date ) { icaltimetype result = date; if( strcasecmp( m_alarmunits, "days" ) == 0 ) icaltime_adjust( &result, -(signed long)m_alarmlength, 0, 0, 0 ); else if( strcasecmp( m_alarmunits, "hours" ) == 0 ) icaltime_adjust( &result, 0, -(signed long)m_alarmlength, 0, 0 ); else icaltime_adjust( &result, 0, 0, -(signed long)m_alarmlength, 0 ); return result; } icaltimetype oeICalEventImpl::CalculateEventTime( icaltimetype alarmtime ) { icaltimetype result = alarmtime; if( strcasecmp( m_alarmunits, "days" ) == 0 ) icaltime_adjust( &result, (signed long)m_alarmlength, 0, 0, 0 ); else if( strcasecmp( m_alarmunits, "hours" ) == 0 ) icaltime_adjust( &result, 0, (signed long)m_alarmlength, 0, 0 ); else icaltime_adjust( &result, 0, 0, (signed long)m_alarmlength, 0 ); return result; } NS_IMETHODIMP oeICalEventImpl::GetStart(oeIDateTime * *start) { *start = m_start; NS_ADDREF(*start); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::GetEnd(oeIDateTime * *end) { *end = m_end; NS_ADDREF(*end); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::GetStamp(oeIDateTime * *stamp) { *stamp = m_stamp; NS_ADDREF(*stamp); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::GetRecurEnd(oeIDateTime * *recurend) { *recurend = m_recurend; NS_ADDREF(*recurend); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::GetRecurWeekdays(PRInt16 *aRetVal) { #ifdef ICAL_DEBUG_ALL printf( "GetRecurWeekdays()\n" ); #endif *aRetVal = m_recurweekdays; return NS_OK; } NS_IMETHODIMP oeICalEventImpl::SetRecurWeekdays(PRInt16 aNewVal) { #ifdef ICAL_DEBUG_ALL printf( "SetRecurWeekdays()\n" ); #endif m_recurweekdays = aNewVal; return NS_OK; } NS_IMETHODIMP oeICalEventImpl::GetRecurWeekNumber(PRInt16 *aRetVal) { #ifdef ICAL_DEBUG_ALL printf( "GetRecurWeekNumber()\n" ); #endif *aRetVal = m_recurweeknumber; return NS_OK; } NS_IMETHODIMP oeICalEventImpl::SetRecurWeekNumber(PRInt16 aNewVal) { #ifdef ICAL_DEBUG_ALL printf( "SetRecurWeekNumber()\n" ); #endif m_recurweeknumber = aNewVal; return NS_OK; } NS_IMETHODIMP oeICalEventImpl::GetIcalString(nsACString& aRetVal) { #ifdef ICAL_DEBUG_ALL printf( "GetIcalString() = " ); #endif icalcomponent *vcalendar = AsIcalComponent(); if ( !vcalendar ) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::GetIcalString() failed!\n" ); #endif return NS_OK; } char *str = icalcomponent_as_ical_string( vcalendar ); if( str ) { aRetVal = str; // *aRetVal= (char*) nsMemory::Clone( str, strlen(str)+1); } else aRetVal.Truncate(); icalcomponent_free( vcalendar ); #ifdef ICAL_DEBUG_ALL printf( "\"%s\"\n", PromiseFlatCString( aRetVal ).get() ); #endif return NS_OK; } NS_IMETHODIMP oeICalEventImpl::ParseIcalString(const nsACString& aNewVal, PRBool *aRetVal) { #ifdef ICAL_DEBUG_ALL printf( "ParseIcalString( %s )\n", PromiseFlatCString( aNewVal ).get() ); #endif *aRetVal = false; icalcomponent *comp = icalparser_parse_string( PromiseFlatCString( aNewVal ).get() ); if( comp ) { if( ParseIcalComponent( comp ) ) *aRetVal = true; icalcomponent_free( comp ); } return NS_OK; } NS_IMETHODIMP oeICalEventImpl::AddException( PRTime exdate ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventImpl::AddException()\n" ); #endif icaltimetype tmpexdate = ConvertFromPrtime( exdate ); tmpexdate.hour = 0; tmpexdate.minute = 0; tmpexdate.second = 0; exdate = ConvertToPrtime( tmpexdate ); PRTime *newexdate = new PRTime; *newexdate = exdate; m_exceptiondates.AppendElement( newexdate ); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::RemoveAllExceptions() { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventImpl::RemoveAllExceptions()\n" ); #endif for( int i=0; i dateEnum = new oeDateEnumerator(); if (!dateEnum) return NS_ERROR_OUT_OF_MEMORY; int count=0; bool found; PRTime current,lastadded,minimum; do { found = false; for( int i=0; i, lastadded ) ) { if( LL_CMP( minimum, ==, lastadded ) ) { minimum = current; found = true; } else if( LL_CMP( current, <, minimum ) ) { minimum = current; found = true; } } } if( found ) { dateEnum->AddDate( minimum ); count++; lastadded = minimum; } } while ( found ); // bump ref count return dateEnum->QueryInterface(NS_GET_IID(nsISimpleEnumerator), (void **)datelist); } bool oeICalEventImpl::IsExcepted( PRTime date ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventImpl::IsExcepted() = " ); #endif icaltimetype tmpexdate = ConvertFromPrtime( date ); tmpexdate.hour = 0; tmpexdate.minute = 0; tmpexdate.second = 0; date = ConvertToPrtime( tmpexdate ); bool result = false; for( int i=0; iRelease(); return NS_OK; } icalcomponent *vevent = icalcomponent_get_first_component( vcalendar, ICAL_VEVENT_COMPONENT ); if( !(icalevent->ParseIcalComponent( vevent )) ) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::Clone() failed.\n" ); #endif icalevent->Release(); return NS_OK; } *ev = icalevent; return NS_OK; } NS_IMETHODIMP oeICalEventImpl::GetAttachmentsArray(nsISupportsArray * *aAttachmentsArray) { NS_ENSURE_ARG_POINTER(aAttachmentsArray); *aAttachmentsArray = m_attachments; NS_IF_ADDREF(*aAttachmentsArray); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::AddAttachment(nsIMsgAttachment *attachment) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::AddAttachment()\n" ); #endif PRUint32 i; PRUint32 attachmentCount = 0; m_attachments->Count(&attachmentCount); //Don't add twice the same attachment. nsCOMPtr element; PRBool sameUrl; for (i = 0; i < attachmentCount; i ++) { m_attachments->QueryElementAt(i, NS_GET_IID(nsIMsgAttachment), getter_AddRefs(element)); if (element) { element->EqualsUrl(attachment, &sameUrl); if (sameUrl) return NS_OK; } } return m_attachments->InsertElementAt(attachment, attachmentCount); } NS_IMETHODIMP oeICalEventImpl::RemoveAttachment(nsIMsgAttachment *attachment) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::RemoveAttachment()\n" ); #endif PRUint32 i; PRUint32 attachmentCount = 0; m_attachments->Count(&attachmentCount); nsCOMPtr element; PRBool sameUrl; for (i = 0; i < attachmentCount; i ++) { m_attachments->QueryElementAt(i, NS_GET_IID(nsIMsgAttachment), getter_AddRefs(element)); if (element) { element->EqualsUrl(attachment, &sameUrl); if (sameUrl) { m_attachments->DeleteElementAt(i); break; } } } return NS_OK; } NS_IMETHODIMP oeICalEventImpl::RemoveAttachments() { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::RemoveAttachments()\n" ); #endif PRUint32 i; PRUint32 attachmentCount = 0; m_attachments->Count(&attachmentCount); for (i = 0; i < attachmentCount; i ++) m_attachments->DeleteElementAt(0); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::GetContactsArray(nsISupportsArray * *aContactsArray) { NS_ENSURE_ARG_POINTER(aContactsArray); *aContactsArray = m_contacts; NS_IF_ADDREF(*aContactsArray); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::AddContact(nsIAbCard *contact) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::AddContact()\n" ); #endif PRUint32 i; PRUint32 contactCount = 0; m_contacts->Count(&contactCount); //Don't add twice the same contact. nsCOMPtr element; PRBool samecontact; for (i = 0; i < contactCount; i ++) { m_contacts->QueryElementAt(i, NS_GET_IID(nsIAbCard), getter_AddRefs(element)); if (element) { element->Equals(contact, &samecontact); if (samecontact) return NS_OK; } } return m_contacts->InsertElementAt(contact, contactCount); } NS_IMETHODIMP oeICalEventImpl::RemoveContact(nsIAbCard *contact) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::RemoveContact()\n" ); #endif PRUint32 i; PRUint32 contactCount = 0; m_contacts->Count(&contactCount); nsCOMPtr element; PRBool samecontact; for (i = 0; i < contactCount; i ++) { m_contacts->QueryElementAt(i, NS_GET_IID(nsIAbCard), getter_AddRefs(element)); if (element) { element->Equals(contact, &samecontact); if (samecontact) { m_contacts->DeleteElementAt(i); break; } } } return NS_OK; } NS_IMETHODIMP oeICalEventImpl::RemoveContacts() { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::RemoveContacts()\n" ); #endif PRUint32 i; PRUint32 contactCount = 0; m_contacts->Count(&contactCount); for (i = 0; i < contactCount; i ++) m_contacts->DeleteElementAt(0); return NS_OK; } NS_IMETHODIMP oeICalEventImpl::SetDuration(PRBool is_negative, PRUint16 weeks, PRUint16 days, PRUint16 hours, PRUint16 minutes, PRUint16 seconds) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventImpl::SetDuration()\n" ); #endif return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP oeICalEventImpl::GetDuration(PRBool *is_negative, PRUint16 *weeks, PRUint16 *days, PRUint16 *hours, PRUint16 *minutes, PRUint16 *seconds) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventImpl::GetDuration()\n" ); #endif return NS_ERROR_NOT_IMPLEMENTED; } void oeICalEventImpl::ChopAndAddEventToEnum( struct icaltimetype startdate, nsISimpleEnumerator **eventlist, bool isallday, bool isbeginning ) { nsCOMPtr eventEnum; eventEnum = (oeEventEnumerator *)*eventlist; oeIICalEventDisplay* eventDisplay; nsresult rv = NS_NewICalEventDisplay( this, &eventDisplay ); if( NS_FAILED( rv ) ) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::ChopAndAddEventToEnum() : WARNING Cannot create oeIICalEventDisplay instance: %x\n", rv ); #endif return; } eventEnum->AddEvent( eventDisplay ); PRTime startdateinms = ConvertToPrtime( startdate ); eventDisplay->SetDisplayDate( startdateinms ); struct icaltimetype endofday = startdate; endofday.hour = 23; endofday.minute = 59; endofday.second = 59; PRTime enddateinms; if( isallday ) { enddateinms = ConvertToPrtime( endofday ); eventDisplay->SetDisplayEndDate( enddateinms ); } else { if( isbeginning ) { struct icaldurationtype eventlength = icaltime_subtract( m_end->m_datetime, m_start->m_datetime ); struct icaltimetype eventenddate = icaltime_add( startdate, eventlength ); if( icaltime_compare( endofday, eventenddate ) < 0 ) { enddateinms = ConvertToPrtime( endofday ); } else { enddateinms = ConvertToPrtime( eventenddate ); } } else { struct icaltimetype eventenddate = endofday; eventenddate.hour = m_end->m_datetime.hour; eventenddate.minute = m_end->m_datetime.minute; eventenddate.second = m_end->m_datetime.second; enddateinms = ConvertToPrtime( eventenddate ); } eventDisplay->SetDisplayEndDate( enddateinms ); } NS_RELEASE( eventDisplay ); } bool oeICalEventImpl::ParseIcalComponent( icalcomponent *comp ) { #ifdef ICAL_DEBUG_ALL printf( "ParseIcalComponent()\n" ); #endif icalcomponent *vevent=nsnull; icalcomponent_kind kind = icalcomponent_isa( comp ); if( kind == ICAL_VCALENDAR_COMPONENT ) { vevent = icalcomponent_get_first_component( comp , ICAL_VEVENT_COMPONENT ); if ( !vevent ) { icalcomponent_get_first_component( comp , ICAL_VTODO_COMPONENT ); } } else if( kind == ICAL_VEVENT_COMPONENT ) vevent = comp; else if( kind == ICAL_VTODO_COMPONENT ) vevent = comp; if ( !vevent ) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::ParseIcalComponent() failed: vevent is NULL!\n" ); #endif return false; } const char *tmpstr; //id icalproperty *prop = icalcomponent_get_first_property( vevent, ICAL_UID_PROPERTY ); if ( prop ) { tmpstr = icalproperty_get_uid( prop ); SetId( tmpstr ); } else { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::ParseIcalComponent() failed: UID not found!\n" ); #endif return false; } //method if( kind == ICAL_VCALENDAR_COMPONENT ) { prop = icalcomponent_get_first_property( comp, ICAL_METHOD_PROPERTY ); if ( prop != 0) { eventMethodProperty tmpMethodProp; tmpMethodProp = icalproperty_get_method( prop ); SetMethod( tmpMethodProp ); } else if ( m_method ) { m_method = 0; } } //status prop = icalcomponent_get_first_property( vevent, ICAL_STATUS_PROPERTY ); if ( prop != 0) { eventStatusProperty tmpStatusProp; tmpStatusProp = icalproperty_get_status( prop ); SetStatus( tmpStatusProp ); } else if ( m_status ) { m_status = 0; } //title prop = icalcomponent_get_first_property( vevent, ICAL_SUMMARY_PROPERTY ); if ( prop != 0) { tmpstr = icalproperty_get_summary( prop ); SetTitle( nsDependentCString( strForceUTF8( tmpstr ) ) ); } else if( !m_title.IsEmpty() ) { m_title.Truncate(); } //description prop = icalcomponent_get_first_property( vevent, ICAL_DESCRIPTION_PROPERTY ); if ( prop != 0) { tmpstr = icalproperty_get_description( prop ); SetDescription( nsDependentCString( strForceUTF8( tmpstr ) ) ); } else if( !m_description.IsEmpty() ) { m_description.Truncate(); } //location prop = icalcomponent_get_first_property( vevent, ICAL_LOCATION_PROPERTY ); if ( prop != 0) { tmpstr = icalproperty_get_location( prop ); SetLocation( nsDependentCString( strForceUTF8( tmpstr ) ) ); } else if( !m_location.IsEmpty() ) { m_location.Truncate(); } //category prop = icalcomponent_get_first_property( vevent, ICAL_CATEGORIES_PROPERTY ); if ( prop != 0) { tmpstr = (char *)icalproperty_get_categories( prop ); SetCategories( nsDependentCString( strForceUTF8( tmpstr ) ) ); } else if( !m_category.IsEmpty() ) { m_category.Truncate(); } //url prop = icalcomponent_get_first_property( vevent, ICAL_URL_PROPERTY ); if ( prop != 0) { tmpstr = (char *)icalproperty_get_url( prop ); SetUrl( nsDependentCString( strForceUTF8( tmpstr ) ) ); } else if( !m_url.IsEmpty() ) { m_url.Truncate(); } //priority prop = icalcomponent_get_first_property( vevent, ICAL_PRIORITY_PROPERTY ); if ( prop != 0) { m_priority = icalproperty_get_priority( prop ); } else { m_priority = 0; } //isprivate prop = icalcomponent_get_first_property( vevent, ICAL_CLASS_PROPERTY ); if ( prop != 0) { icalproperty_class tmpcls = icalproperty_get_class( prop ); if( tmpcls == ICAL_CLASS_PUBLIC ) m_isprivate= false; else m_isprivate= true; } else m_isprivate= false; //syncid for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "SyncId" ) == 0 ) break; } } if ( prop != 0) { tmpstr = icalproperty_get_value_as_string( prop ); SetSyncId( tmpstr ); } else SetSyncId( "" ); //allday for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "AllDay" ) == 0 ) break; } } if ( prop != 0) { tmpstr = (char *)icalproperty_get_value_as_string( prop ); if( strcmp( tmpstr, "TRUE" ) == 0 ) m_allday= true; else m_allday= false; } else m_allday= false; //alarm icalcomponent *valarm = icalcomponent_get_first_component( vevent, ICAL_VALARM_COMPONENT ); if ( valarm != 0) m_hasalarm= true; else m_hasalarm= false; //alarmunits for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "AlarmUnits" ) == 0 ) break; } } if ( prop != 0) { tmpstr = icalproperty_get_value_as_string( prop ); SetAlarmUnits( tmpstr ); } else SetAlarmUnits( DEFAULT_ALARM_UNITS ); //alarmlength for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = (char *)icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "AlarmLength" ) == 0 ) break; } } if ( prop != 0) { tmpstr = (char *)icalproperty_get_value_as_string( prop ); m_alarmlength= atol( tmpstr ); } else m_alarmlength = DEFAULT_ALARM_LENGTH; //alarmemail for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = (char *)icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "AlarmEmailAddress" ) == 0 ) break; } } if ( prop != 0) { tmpstr = icalproperty_get_value_as_string( prop ); SetAlarmEmailAddress( tmpstr ); } else if( m_alarmemail ) { nsMemory::Free( m_alarmemail ); m_alarmemail= nsnull; } //inviteemail for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "InviteEmailAddress" ) == 0 ) break; } } if ( prop != 0) { tmpstr = (char *)icalproperty_get_value_as_string( prop ); SetInviteEmailAddress( tmpstr ); } else if( m_inviteemail ) { nsMemory::Free( m_inviteemail ); m_inviteemail= nsnull; } //recurinterval for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "RecurInterval" ) == 0 ) break; } } if ( prop != 0) { tmpstr = (char *)icalproperty_get_value_as_string( prop ); m_recurinterval= atol( tmpstr ); } else m_recurinterval= 0; //recurunits for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "RecurUnits" ) == 0 ) break; } } if ( prop != 0) { tmpstr = (char *)icalproperty_get_value_as_string( prop ); SetRecurUnits( tmpstr ); } else SetRecurUnits( DEFAULT_RECUR_UNITS ); //startdate prop = icalcomponent_get_first_property( vevent, ICAL_DTSTART_PROPERTY ); if ( prop != 0) { m_start->m_datetime = icalproperty_get_dtstart( prop ); bool datevalue=m_start->m_datetime.is_date; m_start->m_datetime.is_date = false; //Because currently we depend on m_datetime being a complete datetime value. const char *tzid=nsnull; if( m_start->m_datetime.is_utc && !datevalue ) tzid="/Mozilla.org/BasicTimezones/GMT"; m_start->m_datetime.is_utc = false; if( datevalue ) { m_allday = true; m_start->SetHour( 0 ); m_start->SetMinute( 0 ); m_start->m_datetime.is_date = false; //Because currently we depend on m_datetime being a complete datetime value. } icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_TZID_PARAMETER ); if( tmppar ) tzid = icalparameter_get_tzid( tmppar ); if( tzid ) { if( !datevalue ) { PRTime timeinms; m_start->GetTime( &timeinms ); m_start->SetTimeInTimezone( timeinms, tzid ); } else { m_start->SetTzID( tzid ); } } } else { m_start->m_datetime = icaltime_null_time(); } //duration prop = icalcomponent_get_first_property( vevent, ICAL_DURATION_PROPERTY ); if ( prop != 0) { m_duration = icalproperty_get_duration( prop ); } else { m_duration = icaldurationtype_null_duration(); } //enddate if( icaldurationtype_is_null_duration( m_duration ) ) { prop = icalcomponent_get_first_property( vevent, ICAL_DTEND_PROPERTY ); if ( prop != 0) { m_end->m_datetime = icalproperty_get_dtend( prop ); bool datevalue=m_end->m_datetime.is_date; m_end->m_datetime.is_date = false; //Because currently we depend on m_datetime being a complete datetime value. const char *tzid=nsnull; if( m_end->m_datetime.is_utc && !datevalue ) tzid="/Mozilla.org/BasicTimezones/GMT"; m_end->m_datetime.is_utc = false; if( datevalue ) { m_end->SetHour( 0 ); m_end->SetMinute( 0 ); } icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_TZID_PARAMETER ); if( tmppar ) tzid = icalparameter_get_tzid( tmppar ); if( tzid ) { if( !datevalue ) { PRTime timeinms; m_end->GetTime( &timeinms ); m_end->SetTimeInTimezone( timeinms, tzid ); } else { m_end->SetTzID( tzid ); } } } else if( !icaltime_is_null_time( m_start->m_datetime ) ) { m_end->m_datetime = m_start->m_datetime; } else { m_end->m_datetime = icaltime_null_time(); } } else { if( !icaltime_is_null_time( m_start->m_datetime ) ) { m_end->m_datetime = icaltime_add( m_start->m_datetime, m_duration ); } else { m_end->m_datetime = icaltime_null_time(); } } //stampdate prop = icalcomponent_get_first_property( vevent, ICAL_DTSTAMP_PROPERTY ); if ( prop != 0) { m_stamp->m_datetime = icalproperty_get_dtstamp( prop ); } else { m_stamp->m_datetime = icaltime_null_time(); } // scan for X- properties // first set the defaults m_lastalarmack = icaltime_null_time(); const char *propvalue; const char *x_name; for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { x_name = icalproperty_get_x_name ( prop ); if( !x_name ) continue; propvalue = icalproperty_get_value_as_string( prop ); //lastalarmack if ( strcmp( x_name, XPROP_LASTALARMACK ) == 0) { m_lastalarmack = icaltime_from_string( propvalue ); } //syncid else if ( strcmp( x_name, XPROP_SYNCID ) == 0) { SetSyncId( propvalue ); } //alarmunits else if ( strcmp( x_name, XPROP_ALARMUNITS ) == 0) { SetAlarmUnits( propvalue ); } //alarmlength else if ( strcmp( x_name, XPROP_ALARMLENGTH ) == 0) { m_alarmlength= atol( propvalue ); } //recurunits else if ( strcmp( x_name, XPROP_RECURUNITS ) == 0) { SetRecurUnits( propvalue ); } //recurinterval else if ( strcmp( x_name, XPROP_RECURINTERVAL ) == 0) { m_recurinterval= atol( propvalue ); } } //recurend & recurforever & recur & recurweekday & recurweeknumber m_recur = false; m_recurforever = true; m_recurweekdays = 0; m_recurweeknumber = 0; prop = icalcomponent_get_first_property( vevent, ICAL_RRULE_PROPERTY ); if ( prop != 0) { m_recur = true; struct icalrecurrencetype recur; recur = icalproperty_get_rrule(prop); m_recurend->m_datetime = recur.until; m_recurend->m_datetime.is_date = false; m_recurend->m_datetime.is_utc = false; m_recurinterval = recur.interval; m_recurcount = recur.count; if( !icaltime_is_null_time( recur.until ) ) m_recurforever = false; if( recur.freq == ICAL_DAILY_RECURRENCE ) { SetRecurUnits( "days" ); } else if( recur.freq == ICAL_WEEKLY_RECURRENCE ) { int k=0; SetRecurUnits( "weeks" ); while( recur.by_day[k] != ICAL_RECURRENCE_ARRAY_MAX ) { m_recurweekdays += 1 << (recur.by_day[k]-1); k++; } } else if( recur.freq == ICAL_MONTHLY_RECURRENCE ) { SetRecurUnits( "months" ); if( recur.by_day[0] != ICAL_RECURRENCE_ARRAY_MAX ) m_recurweeknumber = icalrecurrencetype_day_position(recur.by_day[0]); if( m_recurweeknumber < 0 ) m_recurweeknumber = 5; } else if( recur.freq == ICAL_YEARLY_RECURRENCE ) { SetRecurUnits( "years" ); } } //recur exceptions RemoveAllExceptions(); for( prop = icalcomponent_get_first_property( vevent, ICAL_EXDATE_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_EXDATE_PROPERTY ) ) { icaltimetype exdate = icalproperty_get_exdate( prop ); PRTime *exdateinms = new PRTime; *exdateinms = ConvertToPrtime( exdate ); m_exceptiondates.AppendElement( exdateinms ); } for( int i=0; i= 0 ) continue; PRTime *snoozetimeinms = new PRTime; *snoozetimeinms = icaltime_as_timet( snoozetime ); *snoozetimeinms = *snoozetimeinms * 1000; m_snoozetimes.AppendElement( snoozetimeinms ); } } //attachments for( prop = icalcomponent_get_first_property( vevent, ICAL_X_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_X_PROPERTY ) ) { icalparameter *tmppar = icalproperty_get_first_parameter( prop, ICAL_MEMBER_PARAMETER ); if ( tmppar != 0 ) { tmpstr = icalparameter_get_member( tmppar ); if( strcmp( tmpstr, "Attachment" ) == 0 ) { nsresult rv; tmpstr = (char *)icalproperty_get_value_as_string( prop ); nsCOMPtr attachment = do_CreateInstance(NS_MSGATTACHMENT_CONTRACTID, &rv); if ( NS_SUCCEEDED(rv) && attachment ) { attachment->SetUrl( tmpstr ); AddAttachment( attachment ); } } } } //contacts for(prop = icalcomponent_get_first_property( vevent, ICAL_CONTACT_PROPERTY ); prop != 0 ; prop = icalcomponent_get_next_property( vevent, ICAL_CONTACT_PROPERTY ) ) { tmpstr = icalproperty_get_contact( prop ); nsresult rv; nsCOMPtr contact = do_CreateInstance(NS_ABCARDPROPERTY_CONTRACTID, &rv); if ( NS_SUCCEEDED(rv) && contact ) { nsAutoString email; email.AssignWithConversion( tmpstr ); contact->SetPrimaryEmail( email.get() ); AddContact( contact ); } } return true; } icalcomponent* oeICalEventImpl::AsIcalComponent() { #ifdef ICAL_DEBUG_ALL printf( "AsIcalComponent()\n" ); #endif icalcomponent *newcalendar; newcalendar = icalcomponent_new_vcalendar(); if ( !newcalendar ) { #ifdef ICAL_DEBUG printf( "oeICalEventImpl::AsIcalComponent() failed: Cannot create VCALENDAR!\n" ); #endif return nsnull; } //version icalproperty *prop = icalproperty_new_version( ICALEVENT_VERSION ); icalcomponent_add_property( newcalendar, prop ); //prodid prop = icalproperty_new_prodid( ICALEVENT_PRODID ); icalcomponent_add_property( newcalendar, prop ); //method if( m_method != 0 ){ prop = icalproperty_new_method( (icalproperty_method) m_method ); icalcomponent_add_property( newcalendar, prop ); } icalcomponent *vevent = icalcomponent_new_vevent(); //id prop = icalproperty_new_uid( m_id ); icalcomponent_add_property( vevent, prop ); //title if( !m_title.IsEmpty() ) { prop = icalproperty_new_summary( PromiseFlatCString( m_title ).get() ); icalcomponent_add_property( vevent, prop ); } //description if( !m_description.IsEmpty() ) { prop = icalproperty_new_description( PromiseFlatCString( m_description ).get() ); icalcomponent_add_property( vevent, prop ); } //location if( !m_location.IsEmpty() ) { prop = icalproperty_new_location( PromiseFlatCString( m_location ).get() ); icalcomponent_add_property( vevent, prop ); } //category if( !m_category.IsEmpty() ) { prop = icalproperty_new_categories( PromiseFlatCString( m_category ).get() ); icalcomponent_add_property( vevent, prop ); } //url if( !m_url.IsEmpty() ) { prop = icalproperty_new_url( PromiseFlatCString( m_url ).get() ); icalcomponent_add_property( vevent, prop ); } //priority if( m_priority != 0) { prop = icalproperty_new_priority( m_priority ); icalcomponent_add_property( vevent, prop ); } //status if( m_status != 0 ){ prop = icalproperty_new_status( (icalproperty_status) m_status ); icalcomponent_add_property( vevent, prop ); } //isprivate if( m_isprivate ) prop = icalproperty_new_class( ICAL_CLASS_PRIVATE ); else prop = icalproperty_new_class( ICAL_CLASS_PUBLIC ); icalcomponent_add_property( vevent, prop ); //syncId if( m_syncid && strlen( m_syncid ) != 0 ){ prop = icalproperty_new_x( m_syncid ); icalproperty_set_x_name( prop, XPROP_SYNCID); icalcomponent_add_property( vevent, prop ); } //alarm if( m_hasalarm ) { struct icaltriggertype trig; icalcomponent *valarm = icalcomponent_new_valarm(); trig.time.year = trig.time.month = trig.time.day = trig.time.hour = trig.time.minute = trig.time.second = 0; trig.duration.is_neg = true; trig.duration.days = trig.duration.weeks = trig.duration.hours = trig.duration.minutes = trig.duration.seconds = 0; if( m_alarmunits ) { if( strcasecmp( m_alarmunits, "days" ) == 0 ) trig.duration.days = m_alarmlength; else if( strcasecmp( m_alarmunits, "hours" ) == 0 ) trig.duration.hours = m_alarmlength; else trig.duration.minutes = m_alarmlength; } else trig.duration.minutes = m_alarmlength; if( m_alarmlength == 0 ) trig.duration.seconds = 1; prop = icalproperty_new_trigger( trig ); icalcomponent_add_property( valarm, prop ); icalcomponent_add_component( vevent, valarm ); } //alarmunits if( m_alarmunits && strlen( m_alarmunits ) != 0 && strcasecmp( m_alarmunits, DEFAULT_ALARM_UNITS ) != 0 ){ prop = icalproperty_new_x( m_alarmunits ); icalproperty_set_x_name( prop, XPROP_ALARMUNITS); icalcomponent_add_property( vevent, prop ); } char tmpstr[20]; //alarmlength if( m_alarmlength && m_alarmlength != DEFAULT_ALARM_LENGTH ) { sprintf( tmpstr, "%lu", m_alarmlength ); prop = icalproperty_new_x( tmpstr ); icalproperty_set_x_name( prop, XPROP_ALARMLENGTH); icalcomponent_add_property( vevent, prop ); } //alarmemail if( m_alarmemail && strlen( m_alarmemail ) != 0 ){ icalparameter *tmppar = icalparameter_new_member( "AlarmEmailAddress" ); prop = icalproperty_new_x( m_alarmemail ); icalproperty_add_parameter( prop, tmppar ); icalcomponent_add_property( vevent, prop ); } //lastalarmack if( !icaltime_is_null_time( m_lastalarmack ) ) { prop = icalproperty_new_x( icaltime_as_ical_string(m_lastalarmack )); icalproperty_set_x_name( prop, XPROP_LASTALARMACK); icalcomponent_add_property( vevent, prop ); } //inviteemail if( m_inviteemail && strlen( m_inviteemail ) != 0 ){ icalparameter *tmppar = icalparameter_new_member( "InviteEmailAddress" ); prop = icalproperty_new_x( m_inviteemail ); icalproperty_add_parameter( prop, tmppar ); icalcomponent_add_property( vevent, prop ); } //Create enddate if does not exist if( icaltime_is_null_time( m_end->m_datetime ) && !icaltime_is_null_time( m_start->m_datetime ) ) { //Set to the same as start date 23:59 m_end->m_datetime = m_start->m_datetime; m_end->SetHour( 23 ); m_end->SetMinute( 59 ); } //recurunits if( m_recurunits && strlen( m_recurunits ) != 0 && strcasecmp( m_recurunits, DEFAULT_RECUR_UNITS ) != 0 ){ prop = icalproperty_new_x( m_recurunits ); icalproperty_set_x_name( prop, XPROP_RECURUNITS); icalcomponent_add_property( vevent, prop ); } //recurinterval if( m_recurinterval != 1 ){ sprintf( tmpstr, "%lu", m_recurinterval ); prop = icalproperty_new_x( tmpstr ); icalproperty_set_x_name( prop, XPROP_RECURINTERVAL); icalcomponent_add_property( vevent, prop ); } //recurrence if( m_recur ) { int recurtype = RECUR_NONE; int interval = m_recurinterval; if( interval == 0 ) interval = 1; if( m_recurunits ) { if( strcasecmp( m_recurunits , "days" ) == 0 ) { recurtype = RECUR_DAILY; } else if( strcasecmp( m_recurunits , "weeks" ) == 0 ) { recurtype = RECUR_WEEKLY; } else if( strcasecmp( m_recurunits , "months" ) == 0 ) { recurtype = RECUR_MONTHLY_MDAY; } else if( strcasecmp( m_recurunits, "months_day" ) == 0 ) { recurtype = RECUR_MONTHLY_WDAY; } else if( strcasecmp( m_recurunits , "years" ) == 0 ) { recurtype = RECUR_YEARLY; } } struct icalrecurrencetype recur; icalrecurrencetype_clear( &recur ); // for( int i=0; im_datetime.year; recur.until.month = m_recurend->m_datetime.month; recur.until.day = m_recurend->m_datetime.day; recur.until.hour = 23; recur.until.minute = 59; recur.until.second = 59; } else { recur.count = m_recurcount; } } switch ( recurtype ) { case RECUR_NONE: break; case RECUR_DAILY: recur.freq = ICAL_DAILY_RECURRENCE; prop = icalproperty_new_rrule( recur ); icalcomponent_add_property( vevent, prop ); break; case RECUR_WEEKLY:{ recur.freq = ICAL_WEEKLY_RECURRENCE; //if the recur rule is weekly make sure a weekdaymask exists if( m_recurweekdays == 0 ) { m_recurweekdays = 1 << (icaltime_day_of_week( m_start->m_datetime )-1); } short weekdaymask = m_recurweekdays; int k=0; // bool weekdaymatchesstartdate=false; for( int i=0; i<7; i++ ) { if( weekdaymask & 1 ) { recur.by_day[k++]=i+1; // if( !weekdaymatchesstartdate ) { // m_start->AdjustToWeekday( i+1 ); // m_end->AdjustToWeekday( i+1 ); // weekdaymatchesstartdate=true; // } } weekdaymask >>= 1; } prop = icalproperty_new_rrule( recur ); icalcomponent_add_property( vevent, prop ); break; } case RECUR_MONTHLY_MDAY: recur.freq = ICAL_MONTHLY_RECURRENCE; if( m_recurweeknumber ) { // printf( "DAY: %d\n" , icaltime_day_of_week( m_start->m_datetime ) ); // printf( "WEEKNUMBER: %d\n" , m_recurweeknumber ); if( m_recurweeknumber != 5 ) recur.by_day[0] = icaltime_day_of_week( m_start->m_datetime ) + m_recurweeknumber*8; else recur.by_day[0] = - icaltime_day_of_week( m_start->m_datetime ) - 8 ; } prop = icalproperty_new_rrule( recur ); icalcomponent_add_property( vevent, prop ); break; case RECUR_MONTHLY_WDAY: recur.freq = ICAL_MONTHLY_RECURRENCE; prop = icalproperty_new_rrule( recur ); icalcomponent_add_property( vevent, prop ); break; case RECUR_YEARLY: recur.by_month[0] = m_start->m_datetime.month; recur.freq = ICAL_YEARLY_RECURRENCE; prop = icalproperty_new_rrule( recur ); icalcomponent_add_property( vevent, prop ); break; } //exceptions for( int i=0; im_datetime ) ) { m_start->GetTzID( &starttzid ); if( m_allday ) { m_start->SetHour( 0 ); m_start->SetMinute( 0 ); m_start->m_datetime.is_date = true; //This will reflect the event being an all-day event prop = icalproperty_new_dtstart( m_start->m_datetime ); if( starttzid ) { icaltimezone *timezone = icaltimezone_get_builtin_timezone_from_tzid (starttzid); icalparameter *tmppar = icalparameter_new_tzid( starttzid ); icalproperty_add_parameter( prop, tmppar ); icalcomponent_add_component( newcalendar, icalcomponent_new_clone( icaltimezone_get_component ( timezone ) ) ); } m_start->m_datetime.is_date = false; //Because currently we depend on m_datetime being a complete datetime value. } else { if( starttzid ) { icaltimezone *timezone = icaltimezone_get_builtin_timezone_from_tzid (starttzid); icaltimetype convertedtime = m_start->m_datetime; icaltimezone_convert_time ( &convertedtime, currenttimezone, timezone ); if( strcmp( starttzid, "/Mozilla.org/BasicTimezones/GMT" )==0 ) { convertedtime.is_utc = true; prop = icalproperty_new_dtstart( convertedtime ); } else { prop = icalproperty_new_dtstart( convertedtime ); icalparameter *tmppar = icalparameter_new_tzid( starttzid ); icalproperty_add_parameter( prop, tmppar ); icalcomponent_add_component( newcalendar, icalcomponent_new_clone( icaltimezone_get_component ( timezone ) ) ); } } else prop = icalproperty_new_dtstart( m_start->m_datetime ); } icalcomponent_add_property( vevent, prop ); } //enddate if( m_end && !icaltime_is_null_time( m_end->m_datetime ) ) { char *tzid=nsnull; m_end->GetTzID( &tzid ); if( m_allday ) { if( m_end->CompareDate( m_start )==0 ) { m_end->m_datetime = m_start->m_datetime; icaltime_adjust( &(m_end->m_datetime), 1, 0, 0, 0 ); } else { m_end->SetHour( 0 ); m_end->SetMinute( 0 ); } m_end->m_datetime.is_date = true; prop = icalproperty_new_dtend( m_end->m_datetime ); if( tzid ) { icaltimezone *timezone = icaltimezone_get_builtin_timezone_from_tzid (tzid); icalparameter *tmppar = icalparameter_new_tzid( tzid ); icalproperty_add_parameter( prop, tmppar ); if( !starttzid || strcmp( starttzid, tzid ) != 0 ) icalcomponent_add_component( newcalendar, icalcomponent_new_clone( icaltimezone_get_component ( timezone ) ) ); nsMemory::Free( tzid ); } m_end->m_datetime.is_date = false; //Because currently we depend on m_datetime being a complete datetime value. } else { if( tzid ) { icaltimezone *timezone = icaltimezone_get_builtin_timezone_from_tzid (tzid); icaltimetype convertedtime = m_end->m_datetime; icaltimezone_convert_time ( &convertedtime, currenttimezone, timezone ); if( strcmp( tzid, "/Mozilla.org/BasicTimezones/GMT" )==0 ) { convertedtime.is_utc = true; prop = icalproperty_new_dtend( convertedtime ); } else { prop = icalproperty_new_dtend( convertedtime ); icalparameter *tmppar = icalparameter_new_tzid( tzid ); icalproperty_add_parameter( prop, tmppar ); if( !starttzid || strcmp( starttzid, tzid ) != 0 ) icalcomponent_add_component( newcalendar, icalcomponent_new_clone( icaltimezone_get_component ( timezone ) ) ); } nsMemory::Free( tzid ); } else prop = icalproperty_new_dtend( m_end->m_datetime ); } icalcomponent_add_property( vevent, prop ); } if( starttzid ) nsMemory::Free( starttzid ); if( m_stamp && !icaltime_is_null_time( m_stamp->m_datetime ) ) { //stampdate prop = icalproperty_new_dtstamp( m_stamp->m_datetime ); icalcomponent_add_property( vevent, prop ); } //snoozetimes icalcomponent *tmpcomp=NULL; int j; for( j=0; jCount(&attachmentCount); nsCOMPtr element; unsigned int i; for (i = 0; i < attachmentCount; i ++) { m_attachments->QueryElementAt(i, NS_GET_IID(nsIMsgAttachment), getter_AddRefs(element)); if (element) { char *url; element->GetUrl( &url ); icalparameter *tmppar = icalparameter_new_member( "Attachment" ); prop = icalproperty_new_x( url ); icalproperty_add_parameter( prop, tmppar ); icalcomponent_add_property( vevent, prop ); /* icalattach *attach= icalattach_new_from_url( url ); if( attach ) { char tst[100]= "testing"; char *buffer; buffer = PL_Base64Encode( tst, strlen(tst), nsnull ); // strcpy( buffer, "salam" ); // icalattachtype_set_base64( attachtype, buffer, 0 ); prop = icalproperty_new_attach( attach ); // tmppar = icalparameter_new_fmttype( url ); // icalproperty_add_parameter( prop, tmppar ); // tmppar = icalparameter_new_encoding( ICAL_ENCODING_BASE64 ); // icalproperty_add_parameter( prop, tmppar ); icalcomponent_add_property( vevent, prop ); }*/ nsMemory::Free( url ); } } PRUint32 contactCount = 0; m_contacts->Count(&contactCount); nsCOMPtr contact; for (i = 0; i < contactCount; i ++) { m_contacts->QueryElementAt(i, NS_GET_IID(nsIAbCard), getter_AddRefs(contact)); if (contact) { nsXPIDLString email; contact->GetPrimaryEmail( getter_Copies( email ) ); NS_ConvertUCS2toUTF8 aUtf8Str(email); prop = icalproperty_new_contact( aUtf8Str.get() ); icalcomponent_add_property( vevent, prop ); } } //add event to newcalendar icalcomponent_add_component( newcalendar, vevent ); return newcalendar; } /********************************************************************************************/ #include "nsIServiceManager.h" NS_IMPL_ADDREF(oeICalEventDisplayImpl) NS_IMPL_RELEASE(oeICalEventDisplayImpl) //NS_IMPL_ISUPPORTS1(oeICalEventDisplayImpl, oeIICalEventDisplay) nsresult NS_NewICalEventDisplay( oeIICalEvent* event, oeIICalEventDisplay** inst ) { NS_PRECONDITION(inst != nsnull, "null ptr"); if (! inst) return NS_ERROR_NULL_POINTER; *inst = new oeICalEventDisplayImpl( event ); if (! *inst) return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(*inst); return NS_OK; } oeICalEventDisplayImpl::oeICalEventDisplayImpl( oeIICalEvent* event ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventDisplayImpl::oeICalEventDisplayImpl(): %d\n", ++gEventDisplayCount ); #endif nsresult rv; if( event == nsnull ) { mEvent = do_CreateInstance(OE_ICALEVENTDISPLAY_CONTRACTID, &rv); } else { mEvent = event; } /* member initializers and constructor code */ m_displaydate = icaltime_null_time(); } oeICalEventDisplayImpl::~oeICalEventDisplayImpl() { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventDisplayImpl::~oeICalEventDisplayImpl(): %d\n", --gEventDisplayCount ); #endif /* destructor code */ mEvent = nsnull; } NS_IMETHODIMP oeICalEventDisplayImpl::QueryInterface(REFNSIID aIID, void** aInstancePtr) { if (nsnull == aInstancePtr) { return NS_ERROR_NULL_POINTER; } if (aIID.Equals(NS_GET_IID(nsISupports))) { *aInstancePtr = (void*)(oeIICalEventDisplay*)this; *aInstancePtr = (nsISupports*)*aInstancePtr; NS_ADDREF_THIS(); return NS_OK; } if (aIID.Equals(NS_GET_IID(oeIICalEventDisplay))) { *aInstancePtr = (void*)(oeIICalEventDisplay*)this; NS_ADDREF_THIS(); return NS_OK; } if (aIID.Equals(NS_GET_IID(oeIICalEvent))) { return mEvent->QueryInterface( aIID, aInstancePtr ); } return NS_NOINTERFACE; } NS_IMETHODIMP oeICalEventDisplayImpl::GetDisplayDate( PRTime *aRetVal ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventDisplayImpl::GetDisplayDate()\n" ); #endif *aRetVal = ConvertToPrtime( m_displaydate ); return NS_OK; } NS_IMETHODIMP oeICalEventDisplayImpl::SetDisplayDate( PRTime aNewVal ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventDisplayImpl::SetDisplayDate()\n" ); #endif m_displaydate = ConvertFromPrtime( aNewVal ); return NS_OK; } NS_IMETHODIMP oeICalEventDisplayImpl::GetDisplayEndDate( PRTime *aRetVal ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventDisplayImpl::GetDisplayEndDate()\n" ); #endif *aRetVal = ConvertToPrtime( m_displaydateend ); return NS_OK; } NS_IMETHODIMP oeICalEventDisplayImpl::SetDisplayEndDate( PRTime aNewVal ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventDisplayImpl::SetDisplayEndDate()\n" ); #endif m_displaydateend = ConvertFromPrtime( aNewVal ); return NS_OK; } NS_IMETHODIMP oeICalEventDisplayImpl::GetEvent( oeIICalEvent **ev ) { #ifdef ICAL_DEBUG_ALL printf( "oeICalEventDisplayImpl::GetEvent()\n" ); #endif #ifdef ICAL_DEBUG_ALL printf( "WARNING: .event is no longer needed to access event fields\n" ); #endif *ev = mEvent; NS_ADDREF(*ev); return NS_OK; }