diff --git a/src/containers/kolabcontact.h b/src/containers/kolabcontact.h index 58ded59..ffc6faf 100644 --- a/src/containers/kolabcontact.h +++ b/src/containers/kolabcontact.h @@ -1,431 +1,431 @@ /* * Copyright (C) 2011 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef KOLABCONTACT_H #define KOLABCONTACT_H #include #include #include #include "kolabcontainers.h" namespace Kolab { - + struct NameComponents { bool operator==(const NameComponents &other) const { return mSurnames == other.mSurnames && mGiven == other.mGiven && mAdditional == other.mAdditional && mPrefixes == other.mPrefixes && mSuffixes == other.mSuffixes; - }; - void setSurnames(const std::vector &s) { mSurnames = s; }; - std::vector surnames() const { return mSurnames; }; - void setGiven(const std::vector &s) { mGiven = s; }; - std::vector given() const { return mGiven; }; - void setAdditional(const std::vector &s) { mAdditional = s; }; - std::vector additional() const { return mAdditional; }; - void setPrefixes(const std::vector &s) { mPrefixes = s; }; - std::vector prefixes() const { return mPrefixes; }; - void setSuffixes(const std::vector &s) { mSuffixes = s; }; - std::vector suffixes() const { return mSuffixes; }; - bool isValid() const { return !(mSurnames.empty() && mGiven.empty() && mAdditional.empty() && mPrefixes.empty() && mSuffixes.empty()); }; + } + void setSurnames(const std::vector &s) { mSurnames = s; } + std::vector surnames() const { return mSurnames; } + void setGiven(const std::vector &s) { mGiven = s; } + std::vector given() const { return mGiven; } + void setAdditional(const std::vector &s) { mAdditional = s; } + std::vector additional() const { return mAdditional; } + void setPrefixes(const std::vector &s) { mPrefixes = s; } + std::vector prefixes() const { return mPrefixes; } + void setSuffixes(const std::vector &s) { mSuffixes = s; } + std::vector suffixes() const { return mSuffixes; } + bool isValid() const { return !(mSurnames.empty() && mGiven.empty() && mAdditional.empty() && mPrefixes.empty() && mSuffixes.empty()); } private: std::vector mSurnames; std::vector mGiven; std::vector mAdditional; std::vector mPrefixes; std::vector mSuffixes; }; struct Related { - + enum DescriptionType { Invalid, Text, Uid }; - Related(): mType(Invalid), mRelationType(NoRelation) {}; + Related(): mType(Invalid), mRelationType(NoRelation) {} Related(DescriptionType t, const std::string &textOrUri, int relationType = NoRelation) : mType(t), mRelationType(relationType) { if (t == Text) { mText = textOrUri; } else { mUri = textOrUri; } - }; + } bool operator==(const Related &other) const { return mType == other.mType && - mUri == other.mUri && - mText == other.mText && - mRelationType == other.mRelationType; - }; - DescriptionType type() const { return mType; }; - std::string uri() const { return mUri; }; - std::string text() const { return mText; }; + mUri == other.mUri && + mText == other.mText && + mRelationType == other.mRelationType; + } + DescriptionType type() const { return mType; } + std::string uri() const { return mUri; } + std::string text() const { return mText; } enum RelationType { NoRelation = 0, Child = 0x01, Spouse = 0x02, Manager = 0x04, - Assistant = 0x08, + Assistant = 0x08 }; - void setRelationTypes(int t) { mRelationType = t; }; - int relationTypes() const { return mRelationType; }; + void setRelationTypes(int t) { mRelationType = t; } + int relationTypes() const { return mRelationType; } private: DescriptionType mType; std::string mUri; std::string mText; int mRelationType; }; struct Address { - - Address(): mTypes(0) {}; + + Address(): mTypes(0) {} enum Type { Work = 0x01, Home = 0x02 }; bool operator==(const Address &other) const { return mTypes == other.mTypes && mLabel == other.mLabel && mStreet == other.mStreet && mLocality == other.mLocality && mRegion == other.mRegion && mCode == other.mCode && mCountry == other.mCountry; - }; - void setTypes(int t) { mTypes = t; }; - int types() const { return mTypes; }; - - void setLabel(const std::string &s) { mLabel = s; }; + } + void setTypes(int t) { mTypes = t; } + int types() const { return mTypes; } + + void setLabel(const std::string &s) { mLabel = s; } std::string label() const { return mLabel; } - - void setStreet(const std::string &s) { mStreet = s; }; - std::string street() const { return mStreet; }; - - void setLocality(const std::string &s) { mLocality = s; }; - std::string locality() const { return mLocality; }; - - void setRegion(const std::string &s) { mRegion = s; }; - std::string region() const { return mRegion; }; - - void setCode(const std::string &s) { mCode = s; }; - std::string code() const { return mCode; }; - - void setCountry(const std::string &s) { mCountry = s; }; - std::string country() const { return mCountry; }; + + void setStreet(const std::string &s) { mStreet = s; } + std::string street() const { return mStreet; } + + void setLocality(const std::string &s) { mLocality = s; } + std::string locality() const { return mLocality; } + + void setRegion(const std::string &s) { mRegion = s; } + std::string region() const { return mRegion; } + + void setCode(const std::string &s) { mCode = s; } + std::string code() const { return mCode; } + + void setCountry(const std::string &s) { mCountry = s; } + std::string country() const { return mCountry; } private: int mTypes; std::string mLabel; std::string mStreet; std::string mLocality; std::string mRegion; std::string mCode; std::string mCountry; }; struct Affiliation { bool operator==(const Affiliation &other) const { return mOrg == other.mOrg && mOrgUnits == other.mOrgUnits && mLogo == other.mLogo && mLogoMimetype == other.mLogoMimetype && mRoles == other.mRoles && mRelateds == other.mRelateds && mOffices == other.mOffices; - }; - void setOrganisation(const std::string &org) { mOrg = org; }; - std::string organisation() const { return mOrg; }; - void setOrganisationalUnits(const std::vector &units) { mOrgUnits = units; }; - std::vector organisationalUnits() const { return mOrgUnits; }; - void setLogo(const std::string &l, const std::string mimetype) { mLogo = l; mLogoMimetype = mimetype; }; - std::string logo() const { return mLogo; }; - std::string logoMimetype() const { return mLogoMimetype; }; - - void setRoles(const std::vector &roles) { mRoles = roles; }; - std::vector roles() const { return mRoles; }; - void setRelateds(const std::vector &relateds) { mRelateds = relateds; }; - std::vector relateds() const { return mRelateds; }; - void setAddresses(const std::vector
&offices) { mOffices = offices; }; - std::vector
addresses() const { return mOffices; }; + } + void setOrganisation(const std::string &org) { mOrg = org; } + std::string organisation() const { return mOrg; } + void setOrganisationalUnits(const std::vector &units) { mOrgUnits = units; } + std::vector organisationalUnits() const { return mOrgUnits; } + void setLogo(const std::string &l, const std::string mimetype) { mLogo = l; mLogoMimetype = mimetype; } + std::string logo() const { return mLogo; } + std::string logoMimetype() const { return mLogoMimetype; } + + void setRoles(const std::vector &roles) { mRoles = roles; } + std::vector roles() const { return mRoles; } + void setRelateds(const std::vector &relateds) { mRelateds = relateds; } + std::vector relateds() const { return mRelateds; } + void setAddresses(const std::vector
&offices) { mOffices = offices; } + std::vector
addresses() const { return mOffices; } private: std::string mOrg; std::vector mOrgUnits; std::string mLogo; std::string mLogoMimetype; std::vector mRoles; std::vector mRelateds; std::vector
mOffices; }; struct Telephone { enum Type { Work = 0x01, Home = 0x02, Text = 0x04, Voice = 0x08, Fax = 0x10, Cell = 0x20, Video = 0x40, Pager = 0x80, Textphone = 0x100, Car = 0x200 }; - Telephone(): mType(0){}; + Telephone(): mType(0){} bool operator==(const Telephone &other) const { return mNumber == other.mNumber && mType == other.mType; - }; - void setTypes(int t) { mType = t; }; - int types() const { return mType; }; - void setNumber(const std::string &n) { mNumber = n; }; - std::string number() const { return mNumber; }; + } + void setTypes(int t) { mType = t; } + int types() const { return mType; } + void setNumber(const std::string &n) { mNumber = n; } + std::string number() const { return mNumber; } private: std::string mNumber; int mType; }; struct Email { enum Type { NoType = 0, Work = 0x01, Home = 0x02 }; - Email(): mType(NoType){}; - Email(const std::string &a, int t = NoType): mAddress(a), mType(t) {}; + Email(): mType(NoType){} + Email(const std::string &a, int t = NoType): mAddress(a), mType(t) {} bool operator==(const Email &other) const { return mAddress == other.mAddress && - mType == other.mType; }; - void setTypes(int t) { mType = t; }; - int types() const { return mType; }; - void setAddress(const std::string &n) { mAddress = n; }; - std::string address() const { return mAddress; }; + mType == other.mType; } + void setTypes(int t) { mType = t; } + int types() const { return mType; } + void setAddress(const std::string &n) { mAddress = n; } + std::string address() const { return mAddress; } private: std::string mAddress; int mType; }; struct Crypto { enum CryptoTypes { PGPinline = 0x01, PGPmime = 0x02, SMIME = 0x04, SMIMEopaque = 0x08 }; - + enum CryptoPref { Ask, Never, Always, IfPossible }; - Crypto(): mCryptoTypes(0), mSignPref(Ask), mEncryptPref(Ask){}; + Crypto(): mCryptoTypes(0), mSignPref(Ask), mEncryptPref(Ask){} bool operator==(const Crypto &other) const { return mCryptoTypes == other.mCryptoTypes && mSignPref == other.mSignPref && - mEncryptPref == other.mEncryptPref; }; - bool isValid() const { return mCryptoTypes; }; - - void setAllowed(int cryptoTypes) { mCryptoTypes = cryptoTypes; }; - int allowed() const { return mCryptoTypes; }; - void setSignPref(CryptoPref p) { mSignPref = p; }; - CryptoPref signPref() const { return mSignPref; }; - void setEncryptPref(CryptoPref p) { mEncryptPref = p; }; - CryptoPref encryptPref() const { return mEncryptPref; }; + mEncryptPref == other.mEncryptPref; } + bool isValid() const { return mCryptoTypes; } + + void setAllowed(int cryptoTypes) { mCryptoTypes = cryptoTypes; } + int allowed() const { return mCryptoTypes; } + void setSignPref(CryptoPref p) { mSignPref = p; } + CryptoPref signPref() const { return mSignPref; } + void setEncryptPref(CryptoPref p) { mEncryptPref = p; } + CryptoPref encryptPref() const { return mEncryptPref; } private: int mCryptoTypes; CryptoPref mSignPref; CryptoPref mEncryptPref; }; struct Geo { - Geo(): latitude(0.0), longitude(0.0) {}; + Geo(): latitude(0.0), longitude(0.0) {} Geo(double lat, double lon) - : latitude(lat), longitude(lon) {}; - - bool operator==(const Geo &other) const{ return (longitude == other.longitude && latitude == other.latitude);}; + : latitude(lat), longitude(lon) {} + + bool operator==(const Geo &other) const{ return (longitude == other.longitude && latitude == other.latitude);} double latitude; double longitude; }; struct Url { enum UrlTypes { NoType = 0, Blog }; - Url(): mType(NoType) {}; - Url(const std::string &u, int t = NoType): mUrl(u), mType(t) {}; - - bool operator==(const Url &other) const{ return (mType == other.mType && mUrl == other.mUrl);}; - - int type() const { return mType; }; - std::string url() const { return mUrl; }; + Url(): mType(NoType) {} + Url(const std::string &u, int t = NoType): mUrl(u), mType(t) {} + + bool operator==(const Url &other) const{ return (mType == other.mType && mUrl == other.mUrl);} + + int type() const { return mType; } + std::string url() const { return mUrl; } private: std::string mUrl; int mType; }; struct Key { enum KeyType { Invalid, PGP, PKCS7_MIME }; - Key(): keytype(Invalid) {}; + Key(): keytype(Invalid) {} Key(const std::string &k, KeyType type) - : mKey(k), keytype(type) {}; - - bool operator==(const Key &other) const{ return (mKey == other.mKey && keytype == other.keytype);}; - - KeyType type() const { return keytype; }; - std::string key() const { return mKey; }; - + : mKey(k), keytype(type) {} + + bool operator==(const Key &other) const{ return (mKey == other.mKey && keytype == other.keytype);} + + KeyType type() const { return keytype; } + std::string key() const { return mKey; } + private: std::string mKey; KeyType keytype; }; class DistList { public: DistList(); ~DistList(); DistList(const DistList &); void operator=(const DistList &); bool isValid() const; void setUid(const std::string &); std::string uid() const; void setLastModified(const cDateTime &); cDateTime lastModified() const; void setName(const std::string &); std::string name() const; void setMembers(const std::vector &); std::vector members() const; void setCustomProperties(const std::vector &); std::vector customProperties() const; private: struct Private; boost::scoped_ptr d; }; class Contact { public: Contact(); ~Contact(); Contact(const Contact &); void operator=(const Contact &); bool isValid() const; void setUid(const std::string &); std::string uid() const; - + void setLastModified(const cDateTime &); cDateTime lastModified() const; - + void setCategories(const std::vector &); void addCategory(const std::string &); std::vector categories() const; - + void setName(const std::string &); std::string name() const; - + void setNameComponents(const NameComponents &); NameComponents nameComponents() const; - + void setNote(const std::string &); std::string note() const; - + void setFreeBusyUrl(const std::string &); std::string freeBusyUrl() const; - + void setTitles(const std::vector &titles); std::vector titles() const; - + void setAffiliations(const std::vector &); std::vector affiliations() const; - + void setUrls(const std::vector &); std::vector urls() const; - + void setAddresses(const std::vector
&, int preferred = -1); std::vector
addresses() const; int addressPreferredIndex() const; - + void setNickNames(const std::vector< std::string > &); std::vector< std::string > nickNames() const; - + void setRelateds(const std::vector &); std::vector relateds() const; - + void setBDay(const cDateTime &); cDateTime bDay() const; - + void setAnniversary(const cDateTime &); cDateTime anniversary() const; - + void setPhoto(const std::string &data, const std::string &mimetype); std::string photo() const; std::string photoMimetype() const; - + enum Gender { NotSet, NotSpecified, Male, Female }; - + void setGender(Gender); Gender gender() const; - + void setLanguages(const std::vector &); std::vector languages() const; - + void setTelephones(const std::vector &, int preferredIndex = -1); std::vector telephones() const; int telephonesPreferredIndex() const; - + void setIMaddresses(const std::vector &, int preferredIndex = -1); std::vector imAddresses() const; int imAddressPreferredIndex() const; - + void setEmailAddresses(const std::vector &, int preferredIndex = -1); std::vector emailAddresses() const; int emailAddressPreferredIndex() const; - + void setGPSpos(const std::vector &); std::vector gpsPos() const; - + void setKeys(const std::vector &); std::vector keys() const; - + void setCrypto(const Crypto &); Crypto crypto() const; - + void setCustomProperties(const std::vector &); std::vector customProperties() const; private: struct Private; boost::scoped_ptr d; }; } //Namespace #endif // KOLABCONTACT_H diff --git a/src/containers/kolabcontainers.cpp b/src/containers/kolabcontainers.cpp index fc241a1..b883657 100644 --- a/src/containers/kolabcontainers.cpp +++ b/src/containers/kolabcontainers.cpp @@ -1,771 +1,771 @@ /* * Copyright (C) 2011 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include "kolabcontainers.h" #include "incidence_p.h" namespace Kolab { - + struct cDateTime::Private { Private() : year(-1), month(-1), day(-1), hour(-1), minute(-1), second(-1), isUtc(false){} int year; int month; int day; int hour; int minute; int second; bool isUtc; std::string timezone; }; cDateTime::cDateTime() : d(new cDateTime::Private()) { } cDateTime::cDateTime(int year, int month, int day, int hour, int minute, int second, bool isUtc) : d(new cDateTime::Private()) { d->year = year; d->month = month; d->day = day; d->hour = hour; d->minute = minute; d->second = second; d->isUtc = isUtc; } cDateTime::cDateTime(const std::string& timezone, int year, int month, int day, int hour, int minute, int second) : d(new cDateTime::Private()) { d->year = year; d->month = month; d->day = day; d->hour = hour; d->minute = minute; d->second = second; d->timezone = timezone; } cDateTime::cDateTime(int year, int month, int day) : d(new cDateTime::Private()) { d->year = year; d->month = month; d->day = day; } cDateTime::cDateTime(const Kolab::cDateTime &other) : d(new cDateTime::Private()) { *d = *other.d; } cDateTime::~cDateTime() { } void cDateTime::operator=(const Kolab::cDateTime &other) { *d = *other.d; } bool cDateTime::operator==(const Kolab::cDateTime &other) const { if ( d->year == other.year() && d->month == other.month() && d->day == other.day() && d->hour == other.hour() && d->minute == other.minute() && d->second== other.second() && d->isUtc== other.isUTC() && d->timezone== other.timezone()) { return true; } return false; } int cDateTime::year() const { return d->year; } int cDateTime::month() const { return d->month; } int cDateTime::day() const { return d->day; } int cDateTime::hour() const { return d->hour; } int cDateTime::minute() const { return d->minute; } int cDateTime::second() const { return d->second; } bool cDateTime::isDateOnly() const { if ((d->hour < 0) && (d->minute < 0) && (d->second < 0)) { return true; } return false; } void cDateTime::setDate(int year, int month, int day) { d->year = year; d->month = month; d->day = day; } void cDateTime::setTime(int hour, int minute, int second) { d->hour = hour; d->minute = minute; d->second = second; } void cDateTime::setTimezone(const std::string &tz) { d->timezone = tz; } void cDateTime::setUTC(bool utc) { d->isUtc = utc; } bool cDateTime::isUTC() const { return d->isUtc; } std::string cDateTime::timezone() const { return d->timezone; } bool cDateTime::isValid() const { return (d->year >= 0 && d->month >= 0 && d->day >= 0); } struct RecurrenceRule::Private { Private() : freq(FreqNone), weekstart(Monday), count(-1), - interval(1){}; - + interval(1){} + Frequency freq; Weekday weekstart; cDateTime end; int count; int interval; std::vector bysecond; std::vector byminute; std::vector byhour; std::vector byday; std::vector bymonthday; std::vector byyearday; std::vector byweekno; std::vector bymonth; }; RecurrenceRule::RecurrenceRule() : d(new RecurrenceRule::Private) { - + } RecurrenceRule::RecurrenceRule(const Kolab::RecurrenceRule &other) : d(new RecurrenceRule::Private) { *d = *other.d; } void RecurrenceRule::operator=(const Kolab::RecurrenceRule &other) { *d = *other.d; } bool RecurrenceRule::operator==(const Kolab::RecurrenceRule &other) const { if ( d->freq == other.frequency() && d->weekstart == other.weekStart() && d->end == other.end() && d->count == other.count() && d->interval == other.interval() && d->bysecond == other.bysecond() && d->byminute == other.byminute() && d->byhour == other.byhour() && d->byday == other.byday() && d->bymonthday == other.bymonthday() && d->byyearday == other.byyearday() && d->byweekno == other.byweekno() && d->bymonth == other.bymonth()) { return true; } return false; } RecurrenceRule::~RecurrenceRule() { - + } void RecurrenceRule::setFrequency(RecurrenceRule::Frequency freq) { d->freq = freq; } RecurrenceRule::Frequency RecurrenceRule::frequency() const { return d->freq; } void RecurrenceRule::setWeekStart(Kolab::Weekday weekstart) { d->weekstart = weekstart; } Kolab::Weekday RecurrenceRule::weekStart() const { return d->weekstart; } void RecurrenceRule::setEnd(const Kolab::cDateTime &end) { d->end = end; } cDateTime RecurrenceRule::end() const { return d->end; } void RecurrenceRule::setCount(int count) { d->count = count; } int RecurrenceRule::count() const { return d->count; } void RecurrenceRule::setInterval(int interval) { d->interval = interval; } int RecurrenceRule::interval() const { return d->interval; } void RecurrenceRule::setBysecond(const std::vector< int >&by) { d->bysecond = by; } std::vector< int > RecurrenceRule::bysecond() const { return d->bysecond; } void RecurrenceRule::setByminute(const std::vector< int > &by) { d->byminute = by; } std::vector< int > RecurrenceRule::byminute() const { return d->byminute; } void RecurrenceRule::setByhour(const std::vector< int > &by) { d->byhour = by; } std::vector< int > RecurrenceRule::byhour() const { return d->byhour; } void RecurrenceRule::setByday(const std::vector< DayPos > &by) { d->byday = by; } std::vector< DayPos > RecurrenceRule::byday() const { return d->byday; } void RecurrenceRule::setBymonthday(const std::vector< int > &by) { d->bymonthday = by; } std::vector< int > RecurrenceRule::bymonthday() const { return d->bymonthday; } void RecurrenceRule::setByyearday(const std::vector< int > &by) { d->byyearday = by; } std::vector< int > RecurrenceRule::byyearday() const { return d->byyearday; } void RecurrenceRule::setByweekno(const std::vector< int > &by) { d->byweekno = by; } std::vector< int > RecurrenceRule::byweekno() const { return d->byweekno; } void RecurrenceRule::setBymonth(const std::vector< int > &by) { d->bymonth = by; } std::vector< int > RecurrenceRule::bymonth() const { return d->bymonth; } bool RecurrenceRule::isValid() const { if (d->freq == FreqNone) { return false; } return true; } struct Attendee::Private { Private() : partStat(PartNeedsAction), role(Required), rsvp(false), cutype(CutypeIndividual) - {}; - + {} + ContactReference contact; PartStatus partStat; Role role; bool rsvp; std::vector delegatedTo; std::vector delegatedFrom; Cutype cutype; }; Attendee::Attendee() : d(new Attendee::Private) { } Attendee::Attendee(const ContactReference& contact) : d(new Attendee::Private) { - d->contact = contact; + d->contact = contact; } Attendee::Attendee(const Kolab::Attendee &other) : d(new Attendee::Private) { *d = *other.d; } void Attendee::operator=(const Kolab::Attendee &other) { *d = *other.d; } Attendee::~Attendee() { } bool Attendee::operator==(const Kolab::Attendee &other) const { if ( d->contact == other.contact() && d->partStat == other.partStat() && d->role == other.role() && d->rsvp == other.rsvp() && d->delegatedTo == other.delegatedTo() && d->delegatedFrom == other.delegatedFrom() && d->cutype == other.cutype() ) { return true; } return false; } -bool Attendee::isValid() const -{ +bool Attendee::isValid() const +{ return d->contact.isValid(); -}; +} void Attendee::setContact(const ContactReference &c) { d->contact = c; } ContactReference Attendee::contact() const { return d->contact; } void Attendee::setPartStat(PartStatus partStat) { d->partStat = partStat; } PartStatus Attendee::partStat() const { return d->partStat; } void Attendee::setRole(Role role) { d->role = role; } Role Attendee::role() const { return d->role; } void Attendee::setRSVP(bool rsvp) { d->rsvp = rsvp; } bool Attendee::rsvp() const { return d->rsvp; } void Attendee::setDelegatedTo(const std::vector< ContactReference > &del) { d->delegatedTo = del; } std::vector< ContactReference > Attendee::delegatedTo() const { return d->delegatedTo; } void Attendee::setDelegatedFrom(const std::vector< ContactReference > &del) { d->delegatedFrom = del; } std::vector< ContactReference > Attendee::delegatedFrom() const { return d->delegatedFrom; } void Attendee::setCutype(Cutype type) { d->cutype = type; } Cutype Attendee::cutype() const { return d->cutype; } struct Attachment::Private { std::string uri; std::string data; std::string mimetype; std::string label; bool isValid; }; Attachment::Attachment() : d(new Attachment::Private) { d->isValid = false; } Attachment::Attachment(const Kolab::Attachment &other) : d(new Attachment::Private) { *d = *other.d; } void Attachment::operator=(const Kolab::Attachment &other) { *d = *other.d; } Attachment::~Attachment() { } bool Attachment::operator==(const Kolab::Attachment &other) const { return ( d->uri == other.uri() && d->data == other.data() && d->label == other.label() && d->mimetype == other.mimetype() ); } void Attachment::setUri(const std::string &uri, const std::string& mimetype) { d->isValid = true; d->uri = uri; d->mimetype = mimetype; } std::string Attachment::uri() const { return d->uri; } std::string Attachment::mimetype() const { return d->mimetype; } void Attachment::setLabel(const std::string &label) { d->label = label; } std::string Attachment::label() const { return d->label; } void Attachment::setData(const std::string &data, const std::string& mimetype) { d->isValid = true; d->data = data; d->mimetype = mimetype; } std::string Attachment::data() const { return d->data; } bool Attachment::isValid() const { return d->isValid; } struct Alarm::Private { Private(): relativeTo(Start), numrepeat(0), - type(Alarm::InvalidAlarm) {}; + type(Alarm::InvalidAlarm) {} std::string text; Attachment audioFile; std::string summary; std::vector attendees; cDateTime start; Duration relativeDuration; Relative relativeTo; Duration duration; int numrepeat; Type type; - + }; Alarm::Alarm() : d(new Alarm::Private) { } Alarm::Alarm(const std::string &text) : d(new Alarm::Private) { d->text = text; d->type = DisplayAlarm; } Alarm::Alarm(const Kolab::Attachment& audio) : d(new Alarm::Private) { d->audioFile = audio; d->type = AudioAlarm; } Alarm::Alarm(const std::string& summary, const std::string& description, const std::vector attendees) : d(new Alarm::Private) { d->summary = summary; d->text = description; d->attendees = attendees; d->type = EMailAlarm; - + } Alarm::Alarm(const Kolab::Alarm &other) : d(new Alarm::Private) { *d = *other.d; } void Alarm::operator=(const Kolab::Alarm &other) { *d = *other.d; } Alarm::~Alarm() { } bool Alarm::operator==(const Kolab::Alarm &other) const { return ( d->text == other.description() && d->text == other.description() && d->audioFile == other.audioFile() && d->summary == other.summary() && d->attendees == other.attendees() && d->start == other.start() && d->relativeDuration == other.relativeStart() && d->relativeTo == other.relativeTo() && d->duration == other.duration() && d->numrepeat == other.numrepeat() ); } std::string Alarm::text() const { return d->text; } Attachment Alarm::audioFile() const { return d->audioFile; } std::string Alarm::summary() const { return d->summary; } std::string Alarm::description() const { return d->text; } std::vector Alarm::attendees() const { return d->attendees; } void Alarm::setStart(const Kolab::cDateTime &start) { d->start = start; } cDateTime Alarm::start() const { return d->start; } void Alarm::setRelativeStart(const Kolab::Duration &duration, Relative relativeTo) { d->relativeDuration = duration; d->relativeTo = relativeTo; } Duration Alarm::relativeStart() const { return d->relativeDuration; } Relative Alarm::relativeTo() const { return d->relativeTo; } void Alarm::setDuration(const Kolab::Duration &duration, int numrepeat) { d->numrepeat = numrepeat; d->duration = duration; } Duration Alarm::duration() const { return d->duration; } int Alarm::numrepeat() const { return d->numrepeat; } Alarm::Type Alarm::type() const { return d->type; } }//Namespace diff --git a/src/containers/kolabcontainers.h b/src/containers/kolabcontainers.h index af44c24..ae25039 100644 --- a/src/containers/kolabcontainers.h +++ b/src/containers/kolabcontainers.h @@ -1,417 +1,416 @@ /* * Copyright (C) 2011 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef KOLAB_CONTAINERS_H #define KOLAB_CONTAINERS_H #include #include #include namespace Kolab { /** * - months: 1-12 * - days: 1-31 * - hour: 0-23 * - minute: 0-59 * - second: 0-59 */ class cDateTime { public: cDateTime(); cDateTime(int year, int month, int day, int hour, int minute, int second, bool isUtc=false); cDateTime(const std::string &timezone, int year, int month, int day, int hour, int minute, int second); cDateTime(int year, int month, int day); ~cDateTime(); cDateTime(const cDateTime &); void operator=(const cDateTime &); bool operator==(const cDateTime &) const; - - + + void setDate(int year, int month, int day); int year() const; int month() const; int day() const; - + bool isDateOnly() const; - + void setTime(int hour, int minute, int second); int hour() const; int minute() const; int second() const; - + void setUTC(bool); bool isUTC() const; void setTimezone(const std::string &); std::string timezone() const; - + bool isValid() const; private: struct Private; boost::scoped_ptr d; }; enum Classification { ClassPublic, ClassPrivate, ClassConfidential }; enum Status { StatusUndefined, StatusNeedsAction, StatusCompleted, StatusInProcess, StatusCancelled, StatusTentative, StatusConfirmed, StatusDraft, StatusFinal }; enum Weekday { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }; struct DayPos { - DayPos(): mIsValid(false){}; - DayPos(int occurrence, Weekday weekday): mOccurrence(occurrence), mWeekday(weekday), mIsValid(true){}; - bool operator==(const DayPos &other) const { return mOccurrence == other.mOccurrence && mWeekday == other.mWeekday; }; - int occurence() const { return mOccurrence; }; - Weekday weekday() const { return mWeekday; }; - bool isValid() { return mIsValid; }; + DayPos(): mIsValid(false){} + DayPos(int occurrence, Weekday weekday): mOccurrence(occurrence), mWeekday(weekday), mIsValid(true){} + bool operator==(const DayPos &other) const { return mOccurrence == other.mOccurrence && mWeekday == other.mWeekday; } + int occurence() const { return mOccurrence; } + Weekday weekday() const { return mWeekday; } + bool isValid() { return mIsValid; } private: int mOccurrence; Weekday mWeekday; bool mIsValid; }; class Attachment { public: Attachment(); Attachment(const Kolab::Attachment &); ~Attachment(); void operator=(const Attachment &); bool operator==(const Attachment &) const; void setUri(const std::string &uri, const std::string &mimetype); std::string uri() const; ///Un-encoded binary content, Implies embedded, will be encoded void setData(const std::string &, const std::string &mimetype); ///Decoded binary content. std::string data() const; //TODO add possibility to set already encoded data and uri to be embedded as performance/convenience improvement? // ///Base64 encoded binary content, Implies embedded // void setEncodedData(const std::string &, const std::string &mimetype); std::string mimetype() const; ///User visible label void setLabel(const std::string &); std::string label() const; - + bool isValid() const; private: struct Private; boost::scoped_ptr d; }; enum Relative { Start, End }; struct Duration { - Duration():mWeeks(0), mDays(0), mHours(0), mMinutes(0), mSeconds(0), mNegative(false), valid(false){}; - Duration(int weeks, bool negative = false): mWeeks(weeks), mDays(0), mHours(0), mMinutes(0), mSeconds(0), mNegative(negative), valid(true){}; - Duration(int days, int hours, int minutes, int seconds, bool negative = false): mWeeks(0), mDays(days), mHours(hours), mMinutes(minutes), mSeconds(seconds), mNegative(negative), valid(true){}; - bool operator==(const Duration &other) const{ return (/*mWeeks == other.mWeeks && + Duration():mWeeks(0), mDays(0), mHours(0), mMinutes(0), mSeconds(0), mNegative(false), valid(false){} + Duration(int weeks, bool negative = false): mWeeks(weeks), mDays(0), mHours(0), mMinutes(0), mSeconds(0), mNegative(negative), valid(true){} + Duration(int days, int hours, int minutes, int seconds, bool negative = false): mWeeks(0), mDays(days), mHours(hours), mMinutes(minutes), mSeconds(seconds), mNegative(negative), valid(true){} + bool operator==(const Duration &other) const{ return (/*mWeeks == other.mWeeks && mDays == other.mDays && mHours == other.mHours && mMinutes == other.mMinutes && mSeconds == other.mSeconds && mNegative == other.mNegative &&*/ ( ((((mWeeks * 7 + mDays) * 24 + mHours) * 60 + mMinutes) * 60 + mSeconds) == ((((other.mWeeks * 7 + other.mDays) * 24 + other.mHours) * 60 + other.mMinutes) * 60 + other.mSeconds) ) && - valid == other.valid );}; - int weeks() const { return mWeeks; }; - int days() const { return mDays; }; - int hours() const { return mHours; }; - int minutes() const { return mMinutes; }; - int seconds() const { return mSeconds; }; - - bool isNegative() const { return mNegative; }; - bool isValid() const { return valid; }; + valid == other.valid );} + int weeks() const { return mWeeks; } + int days() const { return mDays; } + int hours() const { return mHours; } + int minutes() const { return mMinutes; } + int seconds() const { return mSeconds; } + + bool isNegative() const { return mNegative; } + bool isValid() const { return valid; } private: int mWeeks; int mDays; int mHours; int mMinutes; int mSeconds; bool mNegative; bool valid; }; struct ContactReference { enum ReferenceType { Invalid, EmailReference, UidReference, EmailAndUidReference }; - ContactReference(): mType(Invalid) {}; + ContactReference(): mType(Invalid) {} ///For xCal - ContactReference(const std::string &email, const std::string &name = std::string(), const std::string &uid = std::string()): mType(EmailAndUidReference), mEmail(email), mUid(uid), mName(name) {}; + ContactReference(const std::string &email, const std::string &name = std::string(), const std::string &uid = std::string()): mType(EmailAndUidReference), mEmail(email), mUid(uid), mName(name) {} ///For xCard - ContactReference(ReferenceType type, const std::string &emailOrUID, const std::string &name = std::string()): mType(type), mName(name) { + ContactReference(ReferenceType type, const std::string &emailOrUID, const std::string &name = std::string()): mType(type), mName(name) { if (type == EmailReference) { mEmail = emailOrUID; } else { mUid = emailOrUID; } - }; + } bool operator==(const ContactReference &other) const { return mEmail == other.mEmail && mName == other.mName && mUid == other.mUid; - }; + } - bool isValid() const { return mType != Invalid; }; + bool isValid() const { return mType != Invalid; } - void setName(const std::string &name) { mName = name; }; + void setName(const std::string &name) { mName = name; } - std::string email() const { return mEmail; }; - std::string uid() const { return mUid; }; - std::string name() const { return mName; }; + std::string email() const { return mEmail; } + std::string uid() const { return mUid; } + std::string name() const { return mName; } - ReferenceType type() const { return mType; }; + ReferenceType type() const { return mType; } private: ReferenceType mType; std::string mEmail; std::string mUid; std::string mName; }; class Alarm { public: enum Type { InvalidAlarm, EMailAlarm, DisplayAlarm, AudioAlarm }; - + Alarm(); Alarm(const Alarm &); ~Alarm(); void operator=(const Alarm &); bool operator==(const Alarm &other) const; ///EMail Alarm, @param attendees accepts only email + name and no uid Alarm(const std::string &summary, const std::string &description, const std::vector attendees); std::string summary() const; std::string description() const; std::vector attendees() const; ///Display Alarm Alarm(const std::string &text); std::string text() const; ///Audio Alarm Alarm(const Attachment &audio); Attachment audioFile() const; - + void setRelativeStart(const Duration &, Relative); Duration relativeStart() const; Relative relativeTo() const; - + void setStart(const cDateTime &); cDateTime start() const; void setDuration(const Duration &, int numrepeat); Duration duration() const; int numrepeat() const; - + Type type() const; private: struct Private; boost::scoped_ptr d; }; class RecurrenceRule { public: - + RecurrenceRule(); RecurrenceRule(const RecurrenceRule &); ~RecurrenceRule(); void operator=(const RecurrenceRule &); bool operator==(const RecurrenceRule &other) const; - + enum Frequency { FreqNone, Yearly, Monthly, Weekly, Daily, Hourly, Minutely, Secondly }; - + void setFrequency(Frequency); Frequency frequency() const; - + void setWeekStart(Weekday); Weekday weekStart() const; - + void setEnd(const cDateTime &); cDateTime end() const; - + void setCount(int count); int count() const; - + void setInterval(int); int interval() const; - + void setBysecond(const std::vector &); std::vector bysecond() const; - + void setByminute(const std::vector &); std::vector byminute() const; - + void setByhour(const std::vector &); std::vector byhour() const; - + void setByday(const std::vector &); std::vector byday() const; - + void setBymonthday(const std::vector &); std::vector bymonthday() const; - + void setByyearday(const std::vector &); std::vector byyearday() const; - + void setByweekno(const std::vector &); std::vector byweekno() const; - + void setBymonth(const std::vector &); std::vector bymonth() const; - + bool isValid() const; - + private: struct Private; boost::scoped_ptr d; }; enum PartStatus { PartNeedsAction, PartAccepted, PartDeclined, PartTentative, PartDelegated, PartInProcess, PartCompleted }; enum Role { Required, Chair, Optional, NonParticipant }; enum Cutype { CutypeUnknown, CutypeGroup, CutypeIndividual, CutypeResource, CutypeRoom }; class Attendee { public: Attendee(); Attendee(const ContactReference &contact); Attendee(const Attendee &); ~Attendee(); void operator=(const Attendee &); bool operator==(const Attendee &) const; bool isValid() const; void setContact(const ContactReference &); ContactReference contact() const; void setPartStat(PartStatus); PartStatus partStat() const; void setRole(Role); Role role() const; void setRSVP(bool); bool rsvp() const; void setDelegatedTo(const std::vector &); std::vector delegatedTo() const; void setDelegatedFrom(const std::vector &); std::vector delegatedFrom() const; void setCutype(Cutype); Cutype cutype() const; private: struct Private; boost::scoped_ptr d; }; struct CustomProperty { - CustomProperty(){}; + CustomProperty(){} CustomProperty(const std::string &i, const std::string &v) - : identifier(i), value(v) {}; + : identifier(i), value(v) {} - bool operator==(const CustomProperty &other) const{ return (identifier == other.identifier && value == other.value);}; + bool operator==(const CustomProperty &other) const{ return (identifier == other.identifier && value == other.value);} std::string identifier; std::string value; }; //WARNING this function copies the vector and does not modify it template std::vector operator<< ( std::vector v, const T &s) { v.push_back(s); return v; } - } #endif diff --git a/src/containers/kolabfreebusy.h b/src/containers/kolabfreebusy.h index f4ee41f..a641f27 100644 --- a/src/containers/kolabfreebusy.h +++ b/src/containers/kolabfreebusy.h @@ -1,103 +1,103 @@ /* * Copyright (C) 2012 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef KOLABFREEBUSY_H #define KOLABFREEBUSY_H #include #include #include #include "kolabcontainers.h" namespace Kolab { struct Period { - Period(){}; - Period(const cDateTime& s, const cDateTime &e): start(s), end(e){}; - bool operator==(const Period &other) const { return start == other.start && end == other.end; }; - bool isValid() const { return start.isValid() && end.isValid(); }; + Period(){} + Period(const cDateTime& s, const cDateTime &e): start(s), end(e){} + bool operator==(const Period &other) const { return start == other.start && end == other.end; } + bool isValid() const { return start.isValid() && end.isValid(); } cDateTime start; cDateTime end; }; - + class FreebusyPeriod { public: FreebusyPeriod(); ~FreebusyPeriod(); FreebusyPeriod(const FreebusyPeriod &); void operator=(const FreebusyPeriod &); bool operator==(const FreebusyPeriod &) const; bool isValid() const; enum FBType { Invalid, Busy, Tentative, OutOfOffice }; void setType(FBType t); FBType type() const; void setEvent(const std::string &uid, const std::string &summary, const std::string &location); std::string eventUid() const; std::string eventSummary() const; std::string eventLocation() const; - + void setPeriods(const std::vector &); std::vector periods() const; private: struct Private; boost::scoped_ptr d; }; class Freebusy { public: Freebusy(); ~Freebusy(); Freebusy(const Freebusy &); void operator=(const Freebusy &); // bool operator==(const Freebusy &) const; bool isValid() const; void setUid(const std::string &); std::string uid() const; void setTimestamp(const cDateTime &); cDateTime timestamp() const; void setStart(const cDateTime &); cDateTime start() const; void setEnd(const cDateTime &); cDateTime end() const; void setOrganizer(const ContactReference &); ContactReference organizer() const; void setPeriods(const std::vector &); std::vector periods() const; private: struct Private; boost::scoped_ptr d; }; } #endif diff --git a/src/kolabconversions.h b/src/kolabconversions.h index b8331da..3afc229 100644 --- a/src/kolabconversions.h +++ b/src/kolabconversions.h @@ -1,717 +1,709 @@ /* * Copyright (C) 2012 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef KOLABOBJECTCONVERSION_H #define KOLABOBJECTCONVERSION_H #include #include #include #include #include #include #include "kolabcontainers.h" #include "global_definitions.h" #include "utils.h" #include "kolabnote.h" #include "shared_conversions.h" #include "kolabconfiguration.h" #include "kolabfile.h" #include "base64.h" namespace Kolab { namespace KolabObjects { const char* const KOLAB_NAMESPACE = "http://kolab.org"; const char* const BASE64 = "BASE64"; using namespace Kolab::Utils; using namespace Kolab::Shared; template std::vector toStringList(const xsd::cxx::tree::sequence &s) { std::vector d; std::copy(s.begin(), s.end(), std::back_inserter(d)); return d; } Kolab::Attachment toAttachment(KolabXSD::attachmentPropType aProp) { Kolab::Attachment a; const KolabXSD::attachmentPropType ::parameters_type ¶meters = aProp.parameters(); std::string mimetype = parameters.fmttype(); if (parameters.encoding() && (*parameters.encoding() != BASE64)) { ERROR("wrong encoding"); return Kolab::Attachment(); } if (parameters.x_label()) { a.setLabel(*parameters.x_label()); } if (mimetype.empty()) { ERROR("no mimetype"); } if (aProp.uri()) { a.setUri(*aProp.uri(), mimetype); } else if (aProp.binary()) { a.setData(base64_decode(*aProp.binary()), mimetype); } else { ERROR("not uri and no data available"); } return a; } KolabXSD::attachmentPropType fromAttachment(const Kolab::Attachment &a) { KolabXSD::attachmentPropType::parameters_type p(a.mimetype()); if (!a.label().empty()) { p.x_label(a.label()); } if (!a.data().empty()) { p.encoding(BASE64); } KolabXSD::attachmentPropType attachment(p); if (!a.uri().empty()) { attachment.uri(a.uri()); } else if (!a.data().empty()) { attachment.binary(base64_encode(reinterpret_cast(a.data().c_str()), static_cast(a.data().length()))); } else { ERROR("no uri and no data"); } return attachment; } void writeColors(KolabXSD::Configuration::categorycolor_sequence &colors, const std::vector &input) { BOOST_FOREACH (const CategoryColor &entry, input) { KolabXSD::Configuration::categorycolor_type c(entry.category()); c.color(entry.color()); writeColors(c.categorycolor(), entry.subcategories()); colors.push_back(c); } } std::vector readColors(const KolabXSD::Configuration::categorycolor_sequence &list) { std::vector colors ; BOOST_FOREACH (const KolabXSD::Configuration::categorycolor_type &entry, list) { if (!entry.color()) { ERROR("Color is missing"); continue; } CategoryColor color(entry.category()); color.setColor(*entry.color()); color.setSubcategories(readColors(entry.categorycolor())); colors.push_back(color); } return colors; } KolabXSD::Configuration::type_type getConfigurationType(Kolab::Configuration::ConfigurationType t) { switch (t) { case Kolab::Configuration::TypeDictionary: return KolabXSD::Configuration::type_type::dictionary; case Kolab::Configuration::TypeCategoryColor: return KolabXSD::Configuration::type_type::categorycolor; case Kolab::Configuration::TypeSnippet: return KolabXSD::Configuration::type_type::snippets; case Kolab::Configuration::TypeRelation: return KolabXSD::Configuration::type_type::relation; case Kolab::Configuration::TypeFileDriver: return KolabXSD::Configuration::type_type::file_driver; - default: + case Kolab::Configuration::Invalid: CRITICAL("Invalid configuration type"); } return KolabXSD::Configuration::type_type::dictionary; } template std::string serializeObject(const T &, const std::string prod = std::string()); template <> std::string serializeObject (const Kolab::Configuration &configuration, const std::string prod) { try { const std::string &uid = getUID(configuration.uid()); setCreatedUid(uid); KolabXSD::Configuration::creation_date_type created(0,0,0,0,0,0); if (configuration.created().isValid()) { created = fromDateTime(configuration.created()); } else { created = fromDateTime(timestamp()); } KolabXSD::Configuration::last_modification_date_type lastModificationDate(0,0,0,0,0,0); if (configuration.lastModified().isValid()) { lastModificationDate = fromDateTime(configuration.lastModified()); } else { // WARNING("missing last_modification_date, fallback to current timestamp"); lastModificationDate = fromDateTime(timestamp()); } KolabXSD::Configuration n(uid, getProductId(prod), created, lastModificationDate, getConfigurationType(configuration.type())); switch (configuration.type()) { case Kolab::Configuration::TypeDictionary: { const Kolab::Dictionary &dict = configuration.dictionary(); n.language(dict.language()); BOOST_FOREACH(const std::string &e, dict.entries()) { n.e().push_back(e); } } break; case Kolab::Configuration::TypeCategoryColor: writeColors(n.categorycolor(), configuration.categoryColor()); break; case Kolab::Configuration::TypeSnippet: { const Kolab::SnippetsCollection &snippets = configuration.snippets(); n.name(snippets.name()); BOOST_FOREACH(const Kolab::Snippet &s, snippets.snippets()) { KolabXSD::Snippet::textformat_type type = KolabXSD::Snippet::textformat_type::PLAIN; if (s.textType() == Snippet::HTML) { type = KolabXSD::Snippet::textformat_type::HTML; } KolabXSD::Configuration::snippet_type snippet(s.name(), s.text(), type); if (!s.shortCut().empty()) { snippet.shortcut(s.shortCut()); } n.snippet().push_back(snippet); } } break; case Kolab::Configuration::TypeRelation: { const Kolab::Relation &relation = configuration.relation(); n.name(relation.name()); if (!relation.type().empty()) { n.relationType(relation.type()); } if (!relation.color().empty()) { n.color(relation.color()); } if (!relation.iconName().empty()) { n.iconName(relation.iconName()); } if (!relation.parent().empty()) { n.parent(relation.parent()); } if (relation.priority() != 0) { n.priority(fromInt(relation.priority())); } BOOST_FOREACH(const std::string &s, relation.members()) { n.member().push_back(s); } } break; case Kolab::Configuration::TypeFileDriver: { const Kolab::FileDriver &fileDriver = configuration.fileDriver(); n.driver(fileDriver.driver()); n.title(fileDriver.title()); n.enabled(fileDriver.enabled()); KolabXSD::FileDriverSettings settings; settings.host(fileDriver.host()); settings.port(fileDriver.port()); settings.username(fileDriver.username()); settings.password(fileDriver.password()); n.settings(settings); } + break; + case Kolab::Configuration::Invalid: + WARNING("Invalid configuration"); break; - default: - CRITICAL("Invalid configuration type"); - return std::string(); } xml_schema::namespace_infomap map; map[""].name = KOLAB_NAMESPACE; std::ostringstream ostringstream; KolabXSD::configuration(ostringstream, n, map); return ostringstream.str(); } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to write configuration!"); return std::string(); } template <> std::string serializeObject (const Kolab::Note ¬e, const std::string prod) { try { const std::string &uid = getUID(note.uid()); setCreatedUid(uid); KolabXSD::Note::creation_date_type created(0,0,0,0,0,0); if (note.created().isValid()) { created = fromDateTime(note.created()); } else { created = fromDateTime(timestamp()); } KolabXSD::Note::last_modification_date_type lastModificationDate(0,0,0,0,0,0); if (note.lastModified().isValid()) { lastModificationDate = fromDateTime(note.lastModified()); } else { // WARNING("missing last_modification_date, fallback to current timestamp"); lastModificationDate = fromDateTime(timestamp()); } KolabXSD::Note n(uid, getProductId(prod), created, lastModificationDate); if (!note.categories().empty()) { KolabXSD::Note::categories_sequence categories; const std::vector &l = note.categories(); BOOST_FOREACH(const std::string &c, l) { categories.push_back(c); } n.categories(categories); } switch (note.classification()) { case Kolab::ClassPublic: n.classification(KolabXSD::Note::classification_type::PUBLIC); break; case Kolab::ClassPrivate: n.classification(KolabXSD::Note::classification_type::PRIVATE); break; case Kolab::ClassConfidential: n.classification(KolabXSD::Note::classification_type::CONFIDENTIAL); break; - default: - ERROR("unknown classification"); } - + if (!note.attachments().empty()) { const std::vector &l = note.attachments(); BOOST_FOREACH(const Kolab::Attachment &a, l) { n.attachment().push_back(fromAttachment(a)); } } n.summary(note.summary()); n.description(note.description()); n.color(note.color()); if (!note.customProperties().empty()) { const std::vector &l = note.customProperties(); BOOST_FOREACH(const Kolab::CustomProperty &a, l) { n.x_custom().push_back(KolabXSD::CustomType(a.identifier, a.value)); } } xml_schema::namespace_infomap map; map[""].name = KOLAB_NAMESPACE; std::ostringstream ostringstream; KolabXSD::note(ostringstream, n, map); return ostringstream.str(); } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to write note!"); return std::string(); } template <> std::string serializeObject (const Kolab::File &file, const std::string prod) { try { const std::string &uid = getUID(file.uid()); setCreatedUid(uid); KolabXSD::File::creation_date_type created(0,0,0,0,0,0); if (file.created().isValid()) { created = fromDateTime(file.created()); } else { created = fromDateTime(timestamp()); } KolabXSD::File::last_modification_date_type lastModificationDate(0,0,0,0,0,0); if (file.lastModified().isValid()) { lastModificationDate = fromDateTime(file.lastModified()); } else { // WARNING("missing last_modification_date, fallback to current timestamp"); lastModificationDate = fromDateTime(timestamp()); } if (file.file().label().empty()) { ERROR("missing filename"); } KolabXSD::File n(uid, getProductId(prod), created, lastModificationDate, fromAttachment(file.file())); if (!file.categories().empty()) { KolabXSD::File::categories_sequence categories; const std::vector &l = file.categories(); BOOST_FOREACH(const std::string &c, l) { categories.push_back(c); } n.categories(categories); } switch (file.classification()) { case Kolab::ClassPublic: n.classification(KolabXSD::File::classification_type::PUBLIC); break; case Kolab::ClassPrivate: n.classification(KolabXSD::File::classification_type::PRIVATE); break; case Kolab::ClassConfidential: n.classification(KolabXSD::File::classification_type::CONFIDENTIAL); break; - default: - ERROR("unknown classification"); } - + n.note(file.note()); if (!file.customProperties().empty()) { const std::vector &l = file.customProperties(); BOOST_FOREACH(const Kolab::CustomProperty &a, l) { n.x_custom().push_back(KolabXSD::CustomType(a.identifier, a.value)); } } xml_schema::namespace_infomap map; map[""].name = KOLAB_NAMESPACE; std::ostringstream ostringstream; KolabXSD::file(ostringstream, n, map); return ostringstream.str(); } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to write file!"); return std::string(); } template boost::shared_ptr deserializeObject(const std::string& s, bool isUrl); template <> boost::shared_ptr deserializeObject (const std::string& s, bool isUrl) { try { std::auto_ptr note; if (isUrl) { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseFile(s); if (doc.get()) { note = KolabXSD::note(doc); } } else { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseString(s); if (doc.get()) { note = KolabXSD::note(doc); } } if (!note.get()) { CRITICAL("failed to parse note!"); return boost::shared_ptr(); } boost::shared_ptr n = boost::shared_ptr(new Kolab::Note); n->setUid(note->uid()); n->setCreated(*toDate(note->creation_date())); n->setLastModified(*toDate(note->last_modification_date())); std::vector categories; std::copy(note->categories().begin(), note->categories().end(), std::back_inserter(categories)); n->setCategories(categories); if (note->classification()) { switch (*note->classification()) { case KolabXSD::Note::classification_type::PUBLIC: n->setClassification(Kolab::ClassPublic); break; case KolabXSD::Note::classification_type::PRIVATE: n->setClassification(Kolab::ClassPrivate); break; case KolabXSD::Note::classification_type::CONFIDENTIAL: n->setClassification(Kolab::ClassConfidential); break; - default: - ERROR("unknown classification"); } } if (!note->attachment().empty()) { std::vector attachments; BOOST_FOREACH(KolabXSD::Note::attachment_type &aProp, note->attachment()) { const Kolab::Attachment &a = toAttachment(aProp); if (!a.isValid()) { ERROR("invalid attachment"); continue; } attachments.push_back(a); } n->setAttachments(attachments); } if (note->summary()) { n->setSummary(*note->summary()); } if (note->description()) { n->setDescription(*note->description()); } if (note->color()) { n->setColor(*note->color()); } setProductId( note->prodid() ); // setFormatVersion( vcards->vcard().version().text() ); // global_xCardVersion = vcalendar.properties().version().text(); setKolabVersion( note->version() ); if (!note->x_custom().empty()) { std::vector customProperties; BOOST_FOREACH(const KolabXSD::CustomType &p, note->x_custom()) { customProperties.push_back(CustomProperty(p.identifier(), p.value())); } n->setCustomProperties(customProperties); } return n; } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to read note!"); return boost::shared_ptr(); } template <> boost::shared_ptr deserializeObject (const std::string& s, bool isUrl) { try { std::auto_ptr configuration; if (isUrl) { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseFile(s); if (doc.get()) { configuration = KolabXSD::configuration(doc); } } else { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseString(s); if (doc.get()) { configuration = KolabXSD::configuration(doc); } } if (!configuration.get()) { CRITICAL("failed to parse configuration!"); return boost::shared_ptr(); } boost::shared_ptr n; if (configuration->type() == KolabXSD::ConfigurationType::dictionary) { std::string lang("XX"); if (configuration->language()) { lang = *configuration->language(); } else { WARNING("missing dictionary language, default to special value XX"); } Dictionary dict(lang); std::vector entries; BOOST_FOREACH (const KolabXSD::Configuration::e_type &entry, configuration->e()) { entries.push_back(entry); } dict.setEntries(entries); n = boost::shared_ptr(new Kolab::Configuration(dict)); } else if (configuration->type() == KolabXSD::ConfigurationType::categorycolor) { n = boost::shared_ptr(new Kolab::Configuration(readColors(configuration->categorycolor()))); } else if (configuration->type() == KolabXSD::ConfigurationType::snippets) { std::string name; if (configuration->name()) { name = *configuration->name(); } SnippetsCollection collection(name); std::vector snippets; BOOST_FOREACH (const KolabXSD::Configuration::snippet_type &entry, configuration->snippet()) { Snippet snippet(entry.name(), entry.text()); if (entry.textformat() == KolabXSD::textformatType::HTML) { snippet.setTextType(Snippet::HTML); } if (entry.shortcut()) { snippet.setShortCut(*entry.shortcut()); } snippets.push_back(snippet); } collection.setSnippets(snippets); n = boost::shared_ptr(new Kolab::Configuration(collection)); } else if (configuration->type() == KolabXSD::ConfigurationType::relation) { std::string name; if (configuration->name()) { name = *configuration->name(); } std::string type; if (configuration->relationType()) { type = *configuration->relationType(); } Relation relation(name, type); if (configuration->color()) { relation.setColor(*configuration->color()); } if (configuration->iconName()) { relation.setIconName(*configuration->iconName()); } if (configuration->parent()) { relation.setParent(*configuration->parent()); } if (configuration->priority()) { relation.setPriority(convertToInt(*configuration->priority())); } relation.setMembers(toStringList(configuration->member())); n = boost::shared_ptr(new Kolab::Configuration(relation)); } else if (configuration->type() == KolabXSD::ConfigurationType::file_driver) { std::string driver; if (configuration->driver()) { driver = *configuration->driver(); } std::string title; if (configuration->title()) { title = *configuration->title(); } Kolab::FileDriver fileDriver(driver, title); fileDriver.setEnabled(*configuration->enabled()); if (configuration->settings()) { fileDriver.setHost(*configuration->settings()->host()); fileDriver.setPort(convertToInt(*configuration->settings()->port())); fileDriver.setUsername(*configuration->settings()->username()); fileDriver.setPassword(*configuration->settings()->password()); } else { CRITICAL("Settings are missing"); } n = boost::shared_ptr(new Kolab::Configuration(fileDriver)); } else { CRITICAL("No valid configuration type"); } n->setUid(configuration->uid()); n->setCreated(*toDate(configuration->creation_date())); n->setLastModified(*toDate(configuration->last_modification_date())); setProductId( configuration->prodid() ); // setFormatVersion( vcards->vcard().version().text() ); // global_xCardVersion = vcalendar.properties().version().text(); setKolabVersion( configuration->version() ); return n; } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to read configuration!"); return boost::shared_ptr(); } template <> boost::shared_ptr deserializeObject (const std::string& s, bool isUrl) { try { std::auto_ptr file; if (isUrl) { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseFile(s); if (doc.get()) { file = KolabXSD::file(doc); } } else { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseString(s); if (doc.get()) { file = KolabXSD::file(doc); } } if (!file.get()) { CRITICAL("failed to parse file!"); return boost::shared_ptr(); } boost::shared_ptr n = boost::shared_ptr(new Kolab::File); n->setUid(file->uid()); n->setCreated(*toDate(file->creation_date())); n->setLastModified(*toDate(file->last_modification_date())); std::vector categories; std::copy(file->categories().begin(), file->categories().end(), std::back_inserter(categories)); n->setCategories(categories); if (file->classification()) { switch (*file->classification()) { case KolabXSD::File::classification_type::PUBLIC: n->setClassification(Kolab::ClassPublic); break; case KolabXSD::File::classification_type::PRIVATE: n->setClassification(Kolab::ClassPrivate); break; case KolabXSD::File::classification_type::CONFIDENTIAL: n->setClassification(Kolab::ClassConfidential); break; - default: - ERROR("unknown classification"); } } const Kolab::Attachment &attachment = toAttachment(file->file()); if (attachment.label().empty()) { ERROR("Missing filename"); } if (!attachment.isValid()) { ERROR("invalid attachment"); } n->setFile(attachment); if (file->note()) { n->setNote(*file->note()); } setProductId( file->prodid() ); // setFormatVersion( vcards->vcard().version().text() ); // global_xCardVersion = vcalendar.properties().version().text(); setKolabVersion( file->version() ); if (!file->x_custom().empty()) { std::vector customProperties; BOOST_FOREACH(const KolabXSD::CustomType &p, file->x_custom()) { customProperties.push_back(CustomProperty(p.identifier(), p.value())); } n->setCustomProperties(customProperties); } return n; } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to read file!"); return boost::shared_ptr(); } }//Namespace } //Namespace #endif diff --git a/src/xcalconversions.h b/src/xcalconversions.h index 5303d3d..2d24549 100644 --- a/src/xcalconversions.h +++ b/src/xcalconversions.h @@ -1,2036 +1,2022 @@ /* * Copyright (C) 2011 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef XCALCONVERSIONS_H #define XCALCONVERSIONS_H #include "global_definitions.h" #include "libkolabxml-version.h" #include #include #include #include #include #include #include #include #include #include #include "kolabcontainers.h" #include "kolabtodo.h" #include "kolabevent.h" #include "kolabjournal.h" #include #include "utils.h" #include "base64.h" #include "shared_conversions.h" namespace Kolab { namespace XCAL { const char* const XCAL_VERSION = "2.0"; const char* const XCAL_NAMESPACE = "urn:ietf:params:xml:ns:icalendar-2.0"; const char* const TZ_PREFIX = "/kolab.org/"; const char* const THISANDFUTURE = "THISANDFUTURE"; const char* const BASE64 = "BASE64"; const char* const NEEDSACTION = "NEEDS-ACTION"; const char* const COMPLETED = "COMPLETED"; const char* const COMPLETED_COMPAT = "OPAQUE"; const char* const INPROCESS = "IN-PROCESS"; const char* const CANCELLED = "CANCELLED"; const char* const TENTATIVE = "TENTATIVE"; const char* const CONFIRMED = "CONFIRMED"; const char* const DRAFT = "DRAFT"; const char* const FINAL = "FINAL"; const char* const CONFIDENTIAL = "CONFIDENTIAL"; const char* const PRIVATE = "PRIVATE"; const char* const PUBLIC = "PUBLIC"; const char* const PARTACCEPTED = "ACCEPTED"; const char* const PARTDECLINED = "DECLINED"; const char* const PARTDELEGATED = "DELEGATED"; const char* const PARTNEEDSACTION = "NEEDS-ACTION"; const char* const PARTTENTATIVE = "TENTATIVE"; const char* const PARTINPROCESS = "IN-PROCESS"; const char* const PARTCOMPLETED = "COMPLETED"; const char* const CHAIR = "CHAIR"; const char* const NONPARTICIPANT = "NON-PARTICIPANT"; const char* const OPTIONAL = "OPT-PARTICIPANT"; const char* const REQUIRED = "REQ-PARTICIPANT"; const char* const DISPLAYALARM = "DISPLAY"; const char* const EMAILALARM = "EMAIL"; const char* const AUDIOALARM = "AUDIO"; const char* const TRANSPARENT = "TRANSPARENT"; const char* const OPAQUE = "OPAQUE"; const char* const MO = "MO"; const char* const TU = "TU"; const char* const WE = "WE"; const char* const TH = "TH"; const char* const FR = "FR"; const char* const SA = "SA"; const char* const SU = "SU"; const char* const GROUP = "GROUP"; const char* const INDIVIDUAL = "INDIVIDUAL"; const char* const RESOURCE = "RESOURCE"; const char* const UNKNOWN = "UNKNOWN"; const char* const ROOM = "ROOM"; //Alarms const char* const START = "START"; const char* const END = "END"; //Freebusy const char* const BUSY = "BUSY"; const char* const BUSY_TENTATIVE = "BUSY-TENTATIVE"; const char* const BUSY_OUTOFOFFICE = "X-OUT-OF-OFFICE"; using namespace Kolab::Utils; using namespace Kolab::Shared; //=== Generic Conversions === int toInt(const icalendar_2_0::IntegerPropertyType &prop) { return convertToInt(prop.integer()); } std::vector toStringList(const icalendar_2_0::TextListPropertyType &s) { std::vector d; std::copy(s.text().begin(), s.text().end(), std::back_inserter(d)); return d; } template std::auto_ptr fromStringList(const std::vector &list) { std::auto_ptr ptr(new T()); std::copy(list.begin(), list.end(), std::back_inserter(ptr->text())); return ptr; } //TODO doesn't seem very useful after all, remove std::string toString(const icalendar_2_0::TextPropertyType &s) { return s.text(); } std::string fromDayPos(const Kolab::DayPos &d) { std::string s; if (d.occurence() != 0) { s.append(boost::lexical_cast(d.occurence())); } switch (d.weekday()) { case Kolab::Monday: s.append(MO); break; case Kolab::Tuesday: s.append(TU); break; case Kolab::Wednesday: s.append(WE); break; case Kolab::Thursday: s.append(TH); break; case Kolab::Friday: s.append(FR); break; case Kolab::Saturday: s.append(SA); break; case Kolab::Sunday: s.append(SU); break; } return s; } Kolab::DayPos toDayPos(const std::string &s) { std::string number; bool gotOccurrence = false; int occurrence = 0; for (std::string::const_iterator it = s.begin(); it != s.end(); it++) { switch(*it) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '+': case '-': number.push_back(*it); break; default: if (!gotOccurrence && !number.empty()) { try { occurrence = boost::lexical_cast(number); } catch(boost::bad_lexical_cast &) { ERROR("failed to convert: " + number); return DayPos(); } number.clear(); } gotOccurrence = true; number.push_back(*it); break; } } if (number == MO) { return DayPos(occurrence, Kolab::Monday); } else if (number == TU) { return DayPos(occurrence, Kolab::Tuesday); } else if (number == WE) { return DayPos(occurrence, Kolab::Wednesday); } else if (number == TH) { return DayPos(occurrence, Kolab::Thursday); } else if (number == FR) { return DayPos(occurrence, Kolab::Friday); } else if (number == SA) { return DayPos(occurrence, Kolab::Saturday); } else if (number == SU) { return DayPos(occurrence, Kolab::Sunday); } return DayPos(); } std::string fromDuration(const Kolab::Duration &d) { std::string s; if (!d.isValid()) { return s; } if (d.isNegative()) { s.push_back('-'); } s.push_back('P'); try { if (d.weeks() > 0) { s.append(boost::lexical_cast(d.weeks())); s.push_back('W'); } if (d.days() > 0) { s.append(boost::lexical_cast(d.days())); s.push_back('D'); } if (d.hours() > 0 || d.minutes() > 0 || d.seconds() > 0) { s.push_back('T'); if (d.hours() > 0) { s.append(boost::lexical_cast(d.hours())); s.push_back('H'); } if (d.minutes() > 0) { s.append(boost::lexical_cast(d.minutes())); s.push_back('M'); } if (d.seconds() > 0) { s.append(boost::lexical_cast(d.seconds())); s.push_back('S'); } } } catch(boost::bad_lexical_cast &) { ERROR("failed to convert duration"); return std::string(); } return s; } Kolab::Duration toDuration(const icalendar_2_0::DurationValueType &d) { int weeks = 0; int days = 0; int hours = 0; int minutes = 0; int seconds = 0; bool negative = false; std::string number; for (std::string::const_iterator it = d.begin(); it != d.end(); it++) { switch(*it) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': number.push_back(*it); break; case 'H': try { hours = boost::lexical_cast(number); } catch(boost::bad_lexical_cast &) { ERROR("failed to convert: " + number); return Duration(); } number.clear(); break; case 'M': try { minutes = boost::lexical_cast(number); } catch(boost::bad_lexical_cast &) { ERROR("failed to convert: " + number); return Duration(); } number.clear(); break; case 'S': try { seconds = boost::lexical_cast(number); } catch(boost::bad_lexical_cast &) { ERROR("failed to convert: " + number); return Duration(); } number.clear(); break; case 'T': break; case 'W': try { weeks = boost::lexical_cast(number); } catch(boost::bad_lexical_cast &) { ERROR("failed to convert: " + number); return Duration(); } return Duration(weeks, negative); case 'D': try { days = boost::lexical_cast(number); } catch(boost::bad_lexical_cast &) { ERROR("failed to convert: " + number); return Duration(); } number.clear(); break; case '+': break; case '-': negative = true; break; case 'P': break; default: { std::ostringstream s; s << "failed to convert duration: " << *it; ERROR(s.str()); return Duration(); } } } return Duration(days, hours, minutes, seconds, negative); } template T fromContactReference(const Kolab::ContactReference &c) { T organizer(toMailto(c.email())); typename T::parameters_type p; if (!c.name().empty()) { icalendar_2_0::CnParamType name(c.name()); p.baseParameter().push_back(name); } if (!c.uid().empty()) { icalendar_2_0::DirParamType dir(toURN(c.uid())); p.baseParameter().push_back(dir); } organizer.parameters(p); return organizer; } Kolab::ContactReference toContactReference(const icalendar_2_0::CalAddressPropertyType &cal) { const std::string &email = fromMailto(cal.cal_address());; std::string name; std::string uid; if (cal.parameters()) { for (icalendar_2_0::ArrayOfParameters::baseParameter_const_iterator it((*cal.parameters()).baseParameter().begin()); it != (*cal.parameters()).baseParameter().end(); it++) { if (const icalendar_2_0::CnParamType * tz = dynamic_cast (&*it)) { name = tz->text(); continue; } if (const icalendar_2_0::DirParamType * tz = dynamic_cast (&*it)) { uid = fromURN(tz->uri()); continue; } } } return Kolab::ContactReference(email, name, uid); } template Kolab::Attachment toAttachment(T aProp) { Kolab::Attachment a; std::string mimetype; if (aProp.parameters()) { const icalendar_2_0::AttachPropType ::parameters_type ¶meters = *aProp.parameters(); for (icalendar_2_0::AttachPropType::parameters_type::baseParameter_const_iterator it(parameters.baseParameter().begin()); it != parameters.baseParameter().end(); it++) { if (const icalendar_2_0::FmttypeParamType *p = dynamic_cast (&*it)) { mimetype = p->text(); } if (const icalendar_2_0::EncodingParamType *p = dynamic_cast (&*it)) { if (p->text() != BASE64) { ERROR("wrong encoding"); return Kolab::Attachment(); } } if (const icalendar_2_0::XlabelParamType *p = dynamic_cast (&*it)) { a.setLabel(p->text()); } } } if (aProp.uri()) { a.setUri(*aProp.uri(), mimetype); } else if (aProp.binary()) { a.setData(base64_decode(*aProp.binary()), mimetype); } else { ERROR("no uri and no data available"); } return a; } icalendar_2_0::AttachPropType fromAttachment(const Kolab::Attachment &a) { icalendar_2_0::AttachPropType attachment; icalendar_2_0::AttachPropType::parameters_type p; p.baseParameter().push_back(icalendar_2_0::FmttypeParamType(a.mimetype())); if (!a.label().empty()) { p.baseParameter().push_back(icalendar_2_0::XlabelParamType(a.label())); } if (!a.uri().empty()) { attachment.uri(a.uri()); } else if (!a.data().empty()) { attachment.binary(base64_encode(reinterpret_cast(a.data().c_str()), static_cast(a.data().length()))); p.baseParameter().push_back(icalendar_2_0::EncodingParamType(BASE64)); } else { ERROR("no uri and no data"); } attachment.parameters(p); return attachment; } //==== cDateTime ==== std::string getTimezone(const icalendar_2_0::ArrayOfParameters ¶meters) { for (icalendar_2_0::DateDatetimePropertyType::parameters_type::baseParameter_const_iterator it(parameters.baseParameter().begin()); it != parameters.baseParameter().end(); it++) { if (const icalendar_2_0::TzidParamType* tz = dynamic_cast (&*it)) { std::string tzid = tz->text(); if (tzid.find(TZ_PREFIX) != std::string::npos) { tzid.erase(0, strlen(TZ_PREFIX)); } else { WARNING("/kolab.org/ timezone prefix is missing"); } return tzid; } } return std::string(); } cDateTimePtr toDate(const icalendar_2_0::DateDatetimePropertyType &dtProperty) { cDateTimePtr date; if (dtProperty.date_time()) { date = Shared::toDate(*dtProperty.date_time()); } else if (dtProperty.date()) { date = Shared::toDate(*dtProperty.date()); } if (dtProperty.parameters()) { const std::string &tzid = getTimezone(*dtProperty.parameters()); if (tzid.size()) { date->setTimezone(tzid); } } return date; } cDateTimePtr toDate(const icalendar_2_0::UtcDatetimePropertyType &dtProperty) { cDateTimePtr date; if (dtProperty.date_time()) { date = Shared::toDate(*dtProperty.date_time()); } else { //The utc-date-time element shouldn't even exist date = cDateTimePtr(new cDateTime()); ERROR("This element shouldn't even be existing"); //TODO Implement anyways? return date; } date->setUTC(true); return date; } template std::auto_ptr fromDate(const cDateTime &dt) { std::auto_ptr ptr(new I); if (dt.isDateOnly()) { ptr->date(Shared::fromDate(dt)); } else { ptr->date_time(Shared::fromDateTime(dt)); const std::string &timezone = dt.timezone(); if (timezone.size() != 0) { std::string tz(TZ_PREFIX); tz.append(timezone); icalendar_2_0::TzidParamType tzidParam(tz); icalendar_2_0::ArrayOfParameters parameters; parameters.baseParameter().push_back(tzidParam); ptr->parameters(parameters); } } return ptr; } template std::vector toDateTimeList(I datelistProperty) { std::vector list; std::string tzid; if (datelistProperty.parameters()) { tzid = getTimezone(*datelistProperty.parameters()); } if (!datelistProperty.date().empty()) { BOOST_FOREACH(const xml_schema::date &d, datelistProperty.date()) { list.push_back(*Shared::toDate(d)); } } else if (!datelistProperty.date_time().empty()) { BOOST_FOREACH(const xml_schema::date_time &d, datelistProperty.date_time()) { cDateTimePtr date = Shared::toDate(d); if (tzid.size()) { date->setTimezone(tzid); } list.push_back(*date); } } return list; } template std::auto_ptr fromDateTimeList(const std::vector &dtlist) { std::auto_ptr ptr(new I); BOOST_FOREACH(const cDateTime &dt, dtlist) { if (dt.isDateOnly()) { ptr->date().push_back(Shared::fromDate(dt)); } else { ptr->date_time().push_back(Shared::fromDateTime(dt)); } //TODO handle utc } if (!dtlist.empty() && !dtlist.at(0).timezone().empty()) { const std::string &timezone = dtlist.at(0).timezone(); if (timezone.size() != 0) { std::string tz(TZ_PREFIX); tz.append(timezone); icalendar_2_0::TzidParamType tzidParam(tz); icalendar_2_0::ArrayOfParameters parameters; parameters.baseParameter().push_back(tzidParam); ptr->parameters(parameters); } } return ptr; } //---- cDateTime ---- //=== Attendee === std::string mapPartStat(PartStatus status) { switch (status) { case PartAccepted: return PARTACCEPTED; case PartDeclined: return PARTDECLINED; case PartDelegated: return PARTDELEGATED; case PartNeedsAction: return PARTNEEDSACTION; case PartTentative: return PARTTENTATIVE; case PartInProcess: return PARTINPROCESS; case PartCompleted: return PARTCOMPLETED; } std::ostringstream s; s << "PartStat not handled: " << status; ERROR(s.str()); return std::string(); } PartStatus mapPartStat(const std::string &status) { if (status == PARTACCEPTED) { return PartAccepted; } else if (status == PARTDECLINED) { return PartDeclined; } else if (status == PARTDELEGATED) { return PartDelegated; } else if (status == PARTNEEDSACTION) { return PartNeedsAction; } else if (status == PARTTENTATIVE) { return PartTentative; } else if (status == PARTINPROCESS) { return PartInProcess; } else if (status == PARTCOMPLETED) { return PartCompleted; } ERROR("PartStat not handled: " + status); return PartNeedsAction; } std::string mapRole(Role status) { switch (status) { case Chair: return std::string(CHAIR); case NonParticipant: return NONPARTICIPANT; case Optional: return OPTIONAL; case Required: return REQUIRED; } std::ostringstream s; s << "Role not handled: " << status; ERROR(s.str()); return std::string(); } Role mapRole(const std::string &status) { if (status == CHAIR) { return Chair; } else if (status == NONPARTICIPANT) { return NonParticipant; } else if (status == OPTIONAL) { return Optional; } else if (status == REQUIRED) { return Required; } ERROR("Unhandled status " + status); return Required; } //---------------- //=== Recurrence Rule === typedef std::auto_ptr RecurrencePtr; RecurrenceRule::Frequency mapRecurrenceFrequency(const icalendar_2_0::RecurType::freq_type &freq) { using namespace icalendar_2_0; switch (freq) { case FreqRecurType::YEARLY: return RecurrenceRule::Yearly; case FreqRecurType::MONTHLY: return RecurrenceRule::Monthly; case FreqRecurType::WEEKLY: return RecurrenceRule::Weekly; case FreqRecurType::DAILY: return RecurrenceRule::Daily; case FreqRecurType::HOURLY: return RecurrenceRule::Hourly; case FreqRecurType::MINUTELY: return RecurrenceRule::Minutely; case FreqRecurType::SECONDLY: return RecurrenceRule::Secondly; - default: - ERROR("invalid unhandled recurrenc type" + freq); } return RecurrenceRule::FreqNone; } icalendar_2_0::RecurType::freq_type mapRecurrenceFrequency(RecurrenceRule::Frequency freq) { using namespace icalendar_2_0; switch (freq) { case RecurrenceRule::Yearly: return FreqRecurType::YEARLY; case RecurrenceRule::Monthly: return FreqRecurType::MONTHLY; case RecurrenceRule::Weekly: return FreqRecurType::WEEKLY; case RecurrenceRule::Daily: return FreqRecurType::DAILY; case RecurrenceRule::Hourly: return FreqRecurType::HOURLY; case RecurrenceRule::Minutely: return FreqRecurType::MINUTELY; case RecurrenceRule::Secondly: return FreqRecurType::SECONDLY; - default: - ERROR("invalid unhandled recurrenc type"); + case RecurrenceRule::FreqNone: + return 0; } return 0; } static void setWeekStart(RecurrencePtr &r, const icalendar_2_0::RecurType::wkst_type &wkst) { using namespace icalendar_2_0; switch (wkst) { case WeekdayRecurType::MO: r->setWeekStart(Kolab::Monday); break; case WeekdayRecurType::TU: r->setWeekStart(Kolab::Tuesday); break; case WeekdayRecurType::WE: r->setWeekStart(Kolab::Wednesday); break; case WeekdayRecurType::TH: r->setWeekStart(Kolab::Thursday); break; case WeekdayRecurType::FR: r->setWeekStart(Kolab::Friday); break; case WeekdayRecurType::SA: r->setWeekStart(Kolab::Saturday); break; case WeekdayRecurType::SU: r->setWeekStart(Kolab::Sunday); break; - default: - ERROR("invalid unhandled weekday" + wkst); } } static void setByday(RecurrencePtr &r, const icalendar_2_0::RecurType::byday_sequence &list) { std::vector by; for (icalendar_2_0::RecurType::byday_const_iterator it(list.begin()); it != list.end(); it++) { by.push_back(toDayPos(*it)); } r->setByday(by); } template std::vector bylist(const xsd::cxx::tree::sequence &list) { std::vector by; BOOST_FOREACH(const T i, list) { by.push_back(convertToInt(i)); } return by; } RecurrencePtr toRRule(const icalendar_2_0::RecurType &rrule) { using namespace icalendar_2_0; RecurrencePtr r(new RecurrenceRule()); r->setFrequency(mapRecurrenceFrequency(rrule.freq())); if (rrule.until()) { cDateTimePtr date; if ((*rrule.until()).date_time()) { date = Shared::toDate(*(*rrule.until()).date_time()); } else if ((*rrule.until()).date()) { date = Shared::toDate(*(*rrule.until()).date()); } r->setEnd(*date); } else if (rrule.count()) { r->setCount(toInt(*rrule.count())); } if (rrule.interval()) { r->setInterval(toInt(*rrule.interval())); } else { r->setInterval(1); } r->setBysecond(bylist(rrule.bysecond())); r->setByminute(bylist(rrule.byminute())); r->setByhour(bylist(rrule.byhour())); setByday(r, rrule.byday()); r->setBymonthday(bylist(rrule.bymonthday())); r->setByyearday(bylist(rrule.byyearday())); r->setByweekno(bylist(rrule.byweekno())); r->setBymonth(bylist(rrule.bymonth())); if (rrule.wkst()) { setWeekStart(r, *rrule.wkst()); } return r; } //--- Recurrence Rule --- template void setIncidenceProperties(I &inc, const T &prop) { inc.setUid(toString(prop.uid())); inc.setCreated(*toDate(prop.created())); inc.setLastModified(*toDate(prop.dtstamp())); if (prop.sequence()) { inc.setSequence(toInt(*prop.sequence())); } if (prop.class_()) { std::string string(toString(*prop.class_())); Kolab::Classification sec = ClassPublic; if (string == PRIVATE) { sec = ClassPrivate; } else if (string == CONFIDENTIAL) { sec = ClassConfidential; } inc.setClassification(sec); } if (prop.categories()) { inc.setCategories(toStringList(*prop.categories())); } if (prop.dtstart()) { const cDateTimePtr date = toDate(*prop.dtstart()); inc.setStart(*date); } if (prop.summary()) { inc.setSummary(toString(*prop.summary())); } if (prop.description()) { inc.setDescription(toString(*prop.description())); } if (prop.comment()) { inc.setComment(toString(*prop.comment())); } if (prop.status()) { const std::string &status = toString(*prop.status()); if (status == NEEDSACTION) { inc.setStatus(StatusNeedsAction); } else if (status == COMPLETED || status == COMPLETED_COMPAT) { inc.setStatus(StatusCompleted); } else if (status == INPROCESS) { inc.setStatus(StatusInProcess); } else if (status == CANCELLED) { inc.setStatus(StatusCancelled); } else if (status == TENTATIVE) { inc.setStatus(StatusTentative); } else if (status == CONFIRMED) { inc.setStatus(StatusConfirmed); } else if (status == DRAFT) { inc.setStatus(StatusDraft); } else if (status == FINAL) { inc.setStatus(StatusFinal); } else { ERROR("Unhandled status"); } } if (prop.attendee().size()) { std::vector attendees; BOOST_FOREACH(typename T::attendee_type aProp, prop.attendee()) { Kolab::Attendee a; std::string name; if (aProp.parameters()) { const icalendar_2_0::AttendeePropType::parameters_type ¶meters = *aProp.parameters(); for (icalendar_2_0::AttendeePropType::parameters_type::baseParameter_const_iterator it(parameters.baseParameter().begin()); it != parameters.baseParameter().end(); it++) { if (const icalendar_2_0::CnParamType * p = dynamic_cast (&*it)) { name = p->text(); } if (const icalendar_2_0::PartstatParamType * p = dynamic_cast (&*it)) { PartStatus s = mapPartStat(p->text()); if (s != PartNeedsAction) { a.setPartStat(s); } } if (const icalendar_2_0::RoleParamType * p = dynamic_cast (&*it)) { Role s = mapRole(p->text()); if (s != Required) { a.setRole(s); } } if (const icalendar_2_0::RsvpParamType * p = dynamic_cast (&*it)) { a.setRSVP(p->boolean()); } if (const icalendar_2_0::DelegatedToParamType * p = dynamic_cast (&*it)) { std::vector list; BOOST_FOREACH(const icalendar_2_0::CalAddressListParamType::cal_address_type &adr, p->cal_address()) { list.push_back(Shared::toContactReference(adr)); } a.setDelegatedTo(list); } if (const icalendar_2_0::DelegatedFromParamType * p = dynamic_cast (&*it)) { std::vector list; BOOST_FOREACH(const icalendar_2_0::CalAddressListParamType::cal_address_type &adr, p->cal_address()) { list.push_back(Shared::toContactReference(adr)); } a.setDelegatedFrom(list); } if (const icalendar_2_0::CutypeParamType * p = dynamic_cast (&*it)) { if (p->text() == RESOURCE) { a.setCutype(CutypeResource); } else if (p->text() == INDIVIDUAL) { a.setCutype(CutypeIndividual); } else if (p->text() == GROUP) { a.setCutype(CutypeGroup); } else if (p->text() == ROOM) { a.setCutype(CutypeGroup); } else if (p->text() == UNKNOWN) { a.setCutype(CutypeGroup); } else { WARNING("Invalid attendee cutype"); } } } } Kolab::ContactReference ref = toContactReference(aProp); a.setContact(ref); attendees.push_back(a); } inc.setAttendees(attendees); } if (prop.attach().size()) { std::vector attachments; BOOST_FOREACH(typename T::attach_type aProp, prop.attach()) { const Kolab::Attachment &a = toAttachment(aProp); if (!a.isValid()) { ERROR("invalid attachment"); continue; } attachments.push_back(a); } inc.setAttachments(attachments); } if (prop.x_custom().size()) { std::vector customProperties; BOOST_FOREACH(typename T::x_custom_type p, prop.x_custom()) { customProperties.push_back(CustomProperty(p.identifier(), p.value())); } inc.setCustomProperties(customProperties); } } template void setTodoEventProperties(I &inc, const T &prop) { if (prop.rrule()) { RecurrencePtr rrule = toRRule(prop.rrule()->recur()); inc.setRecurrenceRule(*rrule); } if (prop.rdate()) { inc.setRecurrenceDates(toDateTimeList(*prop.rdate())); if (!prop.rdate()->period().empty()) { ERROR("the period element must not be used, ignored."); } } if (prop.exdate()) { inc.setExceptionDates(toDateTimeList(*prop.exdate())); } if (prop.recurrence_id()) { bool thisandfuture = false; if (prop.recurrence_id()->parameters()) { const icalendar_2_0::RecurrenceIdPropType::parameters_type ¶meters = *prop.recurrence_id()->parameters(); for (icalendar_2_0::RecurrenceIdPropType::parameters_type::baseParameter_const_iterator it(parameters.baseParameter().begin()); it != parameters.baseParameter().end(); it++) { if (dynamic_cast (&*it)) { thisandfuture = true; } } } inc.setRecurrenceID(*toDate(*prop.recurrence_id()), thisandfuture); } if (prop.priority()) { inc.setPriority(toInt(*prop.priority())); } if (prop.location()) { inc.setLocation(toString(*prop.location())); } if (prop.organizer()) { inc.setOrganizer(toContactReference(*prop.organizer())); } if (prop.url()) { inc.setUrl((*prop.url()).uri()); } } template T fromList(const std::vector &input) { T list; BOOST_FOREACH(int i, input) { list.push_back(convertToInt(i)); } return list; } std::auto_ptr< icalendar_2_0::RrulePropType > recurrenceProperty(const RecurrenceRule &r) { using namespace icalendar_2_0; std::auto_ptr< RrulePropType > rruleProp(new RrulePropType(mapRecurrenceFrequency(r.frequency()))); RecurPropertyType::recur_type &recur = rruleProp->recur(); const cDateTime &endDate = r.end(); if (endDate.isValid()) { RecurPropertyType::recur_type::until_type until; if (endDate.isDateOnly()) { until.date(Shared::fromDate(endDate)); } else { until.date_time(Shared::fromDateTime(endDate)); } recur.until(until); } else if (r.count() > 0) { recur.count(fromInt(r.count())); } if (r.interval() > 1) { recur.interval(fromInt(r.interval())); } if (!r.bysecond().empty()) { recur.bysecond(fromList(r.bysecond())); } if (!r.byminute().empty()) { recur.byminute(fromList(r.byminute())); } if (!r.byhour().empty()) { recur.byhour(fromList(r.byhour())); } if (!r.byday().empty()) { RecurType::byday_sequence byday; const std::vector &l = r.byday(); BOOST_FOREACH(Kolab::DayPos daypos, l) { byday.push_back(fromDayPos(daypos)); } recur.byday(byday); } if (!r.bymonthday().empty()) { recur.bymonthday(fromList(r.bymonthday())); } if (!r.byyearday().empty()) { recur.byyearday(fromList(r.byyearday())); } if (!r.byweekno().empty()) { recur.byweekno(fromList(r.byweekno())); } if (!r.bymonth().empty()) { recur.bymonth(fromList(r.bymonth())); } return rruleProp; } template void getIncidenceProperties(T &prop, const I &inc) { using namespace icalendar_2_0; typedef T properties; prop.sequence(fromInt(inc.sequence())); switch (inc.classification()) { case Kolab::ClassConfidential: prop.class_(typename properties::class_type(CONFIDENTIAL)); break; case Kolab::ClassPrivate: prop.class_(typename properties::class_type(PRIVATE)); break; - default: + case Kolab::ClassPublic: prop.class_(typename properties::class_type(PUBLIC)); break; } - + if (!inc.categories().empty()) { prop.categories(*fromStringList(inc.categories())); } if (inc.start().isValid()) { prop.dtstart(fromDate(inc.start())); } if (!inc.summary().empty()) { prop.summary(typename properties::summary_type(inc.summary())); } if (!inc.description().empty()) { prop.description(typename properties::description_type(inc.description())); } if (!inc.comment().empty()) { prop.comment(typename properties::comment_type(inc.comment())); } - if (inc.status() != StatusUndefined) { - switch (inc.status()) { - case StatusNeedsAction: - prop.status(typename properties::status_type(NEEDSACTION)); - break; - case StatusCompleted: - prop.status(typename properties::status_type(COMPLETED)); - break; - case StatusInProcess: - prop.status(typename properties::status_type(INPROCESS)); - break; - case StatusCancelled: - prop.status(typename properties::status_type(CANCELLED)); - break; - case StatusTentative: - prop.status(typename properties::status_type(TENTATIVE)); - break; - case StatusConfirmed: - prop.status(typename properties::status_type(CONFIRMED)); - break; - case StatusDraft: - prop.status(typename properties::status_type(DRAFT)); - break; - case StatusFinal: - prop.status(typename properties::status_type(FINAL)); - break; - default: { - std::ostringstream s; - s << "unhandled status " << inc.status(); - ERROR(s.str()); - } - } - + switch (inc.status()) { + case StatusNeedsAction: + prop.status(typename properties::status_type(NEEDSACTION)); + break; + case StatusCompleted: + prop.status(typename properties::status_type(COMPLETED)); + break; + case StatusInProcess: + prop.status(typename properties::status_type(INPROCESS)); + break; + case StatusCancelled: + prop.status(typename properties::status_type(CANCELLED)); + break; + case StatusTentative: + prop.status(typename properties::status_type(TENTATIVE)); + break; + case StatusConfirmed: + prop.status(typename properties::status_type(CONFIRMED)); + break; + case StatusDraft: + prop.status(typename properties::status_type(DRAFT)); + break; + case StatusFinal: + prop.status(typename properties::status_type(FINAL)); + break; + case StatusUndefined: + break; } if (!inc.attendees().empty()) { const std::vector &l = inc.attendees(); BOOST_FOREACH(const Kolab::Attendee &a, l) { const Kolab::ContactReference &c = a.contact(); typename properties::attendee_type attendee = fromContactReference(c); typename properties::attendee_type::parameters_type &p = *attendee.parameters(); std::string stat = mapPartStat(a.partStat()); if (!stat.empty()) { p.baseParameter().push_back(icalendar_2_0::PartstatParamType(stat)); } std::string r = mapRole(a.role()); if (!r.empty()) { p.baseParameter().push_back(icalendar_2_0::RoleParamType(r)); } if (a.rsvp()) { p.baseParameter().push_back(icalendar_2_0::RsvpParamType(true)); } if (!a.delegatedTo().empty()) { icalendar_2_0::DelegatedToParamType delegatedTo; BOOST_FOREACH(const Kolab::ContactReference &ref, a.delegatedTo()) { delegatedTo.cal_address().push_back(CalAddressListParamType::cal_address_type(toMailto(ref.email(), ref.name()))); } p.baseParameter().push_back(delegatedTo); } if (!a.delegatedFrom().empty()) { icalendar_2_0::DelegatedFromParamType delegatedFrom; BOOST_FOREACH(const Kolab::ContactReference &ref, a.delegatedFrom()) { delegatedFrom.cal_address().push_back(CalAddressListParamType::cal_address_type(toMailto(ref.email(), ref.name()))); } p.baseParameter().push_back(delegatedFrom); } if (a.cutype() != CutypeIndividual) { std::string type; switch (a.cutype()) { case CutypeGroup: type = GROUP; break; case CutypeResource: type = RESOURCE; break; case CutypeRoom: type = ROOM; break; case CutypeUnknown: type = UNKNOWN; break; - default: - WARNING("unknown cutype"); - type = INDIVIDUAL; + case CutypeIndividual: // silence compiler warning break; } p.baseParameter().push_back(icalendar_2_0::CutypeParamType(type)); } prop.attendee().push_back(attendee); } } if (!inc.attachments().empty()) { const std::vector &l = inc.attachments(); BOOST_FOREACH(const Kolab::Attachment &a, l) { prop.attach().push_back(fromAttachment(a)); } } if (!inc.customProperties().empty()) { const std::vector &l = inc.customProperties(); BOOST_FOREACH(const Kolab::CustomProperty &a, l) { prop.x_custom().push_back(typename properties::x_custom_type(a.identifier, a.value)); } } } template void getTodoEventProperties(T &prop, const I &inc) { using namespace icalendar_2_0; typedef T properties; if (inc.recurrenceRule().isValid()) { const RecurrenceRule &r = inc.recurrenceRule(); prop.rrule(recurrenceProperty(r)); //TODO check if startdate is allDay if recurrence is allDay //TODO check if startdate matches the one of the event (it MUST) } if (!inc.recurrenceDates().empty()) { prop.rdate(fromDateTimeList(inc.recurrenceDates())); } if (!inc.exceptionDates().empty()) { prop.exdate(fromDateTimeList(inc.exceptionDates())); } if (inc.recurrenceID().isValid()) { std::auto_ptr recurrenceId = fromDate(inc.recurrenceID()); if (inc.thisAndFuture()) { if (!recurrenceId->parameters()) { recurrenceId->parameters(typename properties::recurrence_id_type::parameters_type()); } typename properties::recurrence_id_type::parameters_type ¶meters = *recurrenceId->parameters(); //There is maybe already a timezone set icalendar_2_0::RangeParamType range(THISANDFUTURE); parameters.baseParameter().push_back(range); } prop.recurrence_id(recurrenceId); } if (inc.priority() != 0) { prop.priority(typename properties::priority_type(fromInt(inc.priority()))); } if (!inc.location().empty()) { prop.location(typename properties::location_type(inc.location())); } if (inc.organizer().isValid()) { prop.organizer(fromContactReference(inc.organizer())); } if (!inc.url().empty()) { prop.url(typename properties::url_type(inc.url())); } } //=== Alarms === template void setAlarms(typename KolabType::components_type& components, const IncidenceType &incidence) { const std::vector &alarms = incidence.alarms(); BOOST_FOREACH(const Kolab::Alarm &alarm, alarms) { typedef icalendar_2_0::ValarmType::properties_type PropType; PropType::trigger_type trigger; if (alarm.start().isValid()) { if (!alarm.start().isUTC()) { ERROR("alarm start date is not UTC but MUST be UTC"); continue; } trigger.date_time(fromDateTime(alarm.start())); } else { if (!alarm.relativeStart().isValid()) { ERROR("no start and no relativeStart"); continue; } trigger.duration(PropType::trigger_type::duration_type(fromDuration(alarm.relativeStart()))); icalendar_2_0::ArrayOfParameters parameters; if (alarm.relativeTo() == Kolab::End) { parameters.baseParameter().push_back(icalendar_2_0::RelatedParamType(END)); } else { parameters.baseParameter().push_back(icalendar_2_0::RelatedParamType(START)); } trigger.parameters(parameters); } std::auto_ptr p; switch(alarm.type()) { case Kolab::Alarm::DisplayAlarm: p = std::auto_ptr(new PropType(PropType::action_type(DISPLAYALARM), trigger)); p->description(PropType::description_type(alarm.description())); break; case Kolab::Alarm::EMailAlarm: { p = std::auto_ptr(new PropType(PropType::action_type(EMAILALARM), trigger)); p->summary(PropType::summary_type(alarm.summary())); p->description(PropType::description_type(alarm.description())); const std::vector &l = alarm.attendees(); BOOST_FOREACH(const Kolab::ContactReference &attendee, l) { p->attendee().push_back(icalendar_2_0::ContactType(toMailto(attendee.email(), attendee.name()))); } break; } case Kolab::Alarm::AudioAlarm: p = std::auto_ptr(new PropType(PropType::action_type(AUDIOALARM), trigger)); p->description(PropType::description_type(alarm.description())); p->attach(fromAttachment(alarm.audioFile())); break; - default: - ERROR("invalid alarm"); - continue; + case Kolab::Alarm::InvalidAlarm: + break; } if (alarm.duration().isValid()) { p->duration(PropType::duration_type(fromDuration(alarm.duration()))); p->repeat(PropType::repeat_type(fromInt(alarm.numrepeat()))); } components.valarm().push_back(icalendar_2_0::ValarmType(p)); } } template void getAlarms(IncidenceType &incidence, const typename KolabType::components_type &components) { typedef icalendar_2_0::ValarmType::properties_type PropType; std::vector alarms; BOOST_FOREACH(const typename KolabType::components_type::valarm_type &valarm, components.valarm()) { const icalendar_2_0::ValarmType::properties_type &prop = valarm.properties(); Kolab::Alarm alarm; if (prop.action().text() == DISPLAYALARM) { if (!prop.description()) { ERROR("description is missing"); continue; } alarm = Kolab::Alarm((*prop.description()).text()); } else if (prop.action().text() == EMAILALARM) { std::vector attendees; if (prop.attendee().empty()) { WARNING("No receipents for email alarm"); } for (typename PropType::attendee_const_iterator at(prop.attendee().begin()); at != prop.attendee().end(); at++) { std::string name; const std::string &email = fromMailto((*at).cal_address(), name); attendees.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, email, name)); } if (!prop.description() || !prop.summary()) { ERROR("description or summary is missing"); continue; } alarm = Kolab::Alarm((*prop.summary()).text(), (*prop.description()).text(), attendees); } else if (prop.action().text() == AUDIOALARM) { if (!prop.attach()) { ERROR("audio file is missing"); continue; } const Kolab::Attachment &attach = toAttachment(*prop.attach()); if (!attach.isValid()) { ERROR("audio file is invalid"); continue; } alarm = Kolab::Alarm(attach); } else { ERROR("unknown alarm type " + prop.action().text()); continue; } if (prop.trigger().date_time()) { alarm.setStart(*Shared::toDate(*prop.trigger().date_time())); if (!alarm.start().isUTC()) { ERROR("The start date time must be in UTC "); continue; } } else if (prop.trigger().duration()) { Kolab::Relative relativeTo = Kolab::Start; if (prop.trigger().parameters()) { BOOST_FOREACH(const icalendar_2_0::ArrayOfParameters::baseParameter_type ¶m, (*prop.trigger().parameters()).baseParameter()) { if (const icalendar_2_0::RelatedParamType *rel = dynamic_cast (¶m)) { if (rel->text() == START) { relativeTo = Kolab::Start; } else if (rel->text() == END) { relativeTo = Kolab::End; } else { LOG("relativeTo not specified, default to start "); } } } } alarm.setRelativeStart(toDuration(*prop.trigger().duration()), relativeTo); } else { ERROR("no duration and not starttime "); continue; } if (prop.duration()) { int repeat = 0; if (prop.repeat()) { repeat = toInt(*prop.repeat()); } alarm.setDuration(toDuration((*prop.duration()).duration()), repeat); //TODO check duration? } alarms.push_back(alarm); } incidence.setAlarms(alarms); } //--- Alarms --- ///Trait for incidence properties specialized for Event/Todo/Journal template struct IncidenceTrait; template < > struct IncidenceTrait { typedef icalendar_2_0::KolabEvent KolabType; typedef Kolab::Event IncidenceType; typedef boost::shared_ptr IncidencePtr; static void writeIncidence(icalendar_2_0::KolabEvent& vevent, const Kolab::Event &event) { KolabType::components_type eventComponents; setAlarms(eventComponents, event); if (!eventComponents.valarm().empty()) { vevent.components(eventComponents); } icalendar_2_0::KolabEvent::properties_type &prop = vevent.properties(); getIncidenceProperties(prop, event); getTodoEventProperties(prop, event); if (event.end().isValid()) { prop.dtend(fromDate(event.end())); } else if (event.duration().isValid()) { prop.duration(icalendar_2_0::KolabEvent::properties_type::duration_type(fromDuration(event.duration()))); } if (event.transparency()) { prop.transp( icalendar_2_0::KolabEvent::properties_type::transp_type(TRANSPARENT)); } } static void addIncidence(icalendar_2_0::VcalendarType::components_type &components, icalendar_2_0::KolabEvent inc) //TODO to base trait { components.vevent().push_back(inc); } static void readIncidence(Kolab::Event &event, const icalendar_2_0::KolabEvent& vevent) { const icalendar_2_0::KolabEvent::properties_type &prop = vevent.properties(); if (!prop.dtstart()) { ERROR("Start date is missing, but is mandatory for events"); } setIncidenceProperties(event, prop); setTodoEventProperties(event, prop); if (prop.dtend()) { event.setEnd(*toDate(*prop.dtend())); } else if (prop.duration()) { event.setDuration(toDuration((*prop.duration()).duration())); } if (prop.transp()) { if (toString(*prop.transp()) == TRANSPARENT) { event.setTransparency(true); } else { event.setTransparency(false); if (toString(*prop.transp()) != OPAQUE) { ERROR("wrong transparency value " + toString(*prop.transp())); } } } if (vevent.components()) { getAlarms(event, *vevent.components()); } } static icalendar_2_0::VcalendarType::components_type::vevent_const_iterator begin(const icalendar_2_0::VcalendarType::components_type &components) { return components.vevent().begin(); } static icalendar_2_0::VcalendarType::components_type::vevent_const_iterator end(const icalendar_2_0::VcalendarType::components_type &components) { return components.vevent().end(); } static IncidencePtr resolveExceptions(const std::vector &list) { IncidencePtr incidence = *list.begin(); std::vector exceptions; for (std::vector < IncidencePtr >::const_iterator it = list.begin()+1; it != list.end(); it++) { exceptions.push_back(**it); } incidence->setExceptions(exceptions); return incidence; } static void addExceptions(icalendar_2_0::VcalendarType::components_type &components, const Kolab::Event &event, KolabType::properties_type props) { BOOST_FOREACH(const Kolab::Event &exception, event.exceptions()) { KolabType ex(props); writeIncidence(ex, exception); addIncidence(components, ex); } } }; template < > struct IncidenceTrait { typedef icalendar_2_0::KolabTodo KolabType; typedef Kolab::Todo IncidenceType; typedef boost::shared_ptr IncidencePtr; static void writeIncidence(icalendar_2_0::KolabTodo& vevent, const Kolab::Todo &todo) { KolabType::components_type eventComponents; setAlarms(eventComponents, todo); if (!eventComponents.valarm().empty()) { vevent.components(eventComponents); } icalendar_2_0::KolabTodo::properties_type &prop = vevent.properties(); getIncidenceProperties(prop, todo); getTodoEventProperties(prop, todo); if (!todo.relatedTo().empty()) { icalendar_2_0::KolabTodo::properties_type::related_to_sequence list; const std::vector &l = todo.relatedTo(); BOOST_FOREACH(const std::string &relatedTo, l) { list.push_back(icalendar_2_0::KolabTodo::properties_type::related_to_type(relatedTo)); } prop.related_to(list); } if (todo.due().isValid()) { prop.due(fromDate(todo.due())); } if (todo.percentComplete() > 0) { prop.percent_complete(icalendar_2_0::KolabTodo::properties_type::percent_complete_type(fromInt(todo.percentComplete()))); } } static void addIncidence(icalendar_2_0::VcalendarType::components_type &components, icalendar_2_0::KolabTodo inc) //TODO to base trait { components.vtodo().push_back(inc); } static void readIncidence(Kolab::Todo &todo, const icalendar_2_0::KolabTodo& vevent) { const icalendar_2_0::KolabTodo::properties_type &prop = vevent.properties(); setIncidenceProperties(todo, prop); setTodoEventProperties(todo, prop); if (!prop.related_to().empty()) { BOOST_FOREACH(icalendar_2_0::KolabTodo::properties_type::related_to_type p, prop.related_to()) { todo.addRelatedTo(p.text()); } } if (prop.due()) { todo.setDue(*toDate(*prop.due())); } if (prop.percent_complete()) { todo.setPercentComplete(toInt(*prop.percent_complete())); } if (vevent.components()) { getAlarms(todo, *vevent.components()); } } static icalendar_2_0::VcalendarType::components_type::vevent_const_iterator begin(const icalendar_2_0::VcalendarType::components_type &components) { return components.vtodo().begin(); } static icalendar_2_0::VcalendarType::components_type::vevent_const_iterator end(const icalendar_2_0::VcalendarType::components_type &components) { return components.vtodo().end(); } static IncidencePtr resolveExceptions(const std::vector &list) { IncidencePtr incidence = *list.begin(); std::vector exceptions; for (std::vector < IncidencePtr >::const_iterator it = list.begin()+1; it != list.end(); it++) { exceptions.push_back(**it); } incidence->setExceptions(exceptions); return incidence; } static void addExceptions(icalendar_2_0::VcalendarType::components_type &components, const Kolab::Todo &event, KolabType::properties_type props) { BOOST_FOREACH(const Kolab::Todo &exception, event.exceptions()) { KolabType ex(props); writeIncidence(ex, exception); addIncidence(components, ex); } } }; template < > struct IncidenceTrait { typedef icalendar_2_0::KolabJournal KolabType; typedef Kolab::Journal IncidenceType; typedef boost::shared_ptr IncidencePtr; static void writeIncidence(icalendar_2_0::KolabJournal& vjournal, const Kolab::Journal &journal) { icalendar_2_0::KolabJournal::properties_type &prop = vjournal.properties(); getIncidenceProperties(prop, journal); } static void addIncidence(icalendar_2_0::VcalendarType::components_type &components, icalendar_2_0::KolabJournal inc) { components.vjournal().push_back(inc); } static void readIncidence(Kolab::Journal &journal, const icalendar_2_0::KolabJournal& vjournal) { const icalendar_2_0::KolabJournal::properties_type &prop = vjournal.properties(); setIncidenceProperties(journal, prop); } static icalendar_2_0::VcalendarType::components_type::vjournal_const_iterator begin(const icalendar_2_0::VcalendarType::components_type &components) { return components.vjournal().begin(); } static icalendar_2_0::VcalendarType::components_type::vjournal_const_iterator end(const icalendar_2_0::VcalendarType::components_type &components) { return components.vjournal().end(); } static IncidencePtr resolveExceptions(const std::vector &list) { return *list.begin(); } static void addExceptions(icalendar_2_0::VcalendarType::components_type &, const Kolab::Journal &, KolabType::properties_type) { } }; template < > struct IncidenceTrait { typedef icalendar_2_0::KolabFreebusy KolabType; typedef Kolab::Freebusy IncidenceType; typedef boost::shared_ptr IncidencePtr; static void writeIncidence(icalendar_2_0::KolabFreebusy& vfreebusy, const Kolab::Freebusy &fb) { icalendar_2_0::KolabFreebusy::properties_type &prop = vfreebusy.properties(); if (fb.start().isValid() && fb.end().isValid()) { if ((fb.start().isUTC() || fb.start().isDateOnly()) && (fb.end().isUTC() || fb.end().isDateOnly())) { prop.dtstart(fromDate(fb.start())); prop.dtend(fromDate(fb.end())); } else { WARNING("Start/end is not in UTC, but it MUST be, skipping"); } } if (fb.organizer().isValid()) { prop.organizer(fromContactReference(fb.organizer())); } if (!fb.periods().empty()) { BOOST_FOREACH (const Kolab::FreebusyPeriod &fbPeriod, fb.periods()) { icalendar_2_0::KolabFreebusy::properties_type::freebusy_type fb; icalendar_2_0::BasePropertyType::parameters_type params; std::string fbtype; switch (fbPeriod.type()) { case FreebusyPeriod::Busy: fbtype = BUSY; break; case FreebusyPeriod::Tentative: fbtype = BUSY_TENTATIVE; break; case FreebusyPeriod::OutOfOffice: fbtype = BUSY_OUTOFOFFICE; break; case FreebusyPeriod::Invalid: - default: WARNING("Invalid fb type"); continue; } params.baseParameter().push_back(icalendar_2_0::FbtypeParamType(fbtype)); if (!fbPeriod.eventUid().empty() || fbPeriod.eventSummary().empty() || fbPeriod.eventLocation().empty()) { params.baseParameter().push_back(icalendar_2_0::XFBevent(fbPeriod.eventUid(), fbPeriod.eventSummary(), fbPeriod.eventLocation())); } fb.parameters(params); BOOST_FOREACH (const Kolab::Period &period, fbPeriod.periods()) { if (period.start.isDateOnly() || period.end.isDateOnly()) { WARNING("Period is date-only but must be date-time"); continue; } if (!period.start.isUTC() || !period.end.isUTC()) { WARNING("Period is not in UTC, but it MUST be, skipping"); continue; } icalendar_2_0::PeriodType p(Shared::fromDateTime(period.start)); p.end(Shared::fromDateTime(period.end)); fb.period().push_back(p); } prop.freebusy().push_back(fb); } } } static void addIncidence(icalendar_2_0::VcalendarType::components_type &components, icalendar_2_0::KolabFreebusy inc) { components.vfreebusy().push_back(inc); } static void readIncidence(Kolab::Freebusy &freebusy, const icalendar_2_0::KolabFreebusy& vfreebusy) { const icalendar_2_0::KolabFreebusy::properties_type &prop = vfreebusy.properties(); freebusy.setUid(toString(prop.uid())); freebusy.setTimestamp(*toDate(prop.dtstamp())); if (prop.dtstart()) { freebusy.setStart(*toDate(*prop.dtstart())); } if (prop.dtend()) { freebusy.setEnd(*toDate(*prop.dtend())); } if (prop.organizer()) { freebusy.setOrganizer(toContactReference(*prop.organizer())); } if (!prop.freebusy().empty()) { std::vector fbperiods; BOOST_FOREACH(icalendar_2_0::FreebusyPropType aProp, prop.freebusy()) { Kolab::FreebusyPeriod fbPeriod; fbPeriod.setType(Kolab::FreebusyPeriod::Busy); if (aProp.parameters()) { const icalendar_2_0::FreebusyPropType::parameters_type ¶meters = *aProp.parameters(); for (icalendar_2_0::FreebusyPropType::parameters_type::baseParameter_const_iterator it(parameters.baseParameter().begin()); it != parameters.baseParameter().end(); it++) { if (const icalendar_2_0::FbtypeParamType * p = dynamic_cast (&*it)) { if (p->text() == BUSY) { fbPeriod.setType(Kolab::FreebusyPeriod::Busy); } else if (p->text() == BUSY_OUTOFOFFICE) { fbPeriod.setType(Kolab::FreebusyPeriod::OutOfOffice); } else if (p->text() == BUSY_TENTATIVE) { fbPeriod.setType(Kolab::FreebusyPeriod::Tentative); } else { WARNING("Invalid fb type, default to busy"); } } if (const icalendar_2_0::XFBevent * p = dynamic_cast (&*it)) { fbPeriod.setEvent(p->uid(), p->summary(), p->location()); } } } std::vector periods; BOOST_FOREACH(icalendar_2_0::FreebusyPropType::period_type period, aProp.period()) { if (!period.end()) { WARNING("Period end date is required and duration is not supported, skipping period"); continue; } periods.push_back(Kolab::Period(*Shared::toDate(period.start()), *Shared::toDate(*period.end()))); } fbPeriod.setPeriods(periods); fbperiods.push_back(fbPeriod); } freebusy.setPeriods(fbperiods); } } static icalendar_2_0::VcalendarType::components_type::vfreebusy_const_iterator begin(const icalendar_2_0::VcalendarType::components_type &components) { return components.vfreebusy().begin(); } static icalendar_2_0::VcalendarType::components_type::vfreebusy_const_iterator end(const icalendar_2_0::VcalendarType::components_type &components) { return components.vfreebusy().end(); } static IncidencePtr resolveExceptions(const std::vector &list) { return *list.begin(); } static void addExceptions(icalendar_2_0::VcalendarType::components_type &, const Kolab::Freebusy &, KolabType::properties_type) { } }; //////////////////////////////////========================================= template std::string serializeIncidence(const typename T::IncidenceType &incidence, const std::string productid = std::string()) { using namespace icalendar_2_0; typedef typename T::KolabType KolabType; try { typename KolabType::properties_type::uid_type uid( getUID(incidence.uid())); setCreatedUid(uid.text()); typename KolabType::properties_type::dtstamp_type dtstamp; if (incidence.lastModified().isValid()) { dtstamp.date_time(fromDateTime(incidence.lastModified())); } else { dtstamp.date_time(fromDateTime(timestamp())); } typename KolabType::properties_type::created_type created; if (incidence.created().isValid()) { created.date_time(fromDateTime(incidence.created())); } else { created.date_time(fromDateTime(timestamp())); } typename KolabType::properties_type eventProps(uid, created, dtstamp); KolabType inc(eventProps); T::writeIncidence(inc, incidence); VcalendarType::components_type components; T::addIncidence(components, inc); T::addExceptions(components, incidence, eventProps); VcalendarType::properties_type::prodid_type prodid(getProductId(productid)); VcalendarType::properties_type::version_type version(XCAL_VERSION); VcalendarType::properties_type::x_kolab_version_type x_kolab_version(KOLAB_FORMAT_VERSION); VcalendarType::properties_type properties(prodid, version, x_kolab_version); VcalendarType vcalendar(properties, components); IcalendarType icalendar(vcalendar); xml_schema::namespace_infomap map; map[""].name = XCAL_NAMESPACE; std::ostringstream ostringstream; icalendar_2_0::icalendar(ostringstream, icalendar, map); return ostringstream.str(); - } catch (const xml_schema::exception& e) { + } catch (const xml_schema::exception&) { CRITICAL("failed to write Incidence"); } catch (...) { CRITICAL("Unhandled exception"); } return std::string(); } template typename T::IncidencePtr deserializeIncidence(const std::string& s, bool isUrl) { using namespace icalendar_2_0; typedef typename T::IncidencePtr IncidencePtr; typedef typename T::IncidenceType IncidenceType; typedef typename T::KolabType KolabType; try { std::auto_ptr icalendar; if (isUrl) { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseFile(s); if (doc.get()) { icalendar = icalendar_2_0::icalendar(doc); } } else { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseString(s); if (doc.get()) { icalendar = icalendar_2_0::icalendar(doc); } } if (!icalendar.get()) { CRITICAL("Failed to parse calendar!"); return IncidencePtr(); } const icalendar_2_0::VcalendarType &vcalendar = icalendar->vcalendar(); std::vector < IncidencePtr > incidences; for (typename xsd::cxx::tree::sequence< KolabType >::const_iterator it(T::begin(vcalendar.components())); it != T::end(vcalendar.components()); it++) { IncidencePtr e = IncidencePtr(new IncidenceType); const KolabType &event = *it; T::readIncidence(*e, event); incidences.push_back(e); } setProductId( vcalendar.properties().prodid().text() ); setXCalVersion(vcalendar.properties().version().text()); setKolabVersion( vcalendar.properties().x_kolab_version().text() ); if (incidences.empty()) { CRITICAL("no incidence in object"); return IncidencePtr(); } return T::resolveExceptions(incidences); } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to read incidence!"); return IncidencePtr(); } template std::string serializeFreebusy(const Kolab::Freebusy &incidence, const std::string productid = std::string()) { using namespace icalendar_2_0; typedef typename T::KolabType KolabType; try { typename KolabType::properties_type::uid_type uid( getUID(incidence.uid())); setCreatedUid(uid.text()); typename KolabType::properties_type::dtstamp_type dtstamp; dtstamp.date_time(fromDateTime(timestamp())); typename KolabType::properties_type eventProps(uid, dtstamp); KolabType inc(eventProps); T::writeIncidence(inc, incidence); VcalendarType::components_type components; T::addIncidence(components, inc); VcalendarType::properties_type::prodid_type prodid(getProductId(productid)); VcalendarType::properties_type::version_type version(XCAL_VERSION); VcalendarType::properties_type::x_kolab_version_type x_kolab_version(KOLAB_FORMAT_VERSION); VcalendarType::properties_type properties(prodid, version, x_kolab_version); VcalendarType vcalendar(properties, components); IcalendarType icalendar(vcalendar); xml_schema::namespace_infomap map; map[""].name = XCAL_NAMESPACE; std::ostringstream ostringstream; icalendar_2_0::icalendar(ostringstream, icalendar, map); return ostringstream.str(); } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("failed to write Incidence"); return std::string(); } } }//Namespace #endif diff --git a/src/xcardconversions.h b/src/xcardconversions.h index b88304e..4f58aab 100644 --- a/src/xcardconversions.h +++ b/src/xcardconversions.h @@ -1,1195 +1,1191 @@ /* * Copyright (C) 2011 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #ifndef KOLABXCARDCONVERSION_H #define KOLABXCARDCONVERSION_H #include #include #include #include #include #include #include "kolabcontainers.h" #include "global_definitions.h" #include "libkolabxml-version.h" #include "utils.h" #include "kolabcontact.h" #include "shared_conversions.h" namespace Kolab { namespace XCARD { const char* const XCARD_NAMESPACE = "urn:ietf:params:xml:ns:vcard-4.0"; const char* const INDIVIDUAL = "individual"; const char* const GROUP = "group"; const char* const MIME_PGP_KEYS = "application/pgp-keys"; const char* const MIME_PKCS7_MIME = "application/pkcs7-mime"; using namespace Kolab::Utils; template std::string getType(); template <> std::string getType() { return INDIVIDUAL; } template <> std::string getType() { return GROUP; } template xsd::cxx::tree::sequence fromList(const std::vector &input) { xsd::cxx::tree::sequence list; BOOST_FOREACH(const std::string &s, input) { list.push_back(T(s)); } return list; } template xsd::cxx::tree::sequence fromList(const std::vector &input, int preferredIndex) { xsd::cxx::tree::sequence list; int index = 0; BOOST_FOREACH(const std::string &s, input) { T im(s); if(preferredIndex == index) { typename T::parameters_type parameters; parameters.baseParameter().push_back(vcard_4_0::prefParamType(vcard_4_0::prefParamType::integer_default_value())); im.parameters(parameters); } index++; list.push_back(im); } return list; } template std::vector toUriList(const xsd::cxx::tree::sequence &input) { std::vector list; BOOST_FOREACH(const vcard_4_0::UriPropertyType &s, input) { list.push_back(s.uri()); } return list; } template std::vector toTextList(const xsd::cxx::tree::sequence &input) { std::vector list; BOOST_FOREACH(const vcard_4_0::TextPropertyType &s, input) { list.push_back(s.text()); } return list; } std::vector toStringList(const ::xsd::cxx::tree::sequence< ::xml_schema::string > &s) { std::vector d; std::copy(s.begin(), s.end(), std::back_inserter(d)); return d; } ::xsd::cxx::tree::sequence< ::xml_schema::string > fromStringList(const std::vector &s) { ::xsd::cxx::tree::sequence< ::xml_schema::string > d; std::copy(s.begin(), s.end(), std::back_inserter(d)); return d; } std::string fromDate(const cDateTime &dt) { if (!dt.isDateOnly()) { WARNING("fromDate called on date time value"); } std::stringstream s; s.fill('0'); s.width(4); s << dt.year(); s.width(2); s << dt.month(); s.width(2); s << dt.day(); return s.str(); } std::string fromDateTime(const cDateTime &dt) { std::stringstream s; s.fill('0'); s << std::right; s.width(4); s << dt.year(); s.width(2); s << dt.month(); s.width(2); s << dt.day(); s.width(1); if (dt.isDateOnly()) { return s.str(); } s << "T"; s.width(2); s << dt.hour(); s.width(2); s << dt.minute(); s.width(2); s << dt.second(); if (dt.isUTC()) { s << "Z"; } return s.str(); } cDateTime toDateTime(const std::string &input) { int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; bool isUtc = false; try { year = boost::lexical_cast(input.substr(0, 4)); month = boost::lexical_cast(input.substr(4, 2)); day = boost::lexical_cast(input.substr(6, 2)); if (input.size() >= 15) { //Minimum for time if (input.at(8) != 'T') { ERROR("Wrong demiliter"); return cDateTime(); } hour = boost::lexical_cast(input.substr(9, 2)); minute = boost::lexical_cast(input.substr(11, 2)); second = boost::lexical_cast(input.substr(13, 2)); } else { if (input.size() >= 9) { ERROR("Invalid dt " + input); return cDateTime(); } return cDateTime(year, month, day); } if (input.size() >= 16) { if (input.at(15) == 'Z') { isUtc = true; } else { std::ostringstream s; s << "wrong utc char? " << input.at(15); ERROR(s.str()); return cDateTime(); } } } catch (boost::bad_lexical_cast &c) { ERROR("failed to convert: "+std::string(c.what())); return cDateTime(); } catch (...) { ERROR("failed to convert: unknown exception"); return cDateTime(); } return cDateTime(year, month, day, hour, minute, second, isUtc); } cDateTime toDateTime(const vcard_4_0::DateDatetimePropertyType &prop) { if (prop.date_time()) { return toDateTime(*prop.date_time()); } else if (prop.date()) { return toDateTime(*prop.date()); } ERROR("no date and no datetime"); return cDateTime(); } template T fromDateTime(const Kolab::cDateTime &dt) { T prop; if (dt.isDateOnly()) { prop.date(fromDate(dt)); } else { prop.date_time(fromDateTime(dt)); } return prop; } vcard_4_0::PrefTypeValueType fromCryptoPref(Kolab::Crypto::CryptoPref pref) { switch (pref) { case Kolab::Crypto::Always: return vcard_4_0::CryptoType::encryptpref_type::text_type::Always; case Kolab::Crypto::Ask: return vcard_4_0::CryptoType::encryptpref_type::text_type::Ask; case Kolab::Crypto::IfPossible: return vcard_4_0::CryptoType::encryptpref_type::text_type::IfPossible; case Kolab::Crypto::Never: return vcard_4_0::CryptoType::encryptpref_type::text_type::Never; - default: - WARNING("unknown encrypt pref"); } return vcard_4_0::CryptoType::encryptpref_type::text_type::Ask; } Kolab::Crypto::CryptoPref toCryptoPref(vcard_4_0::PrefTypeValueType pref) { switch (pref) { case vcard_4_0::CryptoType::encryptpref_type::text_type::Always: return Kolab::Crypto::Always; case vcard_4_0::CryptoType::encryptpref_type::text_type::Ask: return Kolab::Crypto::Ask; case vcard_4_0::CryptoType::encryptpref_type::text_type::IfPossible: return Kolab::Crypto::IfPossible; case vcard_4_0::CryptoType::encryptpref_type::text_type::Never: return Kolab::Crypto::Never; - default: - WARNING("unknown encrypt pref"); } return Kolab::Crypto::Ask; } vcard_4_0::relatedPropType fromRelated(const Kolab::Related &r) { using namespace vcard_4_0; vcard_4_0::relatedPropType related; if (r.type() == Kolab::Related::Uid) { related.uri(r.uri()); } else { related.text(r.text()); } if (r.relationTypes() != Kolab::Related::NoRelation) { vcard::adr_type::parameters_type::baseParameter_sequence base; vcard::adr_type::parameters_type b; vcard_4_0::typeParamType::text_sequence seq; if (r.relationTypes() & Kolab::Related::Child) { seq.push_back(TypeValueType::child); } if (r.relationTypes() & Kolab::Related::Spouse) { seq.push_back(TypeValueType::spouse); } if (r.relationTypes() & Kolab::Related::Assistant) { seq.push_back(TypeValueType::x_assistant); } if (r.relationTypes() & Kolab::Related::Manager) { seq.push_back(TypeValueType::x_manager); } if (!seq.empty()) { vcard_4_0::typeParamType type; type.text(seq); b.baseParameter().push_back(type); } related.parameters(b); } return related; } Kolab::Related toRelated(const vcard_4_0::relatedPropType &r) { Kolab::Related::DescriptionType type = Kolab::Related::Invalid; std::string textOrUri; if (r.uri()) { type = Kolab::Related::Uid; textOrUri = *r.uri(); } else if (r.text()) { type = Kolab::Related::Text; textOrUri = *r.text(); } else { ERROR("no text and no uri"); return Kolab::Related(); } Kolab::Related related(type, textOrUri); if (r.parameters()) { BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type ¶m, (*r.parameters()).baseParameter()) { if (const vcard_4_0::typeParamType *rel = dynamic_cast (¶m)) { int types = 0; BOOST_FOREACH(const std::string &s, rel->text()) { if (s == vcard_4_0::TypeValueType(vcard_4_0::TypeValueType::child)) { types |= Kolab::Related::Child; } if (s == vcard_4_0::TypeValueType(vcard_4_0::TypeValueType::spouse)) { types |= Kolab::Related::Spouse; } if (s == vcard_4_0::TypeValueType(vcard_4_0::TypeValueType::x_assistant)) { types |= Kolab::Related::Assistant; } if (s == vcard_4_0::TypeValueType(vcard_4_0::TypeValueType::x_manager)) { types |= Kolab::Related::Manager; } } related.setRelationTypes(types); } } } return related; } vcard_4_0::vcard::adr_type fromAddress(const Kolab::Address &address) { using namespace vcard_4_0; vcard::adr_type a(vcard::adr_type::pobox_type(std::string()/*address.pobox()*/), vcard::adr_type::ext_type(std::string()/*address.ext()*/), vcard::adr_type::street_type(address.street()), vcard::adr_type::locality_type(address.locality()), vcard::adr_type::region_type(address.region()), address.code(), vcard::adr_type::country_type(address.country()) ); vcard::adr_type::parameters_type b; if (address.types()) { vcard_4_0::typeParamType::text_sequence seq; if (address.types() & Kolab::Address::Home) { seq.push_back(TypeValueType::home); } if (address.types() & Kolab::Address::Work) { seq.push_back(TypeValueType::work); } if (!seq.empty()) { vcard_4_0::typeParamType type; type.text(seq); b.baseParameter().push_back(type); } } if (!address.label().empty()) { b.baseParameter().push_back(vcard_4_0::labelParamType(address.label())); } a.parameters(b); return a; } Kolab::Address toAddress(const vcard_4_0::vcard::adr_type &adr, bool *isPreferred = 0) { using namespace vcard_4_0; Address address; if (adr.parameters()) { BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type ¶m, (*adr.parameters()).baseParameter()) { if (const vcard_4_0::labelParamType *rel = dynamic_cast (¶m)) { address.setLabel(rel->text()); } else if (isPreferred && dynamic_cast (¶m)) { *isPreferred = true; } else if (const vcard_4_0::typeParamType *rel = dynamic_cast (¶m)) { int types = 0; BOOST_FOREACH(const std::string &s, rel->text()) { if (s == TypeValueType(TypeValueType::work)) { types |= Kolab::Telephone::Work; } if (s == TypeValueType(TypeValueType::home)) { types |= Kolab::Telephone::Home; } } address.setTypes(types); } } } address.setCode(adr.code()); address.setCountry(adr.country()); address.setLocality(adr.locality()); address.setRegion(adr.region()); address.setStreet(adr.street()); return address; } std::string toGeoUri(double lat, double lon) { //lexical_cast doesn't work, so we're using stringstream std::stringstream s; s << "geo:"; s.precision(15); //can't use std::numeric_limits::max_digits10 because that's c++ 0x, it should be 17, but that seems to cause rounding problems... no idea why. s << lat << ","; s.precision(15); //Needed to get the right precision somehow... s << lon; return s.str(); } bool fromGeoUri(const std::string &uri, double &lat, double &lon) { if (uri.substr(0,4) != std::string("geo:")) { WARNING("not a geo uri"); return false; } std::size_t pos1 = uri.find(","); if (pos1 == std::string::npos) { WARNING("not a valid geo uri"); return false; } lat = boost::lexical_cast(uri.substr(4, pos1-4)); lon = boost::lexical_cast(uri.substr(pos1+1, uri.size()-pos1-1)); return true; } template void writeCard(vcard_4_0::vcard &vcard, const T &); template <> void writeCard(vcard_4_0::vcard &vcard, const Kolab::Contact &contact) { using namespace vcard_4_0; if (!contact.categories().empty()) { vcard_4_0::vcard::categories_type cat; vcard_4_0::vcard::categories_type::text_sequence seq; const std::vector &l = contact.categories(); BOOST_FOREACH(const std::string &s, l) { seq.push_back(s); } cat.text(seq); vcard.categories(cat); } if (contact.nameComponents().isValid()) { const NameComponents &nc = contact.nameComponents(); vcard::n_type n; n.surname(fromStringList(nc.surnames())); n.given(fromStringList(nc.given())); n.additional(fromStringList(nc.additional())); n.prefix(fromStringList(nc.prefixes())); n.suffix(fromStringList(nc.suffixes())); vcard.n(n); } if (!contact.note().empty()) { vcard.note(vcard::note_type(contact.note())); } if (!contact.freeBusyUrl().empty()) { vcard.fburl(vcard::fburl_type(contact.freeBusyUrl())); } if (!contact.titles().empty()) { vcard.title(fromList(contact.titles())); } if (!contact.affiliations().empty()) { vcard::group_sequence affiliations; const std::vector &l = contact.affiliations(); BOOST_FOREACH(const Affiliation &a, l) { if (a == Affiliation()) { //skip empty ones LOG("skipped empty affiliation"); continue; } affiliationPropType::org_type org; org.text().push_back(a.organisation()); const std::vector &orgUnits = a.organisationalUnits(); BOOST_FOREACH(const std::string &unit, orgUnits) { org.text().push_back(unit); } vcard::group_type group(org); if (!a.logo().empty()) { group.logo(affiliationPropType::logo_type(uriInlineEncoding(a.logo(), a.logoMimetype()))); } group.role(fromList(a.roles())); const std::vector &relateds = a.relateds(); BOOST_FOREACH(const Related &rel, relateds) { group.related().push_back(fromRelated(rel)); } const std::vector
&addersses = a.addresses(); BOOST_FOREACH(const Address &adr, addersses) { group.adr().push_back(fromAddress(adr)); } affiliations.push_back(group); } vcard.group(affiliations); } if (!contact.urls().empty()) { vcard_4_0::vcard::url_sequence urls; const std::vector &l = contact.urls(); BOOST_FOREACH(const Kolab::Url &url, l) { vcard::url_type u(url.url()); if (url.type() == Kolab::Url::Blog) { vcard::adr_type::parameters_type b; vcard_4_0::typeParamType p; p.text().push_back(vcard_4_0::TypeValueType::x_blog); b.baseParameter().push_back(p); u.parameters(b); } urls.push_back(u); } vcard.url(urls); } if (!contact.addresses().empty()) { vcard::adr_sequence adrs; int index = 0; const std::vector
&l = contact.addresses(); BOOST_FOREACH(const Kolab::Address &address, l) { vcard::adr_type a = fromAddress(address); if(contact.addressPreferredIndex() == index) { if (a.parameters()) { (*a.parameters()).baseParameter().push_back(vcard_4_0::prefParamType(vcard_4_0::prefParamType::integer_default_value())); } else { vcard::adr_type::parameters_type b; b.baseParameter().push_back(vcard_4_0::prefParamType(vcard_4_0::prefParamType::integer_default_value())); a.parameters(b); } } index++; adrs.push_back(a); } vcard.adr(adrs); } if (!contact.nickNames().empty()) { vcard::nickname_type::text_sequence textsequence; const std::vector &l = contact.nickNames(); BOOST_FOREACH(const std::string &s, l) { textsequence.push_back(s); } vcard::nickname_type nickName; nickName.text(textsequence); vcard.nickname(nickName); } if (!contact.relateds().empty()) { vcard::related_sequence seq; const std::vector &l = contact.relateds(); BOOST_FOREACH(const Kolab::Related &r, l) { seq.push_back(fromRelated(r)); } vcard.related(seq); } if (contact.bDay().isValid()) { Kolab::cDateTime dt = contact.bDay(); if (dt.isUTC() || !dt.timezone().empty()) { WARNING("Must be local time, local time assumed"); dt.setUTC(false); } vcard.bday(fromDateTime(dt)); } if (contact.anniversary().isValid()) { Kolab::cDateTime dt = contact.anniversary(); if (dt.isUTC() || !dt.timezone().empty()) { WARNING("Must be local time, local time assumed"); dt.setUTC(false); } vcard.anniversary(fromDateTime(dt)); } if (!contact.photo().empty()) { vcard::photo_type photo(vcard_4_0::UriPropertyType::uri_type(uriInlineEncoding(contact.photo(), contact.photoMimetype()))); vcard.photo(photo); } if (contact.gender() != Contact::NotSet) { switch (contact.gender()) { case Contact::NotSpecified: vcard.gender(vcard::gender_type(vcard::gender_type::sex_type::empty)); break; case Contact::Male: vcard.gender(vcard::gender_type(vcard::gender_type::sex_type::M)); break; case Contact::Female: vcard.gender(vcard::gender_type(vcard::gender_type::sex_type::F)); break; - default: + case Contact::NotSet: ERROR("Unhandled gender"); } } if (!contact.languages().empty()) { vcard.lang(fromList(contact.languages())); } if (!contact.telephones().empty()) { vcard::tel_sequence seq; int index = 0; const std::vector &l = contact.telephones(); BOOST_FOREACH(const Kolab::Telephone &t, l) { vcard::tel_type tel(t.number()); vcard_4_0::typeParamType telTypeParam; if (t.types() & Kolab::Telephone::Car) { telTypeParam.text().push_back(TypeValueType::x_car); } if (t.types() & Kolab::Telephone::Cell) { telTypeParam.text().push_back(TypeValueType::cell); } if (t.types() & Kolab::Telephone::Fax) { telTypeParam.text().push_back(TypeValueType::fax); } if (t.types() & Kolab::Telephone::Home) { telTypeParam.text().push_back(TypeValueType::home); } if (t.types() & Kolab::Telephone::Work) { telTypeParam.text().push_back(TypeValueType::work); } if (t.types() & Kolab::Telephone::Text) { telTypeParam.text().push_back(TypeValueType::text); } if (t.types() & Kolab::Telephone::Voice) { telTypeParam.text().push_back(TypeValueType::voice); } if (t.types() & Kolab::Telephone::Video) { telTypeParam.text().push_back(TypeValueType::video); } if (t.types() & Kolab::Telephone::Textphone) { telTypeParam.text().push_back(TypeValueType::textphone); } if (t.types() & Kolab::Telephone::Pager) { telTypeParam.text().push_back(TypeValueType::pager); } vcard::tel_type::parameters_type params; if(contact.telephonesPreferredIndex() == index) { params.baseParameter().push_back(vcard_4_0::prefParamType(vcard_4_0::prefParamType::integer_default_value())); } index++; if (!telTypeParam.text().empty()) { params.baseParameter().push_back(telTypeParam); tel.parameters(params); } seq.push_back(tel); } vcard.tel(seq); } if (!contact.imAddresses().empty()) { vcard.impp(fromList(contact.imAddresses(), contact.imAddressPreferredIndex())); } if (!contact.emailAddresses().empty()) { vcard::email_sequence seq; int index = 0; const std::vector &l = contact.emailAddresses(); BOOST_FOREACH(const Kolab::Email &e, l) { vcard::email_type email(e.address()); vcard_4_0::typeParamType emailTypeParam; if (e.types() & Kolab::Email::Home) { emailTypeParam.text().push_back(TypeValueType::home); } if (e.types() & Kolab::Email::Work) { emailTypeParam.text().push_back(TypeValueType::work); } vcard::tel_type::parameters_type params; if (!emailTypeParam.text().empty()) { params.baseParameter().push_back(emailTypeParam); } if(contact.emailAddressPreferredIndex() == index) { params.baseParameter().push_back(vcard_4_0::prefParamType(vcard_4_0::prefParamType::integer_default_value())); } index++; if (!params.baseParameter().empty()) { email.parameters(params); } seq.push_back(email); } vcard.email(seq); } if (!contact.gpsPos().empty()) { vcard_4_0::vcard::geo_sequence list; const std::vector &l = contact.gpsPos(); BOOST_FOREACH(const Kolab::Geo &g, l) { list.push_back(vcard_4_0::vcard::geo_type(toGeoUri(g.latitude, g.longitude))); } vcard.geo(list); } if (contact.crypto().isValid()) { vcard::x_crypto_type crypto; const Kolab::Crypto &c = contact.crypto(); if (c.allowed()) { vcard::x_crypto_type::allowed_type::text_sequence seq; if (c.allowed() & Kolab::Crypto::PGPinline) { seq.push_back(vcard::x_crypto_type::allowed_type::text_type::PGP_INLINE); } if (c.allowed() & Kolab::Crypto::PGPmime) { seq.push_back(vcard::x_crypto_type::allowed_type::text_type::PGP_MIME); } if (c.allowed() & Kolab::Crypto::SMIME) { seq.push_back(vcard::x_crypto_type::allowed_type::text_type::S_MIME); } if (c.allowed() & Kolab::Crypto::SMIMEopaque) { seq.push_back(vcard::x_crypto_type::allowed_type::text_type::S_MIMEOpaque); } vcard::x_crypto_type::allowed_type allowed; allowed.text(seq); crypto.allowed(allowed); } crypto.encryptpref(fromCryptoPref(c.encryptPref())); crypto.signpref(fromCryptoPref(c.signPref())); vcard.x_crypto(crypto); } if (!contact.keys().empty()) { vcard_4_0::vcard::key_sequence keys; const std::vector &l = contact.keys(); BOOST_FOREACH (const Kolab::Key &k, l) { switch (k.type()) { case Kolab::Key::PGP: keys.push_back(vcard_4_0::keyPropType(uriInlineEncoding(k.key(), MIME_PGP_KEYS))); break; case Kolab::Key::PKCS7_MIME: keys.push_back(vcard_4_0::keyPropType(uriInlineEncoding(k.key(), MIME_PKCS7_MIME))); break; - default: - LOG("Unhandled/Invalid keytype"); + case Kolab::Key::Invalid: + LOG("Invalid keytype"); break; } } if (!keys.empty()) { vcard.key(keys); } } } template <> void writeCard(vcard_4_0::vcard &vcard, const Kolab::DistList &distlist) { if (!distlist.members().empty()) { vcard_4_0::vcard::member_sequence members; const std::vector &l = distlist.members(); BOOST_FOREACH (const Kolab::ContactReference &m, l) { if (!m.uid().empty()) { members.push_back(vcard_4_0::vcard::member_type(Shared::toURN(m.uid()))); } else { members.push_back(vcard_4_0::vcard::member_type(Shared::toMailto(m.email(), m.name()))); } } vcard.member(members); } } template std::string serializeCard(const T &card, const std::string prod = std::string()) { using namespace vcard_4_0; clearErrors(); try { vcard_4_0::vcard::uid_type uid(Shared::toURN(getUID(card.uid()))); setCreatedUid(Shared::fromURN(uid.uri())); vcard_4_0::vcard::x_kolab_version_type kolab_version(KOLAB_FORMAT_VERSION); vcard_4_0::vcard::prodid_type prodid(getProductId(prod)); vcard_4_0::vcard::rev_type rev(fromDateTime(timestamp())); vcard_4_0::vcard::kind_type kind(getType()); vcard_4_0::vcard::fn_type fn(card.name()); vcard_4_0::vcard vcard(uid, kolab_version, prodid, rev, kind, fn); writeCard(vcard, card); if (!card.customProperties().empty()) { const std::vector &l = card.customProperties(); BOOST_FOREACH(const Kolab::CustomProperty &a, l) { vcard.x_custom().push_back(vcard_4_0::CustomType(a.identifier, a.value)); } } VcardsType vcards(vcard); xml_schema::namespace_infomap map; map[""].name = XCARD_NAMESPACE; std::ostringstream ostringstream; vcard_4_0::vcards(ostringstream, vcards, map); return ostringstream.str(); } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to write vcard!"); return std::string(); } template boost::shared_ptr readCard(const vcard_4_0::VcardsType::vcard_type &vcard); template <> boost::shared_ptr readCard (const vcard_4_0::VcardsType::vcard_type &vcard) { using namespace vcard_4_0; boost::shared_ptr contact(new Kolab::Contact); if (vcard.categories()) { contact->setCategories(toStringList((*vcard.categories()).text())); } if (vcard.n()) { NameComponents nc; nc.setSurnames(toStringList((*vcard.n()).surname())); nc.setGiven(toStringList((*vcard.n()).given())); nc.setPrefixes(toStringList((*vcard.n()).prefix())); nc.setSuffixes(toStringList((*vcard.n()).suffix())); nc.setAdditional(toStringList((*vcard.n()).additional())); contact->setNameComponents(nc); } if (vcard.note()) { contact->setNote((*vcard.note()).text()); } if (vcard.fburl()) { contact->setFreeBusyUrl((*vcard.fburl()).uri()); } if (!vcard.title().empty()) { contact->setTitles(toTextList(vcard.title())); } if (!vcard.group().empty()) { std::vector list; BOOST_FOREACH (const vcard::group_type &group, vcard.group()) { Kolab::Affiliation aff; if (!group.org().text().empty()) { aff.setOrganisation(*group.org().text().begin()); std::vector units; for ( vcard_4_0::NonEmptyTextListPropertyType::text_const_iterator it = ++group.org().text().begin(); it != group.org().text().end(); it++) { units.push_back(*it); } aff.setOrganisationalUnits(units); } else { WARNING("No org present"); } std::string mimetype; if (group.logo()) { const std::string &logo = uriInlineDecoding((*group.logo()).uri(), mimetype); aff.setLogo(logo, mimetype); } aff.setRoles(toTextList(group.role())); std::vector relateds; BOOST_FOREACH(const vcard::group_type::related_type &rel, group.related()) { relateds.push_back(toRelated(rel)); } aff.setRelateds(relateds); std::vector
addresses; BOOST_FOREACH(const vcard::group_type::adr_type &adr, group.adr()) { addresses.push_back(toAddress(adr)); } aff.setAddresses(addresses); list.push_back(aff); } contact->setAffiliations(list); } if (!vcard.url().empty()) { std::vector urls; BOOST_FOREACH(const vcard_4_0::vcard::url_type &url, vcard.url()) { if (url.parameters()) { //We have only one fixed parameter (x-blog) urls.push_back(Kolab::Url(url.uri(), Kolab::Url::Blog)); } else { urls.push_back(Kolab::Url(url.uri())); } } contact->setUrls(urls); } if (!vcard.adr().empty()) { std::vector list; int preferredIndex = -1; int index = 0; BOOST_FOREACH(const vcard::adr_type &adr, vcard.adr()) { bool isPreferred = false; const Kolab::Address &address = toAddress(adr, &isPreferred); if (isPreferred) { preferredIndex = index; } index++; list.push_back(address); } contact->setAddresses(list, preferredIndex); } if (vcard.nickname()) { contact->setNickNames(toTextList((*vcard.nickname()).text())); } if (!vcard.related().empty()) { std::vector list; BOOST_FOREACH(const vcard_4_0::vcard::related_type &r, vcard.related()) { list.push_back(toRelated(r)); } contact->setRelateds(list); } if (vcard.bday()) { contact->setBDay(toDateTime(*vcard.bday())); } if (vcard.anniversary()) { contact->setAnniversary(toDateTime(*vcard.anniversary())); } if (vcard.photo()) { std::string mimetype; const std::string decodedPhoto = uriInlineDecoding((*vcard.photo()).uri(), mimetype); contact->setPhoto(decodedPhoto, mimetype); } if (vcard.gender()) { if ((*vcard.gender()).sex() == vcard::gender_type::sex_type::empty) { contact->setGender(Kolab::Contact::NotSpecified); } else if ((*vcard.gender()).sex() == vcard::gender_type::sex_type::M) { contact->setGender(Kolab::Contact::Male); } else if ((*vcard.gender()).sex() == vcard::gender_type::sex_type::F) { contact->setGender(Kolab::Contact::Female); } } if (!vcard.lang().empty()) { std::vector list; BOOST_FOREACH(const vcard::lang_type l, vcard.lang()) { list.push_back(l.language_tag()); } contact->setLanguages(list); } if (!vcard.tel().empty()) { std::vector list; int preferredIndex = -1; int index = 0; BOOST_FOREACH(const vcard::tel_type &tel, vcard.tel()) { Kolab::Telephone telephone; if (tel.parameters()) { BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type ¶m, (*tel.parameters()).baseParameter()) { if (dynamic_cast (¶m)) { preferredIndex = index; } else if (const vcard_4_0::typeParamType *rel = dynamic_cast (¶m)) { int types = 0; BOOST_FOREACH(const std::string &s, rel->text()) { if (s == TypeValueType(TypeValueType::work)) { types |= Kolab::Telephone::Work; } if (s == TypeValueType(TypeValueType::home)) { types |= Kolab::Telephone::Home; } if (s == TypeValueType(TypeValueType::text)) { types |= Kolab::Telephone::Text; } if (s == TypeValueType(TypeValueType::voice)) { types |= Kolab::Telephone::Voice; } if (s == TypeValueType(TypeValueType::fax)) { types |= Kolab::Telephone::Fax; } if (s == TypeValueType(TypeValueType::cell)) { types |= Kolab::Telephone::Cell; } if (s == TypeValueType(TypeValueType::video)) { types |= Kolab::Telephone::Video; } if (s == TypeValueType(TypeValueType::pager)) { types |= Kolab::Telephone::Pager; } if (s == TypeValueType(TypeValueType::textphone)) { types |= Kolab::Telephone::Textphone; } if (s == TypeValueType(TypeValueType::x_car)) { types |= Kolab::Telephone::Car; } } telephone.setTypes(types); } } } index++; telephone.setNumber(tel.text()); list.push_back(telephone); } contact->setTelephones(list, preferredIndex); } if (!vcard.impp().empty()) { int preferredIndex = -1; std::vector list; int i = 0; BOOST_FOREACH(const vcard_4_0::UriPropertyType &s, vcard.impp()) { if (s.parameters()) { BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type ¶m, (*s.parameters()).baseParameter()) { if (dynamic_cast (¶m)) { preferredIndex = i; } } } i++; list.push_back(s.uri()); } contact->setIMaddresses(list, preferredIndex); } if (!vcard.email().empty()) { int preferredIndex = -1; std::vector list; int i = 0; BOOST_FOREACH(const vcard_4_0::TextPropertyType &s, vcard.email()) { Kolab::Email email; if (s.parameters()) { BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type ¶m, (*s.parameters()).baseParameter()) { if (dynamic_cast (¶m)) { preferredIndex = i; } else if (const vcard_4_0::typeParamType *rel = dynamic_cast (¶m)) { int types = 0; BOOST_FOREACH(const std::string &s, rel->text()) { if (s == TypeValueType(TypeValueType::work)) { types |= Kolab::Email::Work; } if (s == TypeValueType(TypeValueType::home)) { types |= Kolab::Email::Home; } } email.setTypes(types); } } } i++; email.setAddress(s.text()); list.push_back(email); } contact->setEmailAddresses(list, preferredIndex); } if (!vcard.geo().empty()) { std::vector list; BOOST_FOREACH(const vcard_4_0::geoPropType &s, vcard.geo()) { double lon = 0.0; double lat = 0.0; if (fromGeoUri(s.uri(), lat, lon)) { list.push_back(Kolab::Geo(lat, lon)); } } contact->setGPSpos(list); } if (vcard.x_crypto()) { const vcard_4_0::vcard::x_crypto_type &crypto = *vcard.x_crypto(); Kolab::Crypto c; if (crypto.allowed()) { int allowed = 0; BOOST_FOREACH(const vcard_4_0::vcard::x_crypto_type::allowed_type::text_type &m, crypto.allowed()->text()) { if (m == vcard::x_crypto_type::allowed_type::text_type::PGP_INLINE) { allowed |= Kolab::Crypto::PGPinline; } else if (m == vcard::x_crypto_type::allowed_type::text_type::PGP_MIME) { allowed |= Kolab::Crypto::PGPmime; } else if (m == vcard::x_crypto_type::allowed_type::text_type::S_MIME) { allowed |= Kolab::Crypto::SMIME; } else if (m == vcard::x_crypto_type::allowed_type::text_type::S_MIMEOpaque) { allowed |= Kolab::Crypto::SMIMEopaque; } else { WARNING("unknown allowed property"); } } c.setAllowed(allowed); } if (crypto.encryptpref()) { c.setEncryptPref(toCryptoPref(crypto.encryptpref()->text())); } if (crypto.signpref()) { c.setSignPref(toCryptoPref(crypto.signpref()->text())); } contact->setCrypto(c); } if (!vcard.key().empty()) { std::string mimetype; std::vector keys; BOOST_FOREACH(const vcard_4_0::keyPropType &k, vcard.key()) { const std::string &key = uriInlineDecoding(k.uri(), mimetype); if (mimetype == MIME_PGP_KEYS) { keys.push_back(Kolab::Key(key, Kolab::Key::PGP)); } else if (mimetype == MIME_PKCS7_MIME) { keys.push_back(Kolab::Key(key, Kolab::Key::PKCS7_MIME)); } else { WARNING("wrong mimetype on key"); } } contact->setKeys(keys); } return contact; } template <> boost::shared_ptr readCard (const vcard_4_0::VcardsType::vcard_type &vcard) { using namespace vcard_4_0; boost::shared_ptr distlist(new Kolab::DistList); if (!vcard.member().empty()) { std::vector members; BOOST_FOREACH(const vcard_4_0::vcard::member_type & m, vcard.member()) { members.push_back(Shared::toContactReference(m.uri())); } distlist->setMembers(members); } return distlist; } template boost::shared_ptr deserializeCard(const std::string& s, bool isUrl) { clearErrors(); try { std::auto_ptr vcards; if (isUrl) { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseFile(s); if (doc.get()) { vcards = vcard_4_0::vcards(doc); } } else { xsd::cxx::xml::dom::auto_ptr doc = XMLParserWrapper::inst().parseString(s); if (doc.get()) { vcards = vcard_4_0::vcards(doc); } } if (!vcards.get()) { CRITICAL("failed to parse card!"); return boost::shared_ptr(); } boost::shared_ptr card = readCard(vcards->vcard()); card->setUid(Shared::fromURN(vcards->vcard().uid().uri())); card->setName(vcards->vcard().fn().text()); card->setLastModified(toDateTime(vcards->vcard().rev().timestamp())); setProductId( vcards->vcard().prodid().text() ); // setFormatVersion( vcards->vcard().version().text() ); // global_xCardVersion = vcalendar.properties().version().text(); setKolabVersion( vcards->vcard().x_kolab_version().text() ); if (!vcards->vcard().x_custom().empty()) { std::vector customProperties; BOOST_FOREACH(const vcard_4_0::CustomType &p, vcards->vcard().x_custom()) { customProperties.push_back(CustomProperty(p.identifier(), p.value())); } card->setCustomProperties(customProperties); } return card; } catch (const xml_schema::exception& e) { std::cerr << e << std::endl; } catch (...) { CRITICAL("Unhandled exception"); } CRITICAL("Failed to read vcard!"); return boost::shared_ptr(); } } } //Namespace #endif diff --git a/tests/conversiontest.cpp b/tests/conversiontest.cpp index 9affadc..6af4950 100644 --- a/tests/conversiontest.cpp +++ b/tests/conversiontest.cpp @@ -1,313 +1,313 @@ #include "conversiontest.h" #include #include #include #include #include "serializers.h" #include #include -Q_DECLARE_METATYPE(Kolab::Duration); -Q_DECLARE_METATYPE(Kolab::DayPos); -Q_DECLARE_METATYPE(Kolab::cDateTime); -Q_DECLARE_METATYPE(Kolab::ErrorSeverity); -Q_DECLARE_METATYPE(std::string); +Q_DECLARE_METATYPE(Kolab::Duration) +Q_DECLARE_METATYPE(Kolab::DayPos) +Q_DECLARE_METATYPE(Kolab::cDateTime) +Q_DECLARE_METATYPE(Kolab::ErrorSeverity) +Q_DECLARE_METATYPE(std::string) using namespace Kolab::XCAL; void ConversionTest::dateComparatorTest() { QVERIFY( !(Kolab::cDateTime(2001, 01, 02, 03, 04 ,05, false) == Kolab::cDateTime())); QVERIFY( Kolab::cDateTime(2001, 01, 02, 03, 04 ,05, false) == Kolab::cDateTime(2001, 01, 02, 03, 04 ,05, false)); } void ConversionTest::durationParserTest_data() { QTest::addColumn("expected"); QTest::addColumn("string"); QTest::newRow("Time") << Kolab::Duration(0,2,3,4, false) << "+PT2H3M4S"; QTest::newRow("Day") << Kolab::Duration(1,2,3,4, false) << "+P1DT2H3M4S"; QTest::newRow("Week") << Kolab::Duration(1, false) << "+P1W"; QTest::newRow("Week Multidigit, negative") << Kolab::Duration(23, true) << "-P23W"; Kolab::Utils::clearErrors(); } void ConversionTest::durationParserTest() { QFETCH(QString, string); QFETCH(Kolab::Duration, expected); const Kolab::Duration result = toDuration(string.toStdString()); QCOMPARE(result, expected); QCOMPARE(Kolab::Utils::getError(), Kolab::NoError); } void ConversionTest::durationSerializerTest_data() { QTest::addColumn("expected"); QTest::addColumn("duration"); QTest::newRow("Time") << "PT2H3M4S" << Kolab::Duration(0,2,3,4, false); QTest::newRow("Day") << "P1DT2H3M4S" << Kolab::Duration(1,2,3,4, false); QTest::newRow("Week positive") << "P1W" << Kolab::Duration(1, false); QTest::newRow("Week negative") << "-P3W" << Kolab::Duration(3, true); QTest::newRow("Week Multidigit, negative") << "-P23W" << Kolab::Duration(23, true); Kolab::Utils::clearErrors(); } void ConversionTest::durationSerializerTest() { QFETCH(Kolab::Duration, duration); QFETCH(QString, expected); const std::string result = fromDuration(duration); QCOMPARE(QString::fromStdString(result), expected); QCOMPARE(Kolab::Utils::getError(), Kolab::NoError); } void ConversionTest::dayPosParserTest_data() { QTest::addColumn("expected"); QTest::addColumn("string"); QTest::newRow("positive") << Kolab::DayPos(15, Kolab::Wednesday) << "15WE"; QTest::newRow("positive with +") << Kolab::DayPos(15, Kolab::Wednesday) << "+15WE"; QTest::newRow("negative") << Kolab::DayPos(-15, Kolab::Wednesday) << "-15WE"; QTest::newRow("all occurrences") << Kolab::DayPos(0, Kolab::Wednesday) << "WE"; Kolab::Utils::clearErrors(); } void ConversionTest::dayPosParserTest() { QFETCH(QString, string); QFETCH(Kolab::DayPos, expected); const Kolab::DayPos result = toDayPos(string.toStdString()); QCOMPARE(result, expected); QCOMPARE(Kolab::Utils::getError(), Kolab::NoError); } void ConversionTest::dayPosSerializerTest_data() { QTest::addColumn("expected"); QTest::addColumn("daypos"); QTest::newRow("pos") << "15WE" << Kolab::DayPos(15, Kolab::Wednesday); QTest::newRow("negative") << "-15WE" << Kolab::DayPos(-15, Kolab::Wednesday); QTest::newRow("all occurrences") << "WE" << Kolab::DayPos(0, Kolab::Wednesday); Kolab::Utils::clearErrors(); } void ConversionTest::dayPosSerializerTest() { QFETCH(Kolab::DayPos, daypos); QFETCH(QString, expected); const std::string result = fromDayPos(daypos); QCOMPARE(QString::fromStdString(result), expected); QCOMPARE(Kolab::Utils::getError(), Kolab::NoError); } void ConversionTest::xcardDateParserTest_data() { QTest::addColumn("input"); QTest::addColumn("expected"); QTest::addColumn("errorState"); QTest::newRow("datetime local") << "20010102T030405" << Kolab::cDateTime(2001, 01, 02, 03, 04 ,05, false) << Kolab::NoError; QTest::newRow("datetime utc") << "20010102T030405Z" << Kolab::cDateTime(2001, 01, 02, 03, 04 ,05, true) << Kolab::NoError; QTest::newRow("date only") << "20010102" << Kolab::cDateTime(2001, 01, 02) << Kolab::NoError; QTest::newRow("fail 1 short") << "20010102T03040" << Kolab::cDateTime() << Kolab::Error; QTest::newRow("fail non utc") << "20010102T030401s" << Kolab::cDateTime() << Kolab::Error; QTest::newRow("fail no time") << "20010102T" << Kolab::cDateTime() << Kolab::Error; Kolab::Utils::clearErrors(); } void ConversionTest::xcardDateParserTest() { QFETCH(QString, input); QFETCH(Kolab::cDateTime, expected); QFETCH(Kolab::ErrorSeverity, errorState); const Kolab::cDateTime &dt = Kolab::XCARD::toDateTime(input.toStdString()); QCOMPARE(dt, expected); QCOMPARE(Kolab::Utils::getError(), errorState); } void ConversionTest::xCardSerializerTest_data() { QTest::addColumn("expected"); QTest::addColumn("dt"); QTest::newRow("datetime local") << "20010102T030405" << Kolab::cDateTime(2001, 01, 02, 03, 04 ,05, false); QTest::newRow("datetime utc") << "20010102T030405Z" << Kolab::cDateTime(2001, 01, 02, 03, 04 ,05, true); QTest::newRow("dateonly") << "20010102" << Kolab::cDateTime(2001, 01, 02); Kolab::Utils::clearErrors(); } void ConversionTest::xCardSerializerTest() { QFETCH(QString, expected); QFETCH(Kolab::cDateTime, dt); const std::string &s = Kolab::XCARD::fromDateTime(dt); QCOMPARE(QString::fromStdString(s), expected); if (dt.isDateOnly()) { const std::string &s2 = Kolab::XCARD::fromDate(dt); QCOMPARE(QString::fromStdString(s2), expected); } QCOMPARE(Kolab::Utils::getError(), Kolab::NoError); } void ConversionTest::uriInlineEncodingTest() { const std::string &s = Kolab::Utils::uriInlineEncoding("data", "mimetype/mime"); QCOMPARE(s, std::string("data:mimetype/mime;base64,ZGF0YQ==")); std::string mimetype; const std::string &d = Kolab::Utils::uriInlineDecoding(s, mimetype); QCOMPARE(mimetype, std::string("mimetype/mime")); QCOMPARE(d, std::string("data")); QCOMPARE(Kolab::Utils::getError(), Kolab::NoError); } void ConversionTest::mailtoUriEncodingTest_data() { QTest::addColumn("email"); QTest::addColumn("name"); QTest::addColumn("resultEncoded"); //Older versions used to encode "." and "_". Not sure which version is actually required though (fixed in 7.26.0 but broken in 7.19.7, we're testing for 7.26.0) if (LIBCURL_VERSION_NUM >= 0x071a00) { QTest::newRow("1") << "email_1@email.com" << "John Doe" << "mailto:John%20Doe%3Cemail_1%40email.com%3E"; QTest::newRow("Reserved characters") << "!*'();:@&=+$,/?#[]@email.com" << "John Doe" << "mailto:John%20Doe%3C%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D%40email.com%3E"; QTest::newRow("Unreserved characters") << "Aa0-_.~@email.com" << "John Doe" << "mailto:John%20Doe%3CAa0-_.~%40email.com%3E"; } else { QTest::newRow("1") << "email_1@email.com" << "John Doe" << "mailto:John%20Doe%3Cemail%5F1%40email%2Ecom%3E"; QTest::newRow("Reserved characters") << "!*'();:@&=+$,/?#[]@email.com" << "John Doe" << "mailto:John%20Doe%3C%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%23%5B%5D%40email%2Ecom%3E"; QTest::newRow("Unreserved characters") << "Aa0-_.~@email.com" << "John Doe" << "mailto:John%20Doe%3CAa0%2D%5F%2E%7E%40email%2Ecom%3E"; } Kolab::Utils::clearErrors(); } void ConversionTest::mailtoUriEncodingTest() { QFETCH(QString, email); QFETCH(QString, name); QFETCH(QString, resultEncoded); const std::string &mailto = Kolab::XCARD::toMailto(email.toStdString(), name.toStdString()); // std::cout << mailto << std::endl; QCOMPARE(QString::fromStdString(mailto), resultEncoded); std::string n; const std::string &e = Kolab::XCARD::fromMailto(resultEncoded.toStdString(), n); QCOMPARE(QString::fromStdString(n), name); QCOMPARE(QString::fromStdString(e), email); } void ConversionTest::mailtoUriDecodingTest() { QString name("John Doe"); QString email("email_1@email.com"); //While we shouldn't encode '_' and '.' according to RFC 3986, we should still understand it for backwards compatiblity const std::string resultEncoded = "mailto:John%20Doe%3Cemail%5F1%40email%2Ecom%3E"; std::string n; const std::string &e = Kolab::XCARD::fromMailto(resultEncoded, n); QCOMPARE(QString::fromStdString(n), name); QCOMPARE(QString::fromStdString(e), email); } void ConversionTest::urnTest() { QCOMPARE(Kolab::Shared::toURN("1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000")); QCOMPARE(Kolab::Shared::toURN("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000")); QCOMPARE(Kolab::Shared::fromURN("urn:uuid:1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("1045b57d-ff7f-0000-d814-867b4d7f0000")); QCOMPARE(Kolab::Shared::fromURN("1045b57d-ff7f-0000-d814-867b4d7f0000"), std::string("1045b57d-ff7f-0000-d814-867b4d7f0000")); QCOMPARE(Kolab::Utils::getError(), Kolab::NoError); } void ConversionTest::geoUriTest() { QCOMPARE(Kolab::XCARD::toGeoUri(-34.056, 179.3453), std::string("geo:-34.056,179.3453")); QCOMPARE(Kolab::XCARD::toGeoUri(-34.1, 179.5), std::string("geo:-34.1,179.5")); QCOMPARE(Kolab::XCARD::toGeoUri(-34.0, 179.0), std::string("geo:-34,179")); QCOMPARE(Kolab::XCARD::toGeoUri(-34, 179), std::string("geo:-34,179")); QCOMPARE(Kolab::XCARD::toGeoUri(-34.012342356, 179.3451234553), std::string("geo:-34.012342356,179.3451234553")); double lat, lon; QVERIFY(Kolab::XCARD::fromGeoUri(std::string("geo:-34.056,179.3453"), lat, lon)); QCOMPARE(lat, -34.056); QCOMPARE(lon, 179.3453); QCOMPARE(Kolab::Utils::getError(), Kolab::NoError); } void ConversionTest::contactReferenceTest() { Kolab::ContactReference email(Kolab::ContactReference::EmailReference, "mail", "name"); QCOMPARE(Kolab::Shared::toMailto(email.email(), email.name()), std::string("mailto:name%3Cmail%3E")); Kolab::ContactReference urn(Kolab::ContactReference::UidReference, "urn"); QCOMPARE(Kolab::Shared::toURN(urn.uid()), std::string("urn:uuid:urn")); QCOMPARE(Kolab::Shared::toContactReference("urn:uuid:urn"), urn); QCOMPARE(Kolab::Shared::toContactReference("mailto:name%3Cmail%3E"), email); } void threadF() { for (int i = 0; i < 5; ++i) { std::stringstream s; // s << boost::this_thread::get_id(); std::string uid = s.str(); // std::cout << uid << std::endl; Kolab::Utils::setCreatedUid(uid); boost::this_thread::sleep(boost::posix_time::millisec(50)); QCOMPARE(Kolab::Utils::createdUid(), uid); } } void ConversionTest::threadLocalTest() { //Ensure global variables are not mixed between threads and therefore threadsafe. boost::thread t(threadF); boost::thread t2(threadF); t.join(); t2.join(); } void ConversionTest::uuidGeneratorTest() { const std::string &s = getUID(); // std::cout << s << std::endl; QVERIFY(!s.empty()); QCOMPARE(s.size(), (std::size_t)36ul); //Ensure we don't get the same uuid twice const std::string &s2 = getUID(); QVERIFY(s != s2); } void ConversionTest::uuidGeneratorTest2() { Kolab::Event event; event.setStart(Kolab::cDateTime(2001, 01, 02, 03, 04 ,05, false)); QVERIFY(Kolab::getSerializedUID().empty()); Kolab::writeEvent(event); std::string uid1 = Kolab::getSerializedUID(); QVERIFY(!uid1.empty()); Kolab::writeEvent(event); std::string uid2 = Kolab::getSerializedUID(); std::cout << uid1 << uid2; QVERIFY(!uid2.empty()); QVERIFY(uid1 != uid2); } QTEST_MAIN( ConversionTest ) #include "conversiontest.moc"