Page MenuHomePhorge

No OneTemporary

Authored By
Unknown
Size
136 KB
Referenced Files
None
Subscribers
None
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d007252..ac07b71 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,138 +1,155 @@
project(libkolabxml)
+
cmake_minimum_required(VERSION 2.6)
# only available from cmake-2.8.0
if(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 7)
cmake_policy(SET CMP0012 NEW)
endif()
# only available from cmake-2.8.4
if(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 7 AND
${CMAKE_PATCH_VERSION} GREATER 3)
cmake_policy(SET CMP0017 NEW)
endif()
+set (KOLABXML_VERSION_MAJOR 0)
+set (KOLABXML_VERSION_MINOR 3)
+set (KOLABXML_VERSION_RELEASE 0)
+set (KOLABXML_VERSION "${KOLABXML_VERSION_MAJOR}.${KOLABXML_VERSION_MINOR}.${KOLABXML_VERSION_RELEASE}" )
+set (KOLABXML_VERSION_STRING ${CMAKE_PROJECT_NAME}-${KOLABXML_VERSION})
+set (KOLAB_FORMAT_VERSION "3.0dev1")
+
+configure_file(libkolabxml-version.h.cmake "${CMAKE_BINARY_DIR}/libkolabxml-version.h" @ONLY)
+
+
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
include( cmake/modules/FindKolabInternal.cmake )
add_subdirectory(cmake/modules)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost REQUIRED COMPONENTS thread)
if (Boost_FOUND)
message("Found boost in ${Boost_INCLUDE_DIRS}")
include_directories(${Boost_INCLUDE_DIRS})
endif (Boost_FOUND)
if (${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.42)
find_library(UUID NAMES ossp-uuid)
if(UUID)
message("uuid found")
else (UUID)
message(FATAL_ERROR "uuid NOT found!")
endif(UUID)
endif()
find_package(Qt4)
find_program( XSDCXX xsdcxx /usr/bin/)
if(XSDCXX)
message("xsd code generator found")
else (XSDCXX)
message(FATAL_ERROR
"xsd code generator NOT found!")
endif(XSDCXX)
find_library(XERCES_C NAMES xerces-c xerces-c_2)
if(XERCES_C)
message("xerces found")
else (XERCES_C)
message(FATAL_ERROR
"xerces NOT found!")
endif(XERCES_C)
find_program(SWIG swig /usr/bin/)
if(SWIG)
set(SWIG_FOUND ON)
message("SWIG found")
endif(SWIG)
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall" )
# set( CMAKE_VERBOSE_MAKEFILE on )
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_BUILD_DIR ${CMAKE_SOURCE_DIR}/build)
file(MAKE_DIRECTORY ${CMAKE_BUILD_DIR}/bindings)
set( SCHEMA_DIR ${CMAKE_SOURCE_DIR}/schemas )
# Generate bindings
set( SCHEMAS
${SCHEMA_DIR}/ical/kolabformat-xcal.xsd
${SCHEMA_DIR}/ical/iCalendar-params.xsd
${SCHEMA_DIR}/ical/iCalendar-props.xsd
${SCHEMA_DIR}/ical/iCalendar-valtypes.xsd
${SCHEMA_DIR}/xCard.xsd
${SCHEMA_DIR}/kolabformat-xcard.xsd
${SCHEMA_DIR}/kolabformat.xsd
)
set( SCHEMA_SOURCEFILES
${CMAKE_BUILD_DIR}/bindings/kolabformat.cxx
${CMAKE_BUILD_DIR}/bindings/xCard.cxx
${CMAKE_BUILD_DIR}/bindings/kolabformat-xcal.cxx
${CMAKE_BUILD_DIR}/bindings/kolabformat-xcard.cxx
${CMAKE_BUILD_DIR}/bindings/iCalendar-params.cxx
${CMAKE_BUILD_DIR}/bindings/iCalendar-props.cxx
${CMAKE_BUILD_DIR}/bindings/iCalendar-valtypes.cxx
# bindings/iCalendar-link-extension.cxx
# bindings/iCalendar-bw-extensions.cxx
# bindings/iCalendar-ms-extensions.cxx
)
#xsdcxx cxx-tree --generate-xml-schema --generate-serialization --custom-type date_time --hxx-epilogue '#include "bindings/customtypes/xml-schema-custom.hxx"' xml-schema.xsd
# --generate-inline --extern-xml-schema xml-schema.xsd
# --cxx-suffix .cpp --hxx-suffix .h
add_custom_command(OUTPUT ${SCHEMA_SOURCEFILES}
COMMAND ${XSDCXX} cxx-tree --generate-polymorphic --generate-serialization --namespace-map http://kolab.org=KolabXSD --root-element icalendar --root-element vcards --root-element note --output-dir ${CMAKE_BUILD_DIR}/bindings ${SCHEMAS}
COMMENT "Generating XSD bindings"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
DEPENDS ${SCHEMAS}
VERBATIM
)
# Compile Schemas
add_executable(xsdbin compiled/xsdbin.cxx)
target_link_libraries(xsdbin ${XERCES_C})
add_custom_command(OUTPUT kolabformat-xcal-schema.cxx
COMMAND ${CMAKE_BUILD_DIR}/xsdbin --verbose --array-name iCalendar_schema --output-dir ${CMAKE_BUILD_DIR} ${SCHEMAS}
COMMENT "Compiling Kolab XSD schema"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
DEPENDS ${SCHEMAS} xsdbin
VERBATIM
)
set( SCHEMA_SOURCEFILES ${SCHEMA_SOURCEFILES} ${CMAKE_BUILD_DIR}/kolabformat-xcal-schema.cxx)
# ---------
SET_SOURCE_FILES_PROPERTIES(${SCHEMA_SOURCEFILES} PROPERTIES GENERATED 1)
ADD_CUSTOM_TARGET(generate_bindings ALL DEPENDS ${SCHEMA_SOURCEFILES})
include_directories( ./ )
include_directories( compiled )
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
add_subdirectory(src)
if (QT4_FOUND)
add_subdirectory(tests)
else()
message("Qt libraries have not been found, not building tests")
endif()
+set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${KOLABXML_VERSION})
+#make dist requires a tag with ${ARCHIVE_NAME} (e.g. libkolabxml-0.2.0)
+add_custom_target(dist
+ COMMAND git archive --prefix=${ARCHIVE_NAME}/ ${ARCHIVE_NAME}
+ | bzip2 > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
diff --git a/libkolabxml-version.h.cmake b/libkolabxml-version.h.cmake
new file mode 100644
index 0000000..d91e377
--- /dev/null
+++ b/libkolabxml-version.h.cmake
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2012 Christian Mollekopf <mollekopf@kolabsys.com>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBKOLABXML_VERSION_H
+#define LIBKOLABXML_VERSION_H
+
+#define KOLAB_LIBNAME "@CMAKE_PROJECT_NAME@"
+#define KOLAB_LIB_VERSION "@KOLABXML_VERSION@"
+#define KOLAB_LIB_VERSION_STRING "@KOLABXML_VERSION_STRING@"
+#define KOLAB_FORMAT_VERSION "@KOLAB_FORMAT_VERSION@"
+
+#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cedf061..cc6c0ed 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,52 +1,52 @@
SET_SOURCE_FILES_PROPERTIES(${SCHEMA_SOURCEFILES} PROPERTIES GENERATED 1)
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wp,-D_FORTIFY_SOURCE=2 -O2" ) #always generate shared libraries with -fPIC, -D_FORTIFY_SOURCE=2 enables some extra checking
#Library with serialization/deserialization code and kolab-containers
add_library(kolabxml SHARED kolabformat.cpp kolabcontainers.cpp kolabnote.cpp kolabevent.cpp kolabtodo.cpp kolabjournal.cpp kolabcontact.cpp utils.cpp base64.cpp ../compiled/XMLParserWrapper.cpp ../compiled/grammar-input-stream.cxx ${SCHEMA_SOURCEFILES})
add_dependencies(kolabxml generate_bindings)
target_link_libraries(kolabxml ${XERCES_C} ${Boost_LIBRARIES} ${UUID})
#For the core library we can be stricter when compiling. This doesn't work with the auto generated code though.
set_target_properties(kolabxml PROPERTIES COMPILE_FLAGS "-Wall -Wextra -Werror -Wfatal-errors -Wl,--no-undefined")
-set_target_properties(kolabxml PROPERTIES VERSION 3.0.0 SOVERSION 0)
+set_target_properties(kolabxml PROPERTIES VERSION ${KOLABXML_VERSION} SOVERSION 0)
install(TARGETS kolabxml ${KOLAB_INSTALL_DIRECTORIES})
install( FILES
kolabformat.h
kolabevent.h
kolabtodo.h
kolabjournal.h
kolabcontact.h
kolabnote.h
kolabcontainers.h
global_definitions.h
DESTINATION ${KOLAB_HEADER_INSTALL_DIR} COMPONENT Devel)
#----- The following makes sure libkolabxml is found in the install directory for installed files and not in the build directory (for libraries which link to libkolabxml)
# use, i.e. don't skip the full RPATH for the build tree
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
# when building, don't use the install RPATH already(but later on when installing)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
SET(CMAKE_INSTALL_RPATH "${KOLAB_LIB_INSTALL_DIR}")
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
# the RPATH to be used when installing, but only if it's not a system directory
LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${KOLAB_LIB_INSTALL_DIR}" isSystemDir)
IF("${isSystemDir}" STREQUAL "-1")
SET(CMAKE_INSTALL_RPATH "${KOLAB_LIB_INSTALL_DIR}")
ENDIF("${isSystemDir}" STREQUAL "-1")
#-----------------------SWIG--------------------
if (SWIG_FOUND)
add_subdirectory(python)
add_subdirectory(php)
else()
message(WARNING "Could not build SWIG bindings, because SWIG is missing.")
endif()
diff --git a/src/global_definitions.h b/src/global_definitions.h
index 2aa36e8..0860843 100644
--- a/src/global_definitions.h
+++ b/src/global_definitions.h
@@ -1,37 +1,34 @@
/*
* Copyright (C) 2011 Christian Mollekopf <mollekopf@kolabsys.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef GLOBAL_DEFINITIONS_H
#define GLOBAL_DEFINITIONS_H
#include <string>
+#include "libkolabxml-version.h"
namespace Kolab {
-const char* const KOLAB_LIBNAME = "libkolabxml";
-const char* const KOLAB_LIB_VERSION = "0.1";
-const char* const KOLAB_FORMAT_VERSION = "3.0dev1";
-
enum ErrorSeverity {
NoError,
Warning, //Warning, error could be corrected, object can be used without dataloss
Error, //Potentially corrupt object, writing the object back could result in dataloss. (Object could still be used to display the data readonly).
Critical //Ciritcal error, produced object cannot be used and should be thrown away (writing back will result in dataloss).
};
}
#endif
diff --git a/src/kolabconversions.h b/src/kolabconversions.h
index 4871acd..cca2775 100644
--- a/src/kolabconversions.h
+++ b/src/kolabconversions.h
@@ -1,181 +1,181 @@
/*
* Copyright (C) 2012 Christian Mollekopf <mollekopf@kolabsys.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KOLABOBJECTCONVERSION_H
#define KOLABOBJECTCONVERSION_H
#include <bindings/kolabformat.hxx>
#include "kolabcontainers.h"
#include <XMLParserWrapper.h>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include "global_definitions.h"
#include "utils.h"
#include "kolabnote.h"
#include "shared_conversions.h"
namespace Kolab {
namespace KolabObjects {
const char* const KOLAB_NAMESPACE = "http://kolab.org";
using namespace Kolab::Utils;
using namespace Kolab::Shared;
template <typename T>
std::string serializeObject(const Kolab::Note &note, const std::string prod = std::string())
{
clearErrors();
try {
const std::string &uid = getUID(note.uid());
setCreatedUid(uid);
KolabXSD::Note::creation_date_type created = fromDateTime(note.created());
if (!note.created().isValid()) {
created = fromDateTime(getCurrentTime());
}
- KolabXSD::Note n(getUID(note.uid()), prod+KOLAB_LIBNAME+KOLAB_LIB_VERSION, created, fromDateTime(getCurrentTime()));
+ KolabXSD::Note n(getUID(note.uid()), prod+KOLAB_LIB_VERSION_STRING, created, fromDateTime(getCurrentTime()));
if (!note.categories().empty()) {
KolabXSD::Note::categories_sequence categories;
BOOST_FOREACH(const std::string &c, note.categories()) {
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");
}
//TODO
// n.attachment();
n.summary(note.summary());
n.description(note.description());
n.color(note.color());
if (!note.customProperties().empty()) {
BOOST_FOREACH(const Kolab::CustomProperty &a, note.customProperties()) {
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) {
CRITICAL("Unknown Exception: failed to write Note");
}
return std::string();
}
template <typename T>
boost::shared_ptr<Kolab::Note> deserializeObject(const std::string& s, bool isUrl)
{
clearErrors();
try {
std::auto_ptr<KolabXSD::Note> note;
if (isUrl) {
xsd::cxx::xml::dom::auto_ptr <xercesc::DOMDocument > doc = XMLParserWrapper::inst().parseFile(s);
if (doc.get()) {
note = KolabXSD::note(doc);
}
} else {
xsd::cxx::xml::dom::auto_ptr <xercesc::DOMDocument > doc = XMLParserWrapper::inst().parseString(s);
if (doc.get()) {
note = KolabXSD::note(doc);
}
}
if (!note.get()) {
CRITICAL("failed to parse note!");
return boost::shared_ptr<Kolab::Note>();
}
boost::shared_ptr<Kolab::Note> n = boost::shared_ptr<Kolab::Note>(new Kolab::Note);
n->setUid(note->uid());
n->setCreated(*toDate(note->creation_date()));
n->setLastModified(*toDate(note->last_modification_date()));
std::vector<std::string> 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");
}
}
//TODO
// n->setAttachments();
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<Kolab::CustomProperty> 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;
CRITICAL("Failed to read note!");
}
return boost::shared_ptr<T>();
}
}//Namespace
} //Namespace
#endif
diff --git a/src/xcalconversions.h b/src/xcalconversions.h
index 601acea..3829cc9 100644
--- a/src/xcalconversions.h
+++ b/src/xcalconversions.h
@@ -1,1701 +1,1701 @@
/*
* Copyright (C) 2011 Christian Mollekopf <mollekopf@kolabsys.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XCALCONVERSIONS_H
#define XCALCONVERSIONS_H
#include "global_definitions.h"
#include <bindings/kolabformat-xcal.hxx>
#include <bindings/iCalendar-props.hxx>
#include <compiled/XMLParserWrapper.h>
#include <boost/shared_ptr.hpp>
#include <boost/numeric/conversion/converter_policies.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <boost/foreach.hpp>
#include <fstream>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include "kolabcontainers.h"
#include "kolabtodo.h"
#include "kolabevent.h"
#include "kolabjournal.h"
#include "utils.h"
#include "base64.h"
#include "shared_conversions.h"
namespace Kolab {
namespace XCAL {
std::string global_xCalVersion;
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 = "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 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";
//Alarms
const char* const START = "START";
const char* const END = "END";
using namespace Kolab::Utils;
using namespace Kolab::Shared;
//=== Generic Conversions ===
int toInt(const icalendar_2_0::IntegerPropertyType &prop)
{
return convertToInt<icalendar_2_0::IntegerPropertyType::integer_type>(prop.integer());
}
std::vector<std::string> toStringList(const icalendar_2_0::TextListPropertyType &s)
{
std::vector<std::string> d;
std::copy(s.text().begin(), s.text().end(), std::back_inserter(d));
return d;
}
template <typename T>
std::auto_ptr<T> fromStringList(const std::vector<std::string> &list)
{
std::auto_ptr<T> 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<std::string>(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<int>(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<std::string>(d.weeks()));
s.push_back('W');
}
if (d.days() > 0) {
s.append(boost::lexical_cast<std::string>(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<std::string>(d.hours()));
s.push_back('H');
}
if (d.minutes() > 0) {
s.append(boost::lexical_cast<std::string>(d.minutes()));
s.push_back('M');
}
if (d.seconds() > 0) {
s.append(boost::lexical_cast<std::string>(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<int>(number);
} catch(boost::bad_lexical_cast &) {
ERROR("failed to convert: " + number);
return Duration();
}
number.clear();
break;
case 'M':
try {
minutes = boost::lexical_cast<int>(number);
} catch(boost::bad_lexical_cast &) {
ERROR("failed to convert: " + number);
return Duration();
}
number.clear();
break;
case 'S':
try {
seconds = boost::lexical_cast<int>(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<int>(number);
} catch(boost::bad_lexical_cast &) {
ERROR("failed to convert: " + number);
return Duration();
}
return Duration(weeks, negative);
case 'D':
try {
days = boost::lexical_cast<int>(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:
ERROR("failed to convert duration: " + *it);
return Duration();
}
}
return Duration(days, hours, minutes, seconds, negative);
}
template <typename T>
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<const icalendar_2_0::CnParamType*> (&*it)) {
name = tz->text();
continue;
}
if (const icalendar_2_0::DirParamType * tz = dynamic_cast<const icalendar_2_0::DirParamType*> (&*it)) {
uid = tz->uri();
continue;
}
}
}
return Kolab::ContactReference(email, name, uid);
}
template <typename T>
Kolab::Attachment toAttachment(T aProp)
{
Kolab::Attachment a;
std::string mimetype;
if (aProp.parameters()) {
const icalendar_2_0::AttachPropType ::parameters_type &parameters = *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<const icalendar_2_0::FmttypeParamType*> (&*it)) {
mimetype = p->text();
}
if (const icalendar_2_0::EncodingParamType *p = dynamic_cast<const icalendar_2_0::EncodingParamType*> (&*it)) {
if (p->text() != BASE64) {
ERROR("wrong encoding");
return Kolab::Attachment();
}
}
if (const icalendar_2_0::XlabelParamType *p = dynamic_cast<const icalendar_2_0::XlabelParamType*> (&*it)) {
a.setLabel(p->text());
}
}
}
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;
}
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<const unsigned char*>(a.data().c_str()), 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 &parameters) {
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<const icalendar_2_0::TzidParamType*> (&*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 <typename I>
std::auto_ptr<I> fromDate(const cDateTime &dt)
{
std::auto_ptr<I> 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 <typename I>
std::vector<cDateTime> toDateTimeList(I datelistProperty)
{
std::vector<cDateTime> 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 <typename I>
std::auto_ptr<I> fromDateTimeList(const std::vector<cDateTime> &dtlist)
{
std::auto_ptr<I> 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
//TODO check for equality of timezones?
}
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;
}
ERROR("PartStat not handled: " + status);
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;
}
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;
}
ERROR("PartStat not handled: " + status);
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 Role " + status);
return Required;
}
//----------------
//=== Recurrence Rule ===
typedef std::auto_ptr<RecurrenceRule> 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");
}
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<DayPos> 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 <typename T, typename I>
std::vector<int> bylist(const xsd::cxx::tree::sequence <T> &list)
{
std::vector<int> by;
BOOST_FOREACH(const T i, list) {
by.push_back(convertToInt<I>(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<RecurType::bysecond_type, xml_schema::non_negative_integer>(rrule.bysecond()));
r->setByminute(bylist<RecurType::byminute_type, xml_schema::non_negative_integer>(rrule.byminute()));
r->setByhour(bylist<RecurType::byhour_type, xml_schema::non_negative_integer>(rrule.byhour()));
setByday(r, rrule.byday());
r->setBymonthday(bylist<RecurType::bymonthday_type, xml_schema::integer>(rrule.bymonthday()));
r->setByyearday(bylist<RecurType::byyearday_type, xml_schema::integer>(rrule.byyearday()));
r->setByweekno(bylist<RecurType::byweekno_type, xml_schema::integer>(rrule.byweekno()));
r->setBymonth(bylist<RecurType::bymonth_type, xml_schema::integer>(rrule.bymonth()));
if (rrule.wkst()) {
setWeekStart(r, *rrule.wkst());
}
return r;
}
//--- Recurrence Rule ---
template <typename I, typename T>
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.status()) {
const std::string &status = toString(*prop.status());
if (status == NEEDSACTION) {
inc.setStatus(StatusNeedsAction);
} else if (status == COMPLETED) {
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<Kolab::Attendee> 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 &parameters = *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<const icalendar_2_0::CnParamType*> (&*it)) {
name = p->text();
}
if (const icalendar_2_0::PartstatParamType * p = dynamic_cast<const icalendar_2_0::PartstatParamType*> (&*it)) {
PartStatus s = mapPartStat(p->text());
if (s != PartNeedsAction) {
a.setPartStat(s);
}
}
if (const icalendar_2_0::RoleParamType * p = dynamic_cast<const icalendar_2_0::RoleParamType*> (&*it)) {
Role s = mapRole(p->text());
if (s != Required) {
a.setRole(s);
}
}
if (const icalendar_2_0::RsvpParamType * p = dynamic_cast<const icalendar_2_0::RsvpParamType*> (&*it)) {
a.setRSVP(p->boolean());
}
}
}
Kolab::ContactReference ref = toContactReference(aProp);
a.setContact(ref);
attendees.push_back(a);
}
inc.setAttendees(attendees);
}
if (prop.attach().size()) {
std::vector<Kolab::Attachment> attachments;
BOOST_FOREACH(typename T::attach_type aProp, prop.attach()) {
const Kolab::Attachment &a = toAttachment<typename T::attach_type>(aProp);
if (!a.isValid()) {
ERROR("invalid attachment");
continue;
}
attachments.push_back(a);
}
inc.setAttachments(attachments);
}
if (prop.x_custom().size()) {
std::vector<Kolab::CustomProperty> customProperties;
BOOST_FOREACH(typename T::x_custom_type p, prop.x_custom()) {
customProperties.push_back(CustomProperty(p.identifier(), p.value()));
}
inc.setCustomProperties(customProperties);
}
}
template <typename I, typename T>
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<icalendar_2_0::KolabEvent::properties_type::rdate_type>(*prop.rdate()));
if (!prop.rdate()->period().empty()) {
ERROR("the period element must not be used, ignored.");
}
}
if (prop.exdate()) {
inc.setExceptionDates(toDateTimeList<icalendar_2_0::KolabEvent::properties_type::exdate_type>(*prop.exdate()));
}
if (prop.recurrence_id()) {
bool thisandfuture = false;
if (prop.recurrence_id()->parameters()) {
const icalendar_2_0::RecurrenceIdPropType::parameters_type &parameters = *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<const icalendar_2_0::RangeParamType*> (&*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()));
}
}
template <typename T, typename I>
T fromList(const std::vector<int> &input) {
T list;
BOOST_FOREACH(int i, input) {
list.push_back(convertToInt<I>(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<RecurType::count_type>(r.count()));
}
if (r.interval() > 1) {
recur.interval(fromInt<RecurType::interval_type>(r.interval()));
}
if (!r.bysecond().empty()) {
recur.bysecond(fromList<RecurType::bysecond_sequence, xml_schema::non_negative_integer>(r.bysecond()));
}
if (!r.byminute().empty()) {
recur.byminute(fromList<RecurType::byminute_sequence, xml_schema::non_negative_integer>(r.byminute()));
}
if (!r.byhour().empty()) {
recur.byhour(fromList<RecurType::byhour_sequence, xml_schema::non_negative_integer>(r.byhour()));
}
if (!r.byday().empty()) {
RecurType::byday_sequence byday;
BOOST_FOREACH(const Kolab::DayPos &daypos, r.byday()) {
byday.push_back(fromDayPos(daypos));
}
recur.byday(byday);
}
if (!r.bymonthday().empty()) {
recur.bymonthday(fromList<RecurType::bymonthday_sequence, xml_schema::integer>(r.bymonthday()));
}
if (!r.byyearday().empty()) {
recur.byyearday(fromList<RecurType::byyearday_sequence, xml_schema::integer>(r.byyearday()));
}
if (!r.byweekno().empty()) {
recur.byweekno(fromList<RecurType::byweekno_sequence, xml_schema::integer>(r.byweekno()));
}
if (!r.bymonth().empty()) {
recur.bymonth(fromList<RecurType::bymonth_sequence, xml_schema::integer>(r.bymonth()));
}
return rruleProp;
}
template <typename T, typename I>
void getIncidenceProperties(T &prop, const I &inc)
{
using namespace icalendar_2_0;
typedef T properties;
prop.sequence(fromInt<xml_schema::integer>(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:
prop.class_(typename properties::class_type(PUBLIC));
break;
}
if (!inc.categories().empty()) {
prop.categories(*fromStringList<typename properties::categories_type>(inc.categories()));
}
if (inc.start().isValid()) {
prop.dtstart(fromDate<typename properties::dtstart_type>(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.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:
ERROR("unhandled status " + inc.status());
}
}
if (!inc.attendees().empty()) {
BOOST_FOREACH(const Kolab::Attendee &a, inc.attendees()) {
const Kolab::ContactReference &c = a.contact();
typename properties::attendee_type attendee = fromContactReference<typename properties::attendee_type>(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));
}
prop.attendee().push_back(attendee);
}
}
if (!inc.attachments().empty()) {
BOOST_FOREACH(const Kolab::Attachment &a, inc.attachments()) {
prop.attach().push_back(fromAttachment(a));
}
}
if (!inc.customProperties().empty()) {
BOOST_FOREACH(const Kolab::CustomProperty &a, inc.customProperties()) {
prop.x_custom().push_back(typename properties::x_custom_type(a.identifier, a.value));
}
}
}
template <typename T, typename I>
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<typename properties::rdate_type>(inc.recurrenceDates()));
}
if (!inc.exceptionDates().empty()) {
prop.exdate(fromDateTimeList<typename properties::exdate_type>(inc.exceptionDates()));
}
if (inc.recurrenceID().isValid()) {
std::auto_ptr<typename properties::recurrence_id_type> recurrenceId = fromDate<typename properties::recurrence_id_type>(inc.recurrenceID());
if (inc.thisAndFuture()) {
if (!recurrenceId->parameters()) {
recurrenceId->parameters(typename properties::recurrence_id_type::parameters_type());
}
typename properties::recurrence_id_type::parameters_type &parameters = *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<typename properties::priority_type::integer_type>(inc.priority())));
}
if (!inc.location().empty()) {
prop.location(typename properties::location_type(inc.location()));
}
if (inc.organizer().isValid()) {
prop.organizer(fromContactReference<typename properties::organizer_type>(inc.organizer()));
}
}
//=== Alarms ===
template <typename KolabType, typename IncidenceType>
void setAlarms(typename KolabType::components_type& components, const IncidenceType &incidence)
{
BOOST_FOREACH(const Kolab::Alarm &alarm, incidence.alarms()) {
typedef icalendar_2_0::ValarmType::properties_type PropType;
PropType::trigger_type trigger;
if (alarm.start().isValid()) {
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<PropType> p;
switch(alarm.type()) {
case Kolab::Alarm::DisplayAlarm:
p = std::auto_ptr<PropType>(new PropType(PropType::action_type(DISPLAYALARM), trigger));
p->description(PropType::description_type(alarm.description()));
break;
case Kolab::Alarm::EMailAlarm:
p = std::auto_ptr<PropType>(new PropType(PropType::action_type(EMAILALARM), trigger));
p->summary(PropType::summary_type(alarm.summary()));
p->description(PropType::description_type(alarm.description()));
BOOST_FOREACH(const Kolab::ContactReference &attendee, alarm.attendees()) {
p->attendee().push_back(icalendar_2_0::ContactType(toMailto(attendee.email(), attendee.name())));
}
break;
case Kolab::Alarm::AudioAlarm:
p = std::auto_ptr<PropType>(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;
}
if (alarm.duration().isValid()) {
p->duration(PropType::duration_type(fromDuration(alarm.duration())));
p->repeat(PropType::repeat_type(fromInt<PropType::repeat_type::integer_type>(alarm.numrepeat())));
}
components.valarm().push_back(icalendar_2_0::ValarmType(p));
}
}
template <typename IncidenceType, typename KolabType>
void getAlarms(IncidenceType &incidence, const typename KolabType::components_type &components)
{
typedef icalendar_2_0::ValarmType::properties_type PropType;
std::vector<Kolab::Alarm> 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<Kolab::ContactReference> 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<icalendar_2_0::properties::attach_type>(*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 &param, (*prop.trigger().parameters()).baseParameter()) {
if (const icalendar_2_0::RelatedParamType *rel = dynamic_cast<const icalendar_2_0::RelatedParamType*> (&param)) {
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 ---
class Incidence; //Just for Trait
///Trait for Incidence object
template <typename T, typename I>
struct IncidenceConverter;
template <typename T> struct IncidenceConverter < Incidence, T >
{
static std::string uid(const T &inc) {
if (inc.uid().empty()) { //generate new UID
return getUID();
}
return inc.uid();
}
static xml_schema::date_time dtstamp() {
return fromDateTime(getCurrentTime());
}
static xml_schema::date_time created(const T &inc) {
if (inc.created().isValid()) {
return fromDateTime(inc.created());
}
return fromDateTime(getCurrentTime());
}
};
///Trait for incidence properties specialized for Event/Todo/Journal
template <typename T> struct IncidenceTrait;
template < > struct IncidenceTrait <Kolab::Event>
{
typedef icalendar_2_0::KolabEvent KolabType;
typedef Kolab::Event IncidenceType;
typedef boost::shared_ptr<Kolab::Event> IncidencePtr;
static void writeIncidence(icalendar_2_0::KolabEvent& vevent, const Kolab::Event &event)
{
KolabType::components_type eventComponents;
setAlarms<icalendar_2_0::KolabEvent, IncidenceType>(eventComponents, event);
if (!eventComponents.valarm().empty()) {
vevent.components(eventComponents);
}
icalendar_2_0::KolabEvent::properties_type &prop = vevent.properties();
getIncidenceProperties<icalendar_2_0::KolabEvent::properties_type>(prop, event);
getTodoEventProperties<icalendar_2_0::KolabEvent::properties_type>(prop, event);
if (!event.start().isValid()) {
ERROR("Start date is missing, but is mandatory for events");
}
if (event.end().isValid()) {
prop.dtend(fromDate<icalendar_2_0::KolabEvent::properties_type::dtend_type>(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<Kolab::Event, icalendar_2_0::KolabEvent::properties_type>(event, prop);
setTodoEventProperties<Kolab::Event, icalendar_2_0::KolabEvent::properties_type>(event, prop);
if (prop.dtend()) {
event.setEnd(*toDate(*prop.dtend()));
if (event.end().isUTC() != event.end().isUTC() &&
event.end().timezone() != event.end().timezone() &&
event.end().isDateOnly() != event.end().isDateOnly()) {
ERROR("dtEnd has wrong timespec");
}
} 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<Kolab::Event, icalendar_2_0::KolabEvent>(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();
}
};
template < > struct IncidenceTrait <Kolab::Todo>
{
typedef icalendar_2_0::KolabTodo KolabType;
typedef Kolab::Todo IncidenceType;
typedef boost::shared_ptr<Kolab::Todo> IncidencePtr;
static void writeIncidence(icalendar_2_0::KolabTodo& vevent, const Kolab::Todo &todo)
{
KolabType::components_type eventComponents;
setAlarms<icalendar_2_0::KolabTodo, IncidenceType>(eventComponents, todo);
if (!eventComponents.valarm().empty()) {
vevent.components(eventComponents);
}
icalendar_2_0::KolabTodo::properties_type &prop = vevent.properties();
getIncidenceProperties<icalendar_2_0::KolabTodo::properties_type>(prop, todo);
getTodoEventProperties<icalendar_2_0::KolabTodo::properties_type>(prop, todo);
if (!todo.relatedTo().empty()) {
icalendar_2_0::KolabTodo::properties_type::related_to_sequence list;
BOOST_FOREACH(std::string relatedTo, todo.relatedTo()) {
list.push_back(icalendar_2_0::KolabTodo::properties_type::related_to_type(relatedTo));
}
prop.related_to(list);
}
if (todo.due().isValid()) {
prop.due(fromDate<icalendar_2_0::KolabTodo::properties_type::due_type>(todo.due()));
}
if (todo.percentComplete() > 0) {
prop.percent_complete(icalendar_2_0::KolabTodo::properties_type::percent_complete_type(fromInt<icalendar_2_0::IntegerPropertyType::integer_type>(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<Kolab::Todo, icalendar_2_0::KolabTodo::properties_type>(todo, prop);
setTodoEventProperties<Kolab::Todo, icalendar_2_0::KolabTodo::properties_type>(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<Kolab::Todo, icalendar_2_0::KolabTodo>(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();
}
};
template < > struct IncidenceTrait <Kolab::Journal>
{
typedef icalendar_2_0::KolabJournal KolabType;
typedef Kolab::Journal IncidenceType;
typedef boost::shared_ptr<Kolab::Journal> IncidencePtr;
static void writeIncidence(icalendar_2_0::KolabJournal& vjournal, const Kolab::Journal &journal)
{
icalendar_2_0::KolabJournal::properties_type &prop = vjournal.properties();
getIncidenceProperties<icalendar_2_0::KolabJournal::properties_type>(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<Kolab::Journal, icalendar_2_0::KolabJournal::properties_type>(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();
}
};
//////////////////////////////////=========================================
template <typename T>
std::string serializeIncidence(const typename T::IncidenceType &incidence, const std::string productid = std::string()) {
using namespace icalendar_2_0;
typedef IncidenceConverter< Incidence, typename T::IncidenceType > IC;
typedef typename T::KolabType KolabType;
clearErrors();
try {
typename KolabType::properties_type::uid_type uid(IC::uid(incidence));
setCreatedUid(uid.text());
typename KolabType::properties_type::dtstamp_type dtstamp;
dtstamp.date_time(IC::dtstamp());
typename KolabType::properties_type::created_type created;
created.date_time(IC::created(incidence));
typename KolabType::properties_type eventProps(uid, created, dtstamp);
KolabType inc(eventProps);
T::writeIncidence(inc, incidence);
VcalendarType::components_type components;
T::addIncidence(components, inc);
- VcalendarType::properties_type::prodid_type prodid(productid+KOLAB_LIBNAME+KOLAB_LIB_VERSION); //FIXME own version field for lib version
+ VcalendarType::properties_type::prodid_type prodid(productid+KOLAB_LIB_VERSION_STRING); //FIXME own version field for lib version
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) {
CRITICAL("failed to write Incidence");
} catch (...) {
CRITICAL("Unhandled exception");
}
return std::string();
}
template <typename T>
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;
clearErrors();
try {
std::auto_ptr<icalendar_2_0::IcalendarType> icalendar;
if (isUrl) {
xsd::cxx::xml::dom::auto_ptr <xercesc::DOMDocument > doc = XMLParserWrapper::inst().parseFile(s);
if (doc.get()) {
icalendar = icalendar_2_0::icalendar(doc);
}
} else {
xsd::cxx::xml::dom::auto_ptr <xercesc::DOMDocument > 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() );
global_xCalVersion = vcalendar.properties().version().text();
setKolabVersion( vcalendar.properties().x_kolab_version().text() );
//TODO resolve events, exceptions can be identified based on the recurrence-id attribute
// foreach (KCalCore::Event * event, events) {
// if (!event->hasRecurrenceId()) {
// return event;
// }
// }
if (incidences.size() != 1) {
WARNING("wrong number of incidences: "+ incidences.size());
}
return *incidences.begin();
} catch (const xml_schema::exception& e) {
std::cout << e << std::endl;
CRITICAL("Failed to read incidence!");
} catch (...) {
CRITICAL("Unhandled exception");
}
return IncidencePtr();
}
}
}//Namespace
#endif
diff --git a/src/xcardconversions.h b/src/xcardconversions.h
index b3c1577..30da824 100644
--- a/src/xcardconversions.h
+++ b/src/xcardconversions.h
@@ -1,1092 +1,1092 @@
/*
* Copyright (C) 2011 Christian Mollekopf <mollekopf@kolabsys.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef KOLABXCARDCONVERSION_H
#define KOLABXCARDCONVERSION_H
#include <bindings/kolabformat-xcard.hxx>
#include "kolabcontainers.h"
#include <XMLParserWrapper.h>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <iomanip>
#include "global_definitions.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 <typename T>
std::string getType();
template <>
std::string getType<Kolab::Contact>()
{
return INDIVIDUAL;
}
template <>
std::string getType<Kolab::DistList>()
{
return GROUP;
}
template <typename T>
xsd::cxx::tree::sequence<T> fromList(const std::vector<std::string> &input)
{
xsd::cxx::tree::sequence<T> list;
BOOST_FOREACH(const std::string &s, input) {
list.push_back(T(s));
}
return list;
}
template <typename T>
xsd::cxx::tree::sequence<T> fromList(const std::vector<std::string> &input, int preferredIndex)
{
xsd::cxx::tree::sequence<T> 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 <typename T>
std::vector<std::string> toUriList(const xsd::cxx::tree::sequence<T> &input)
{
std::vector<std::string> list;
BOOST_FOREACH(const vcard_4_0::UriPropertyType &s, input) {
list.push_back(s.uri());
}
return list;
}
template <typename T>
std::vector<std::string> toTextList(const xsd::cxx::tree::sequence<T> &input)
{
std::vector<std::string> list;
BOOST_FOREACH(const vcard_4_0::TextPropertyType &s, input) {
list.push_back(s.text());
}
return list;
}
std::vector<std::string> toStringList(const ::xsd::cxx::tree::sequence< ::xml_schema::string > &s)
{
std::vector<std::string> d;
std::copy(s.begin(), s.end(), std::back_inserter(d));
return d;
}
::xsd::cxx::tree::sequence< ::xml_schema::string > fromStringList(const std::vector<std::string> &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<int>(input.substr(0, 4));
month = boost::lexical_cast<int>(input.substr(4, 2));
day = boost::lexical_cast<int>(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<int>(input.substr(9, 2));
minute = boost::lexical_cast<int>(input.substr(11, 2));
second = boost::lexical_cast<int>(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 {
ERROR("wrong utc char? " + input.at(15));
return cDateTime();
}
}
} catch (boost::bad_lexical_cast &c) {
ERROR("failed to convert: "+std::string(c.what()));
return cDateTime();
} catch (...) {
ERROR("failed to convert: unkown 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 <typename T>
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 &param, (*r.parameters()).baseParameter()) {
if (const vcard_4_0::typeParamType *rel = dynamic_cast<const vcard_4_0::typeParamType*> (&param)) {
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 &param, (*adr.parameters()).baseParameter()) {
if (const vcard_4_0::labelParamType *rel = dynamic_cast<const vcard_4_0::labelParamType*> (&param)) {
address.setLabel(rel->text());
} else if (isPreferred && dynamic_cast<const vcard_4_0::prefParamType*> (&param)) {
*isPreferred = true;
} else if (const vcard_4_0::typeParamType *rel = dynamic_cast<const vcard_4_0::typeParamType*> (&param)) {
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<double>::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<double>(uri.substr(4, pos1-4));
lon = boost::lexical_cast<double>(uri.substr(pos1+1, uri.size()-pos1-1));
return true;
}
template <typename T>
void writeCard(vcard_4_0::vcard &vcard, const T &);
template <>
void writeCard<Kolab::Contact>(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;
BOOST_FOREACH(const std::string &s, contact.categories()) {
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<vcard::title_type>(contact.titles()));
}
if (!contact.affiliations().empty()) {
vcard::group_sequence affiliations;
BOOST_FOREACH(const Affiliation &a, contact.affiliations()) {
affiliationPropType::org_type org;
org.text().push_back(a.organisation());
BOOST_FOREACH(const std::string &unit, a.organisationalUnits()) {
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<affiliationPropType::role_type>(a.roles()));
BOOST_FOREACH(const Related &rel, a.relateds()) {
group.related().push_back(fromRelated(rel));
}
BOOST_FOREACH(const Address &adr, a.addresses()) {
group.adr().push_back(fromAddress(adr));
}
affiliations.push_back(group);
}
vcard.group(affiliations);
}
if (!contact.urls().empty()) {
vcard.url(fromList<vcard::url_type>(contact.urls()));
}
if (!contact.addresses().empty()) {
vcard::adr_sequence adrs;
int index = 0;
BOOST_FOREACH(const Kolab::Address &address, contact.addresses()) {
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;
BOOST_FOREACH(const std::string &s, contact.nickNames()) {
textsequence.push_back(s);
}
vcard::nickname_type nickName;
nickName.text(textsequence);
vcard.nickname(nickName);
}
if (!contact.relateds().empty()) {
vcard::related_sequence seq;
BOOST_FOREACH(const Kolab::Related &r, contact.relateds()) {
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<vcard::bday_type>(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<vcard::anniversary_type>(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:
ERROR("Unhandled gender");
}
}
if (!contact.languages().empty()) {
vcard.lang(fromList<vcard::lang_type>(contact.languages()));
}
if (!contact.telephones().empty()) {
vcard::tel_sequence seq;
int index = 0;
BOOST_FOREACH(const Kolab::Telephone &t, contact.telephones()) {
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<vcard::impp_type>(contact.imAddresses(), contact.imAddressPreferredIndex()));
}
if (!contact.emailAddresses().empty()) {
vcard.email(fromList<vcard::email_type>(contact.emailAddresses(), contact.emailAddressPreferredIndex()));
}
if (!contact.gpsPos().empty()) {
vcard_4_0::vcard::geo_sequence list;
BOOST_FOREACH(const Kolab::Geo &g ,contact.gpsPos()) {
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);
}
vcard_4_0::vcard::key_sequence keys;
if (!c.pgpKey().empty()) {
keys.push_back(vcard_4_0::keyPropType(uriInlineEncoding(c.pgpKey(), MIME_PGP_KEYS)));
}
if (!c.smimeKey().empty()) {
keys.push_back(vcard_4_0::keyPropType(uriInlineEncoding(c.smimeKey(), MIME_PKCS7_MIME)));
}
if (!keys.empty()) {
vcard.key(keys);
}
crypto.encryptpref(fromCryptoPref(c.encryptPref()));
crypto.signpref(fromCryptoPref(c.signPref()));
vcard.x_crypto(crypto);
}
}
template <>
void writeCard<Kolab::DistList>(vcard_4_0::vcard &vcard, const Kolab::DistList &distlist)
{
if (!distlist.members().empty()) {
vcard_4_0::vcard::member_sequence members;
BOOST_FOREACH (const Kolab::ContactReference &m, distlist.members()) {
members.push_back(vcard_4_0::vcard::member_type(Shared::fromContactReference(m)));
}
vcard.member(members);
} else {
WARNING("empty distlist");
}
}
template <typename T>
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(prod+KOLAB_LIBNAME+KOLAB_LIB_VERSION);
+ vcard_4_0::vcard::prodid_type prodid(prod+KOLAB_LIB_VERSION_STRING);
vcard_4_0::vcard::rev_type rev(fromDateTime(getCurrentTime()));
vcard_4_0::vcard::kind_type kind(getType<T>());
vcard_4_0::vcard::fn_type fn(card.name());
vcard_4_0::vcard vcard(uid, kolab_version, prodid, rev, kind, fn);
writeCard<T>(vcard, card);
if (!card.customProperties().empty()) {
BOOST_FOREACH(const Kolab::CustomProperty &a, card.customProperties()) {
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) {
CRITICAL("Unknown Exception: failed to write Contact");
}
return std::string();
}
template <typename T>
boost::shared_ptr<T> readCard(const vcard_4_0::VcardsType::vcard_type &vcard);
template <>
boost::shared_ptr<Kolab::Contact> readCard <Kolab::Contact> (const vcard_4_0::VcardsType::vcard_type &vcard)
{
using namespace vcard_4_0;
boost::shared_ptr<Kolab::Contact> 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_type >(vcard.title()));
}
if (!vcard.group().empty()) {
std::vector<Kolab::Affiliation> 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<std::string> 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<vcard::group_type::role_type>(group.role()));
std::vector<Related> relateds;
BOOST_FOREACH(const vcard::group_type::related_type &rel, group.related()) {
relateds.push_back(toRelated(rel));
}
aff.setRelateds(relateds);
std::vector<Address> 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()) {
contact->setUrls(toUriList<vcard::url_type >(vcard.url()));
}
if (!vcard.adr().empty()) {
std::vector<Kolab::Address> 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<TextListPropertyType::text_type>((*vcard.nickname()).text()));
}
if (!vcard.related().empty()) {
std::vector<Related> 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<std::string> 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<Kolab::Telephone> 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 &param, (*tel.parameters()).baseParameter()) {
if (dynamic_cast<const vcard_4_0::prefParamType*> (&param)) {
preferredIndex = index;
} else if (const vcard_4_0::typeParamType *rel = dynamic_cast<const vcard_4_0::typeParamType*> (&param)) {
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<std::string> 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 &param, (*s.parameters()).baseParameter()) {
if (dynamic_cast<const vcard_4_0::prefParamType*> (&param)) {
preferredIndex = i;
}
}
}
i++;
list.push_back(s.uri());
}
contact->setIMaddresses(list, preferredIndex);
}
if (!vcard.email().empty()) {
int preferredIndex = -1;
std::vector<std::string> list;
int i = 0;
BOOST_FOREACH(const vcard_4_0::TextPropertyType &s, vcard.email()) {
if (s.parameters()) {
BOOST_FOREACH(const vcard_4_0::ArrayOfParameters::baseParameter_type &param, (*s.parameters()).baseParameter()) {
if (dynamic_cast<const vcard_4_0::prefParamType*> (&param)) {
preferredIndex = i;
}
}
}
i++;
list.push_back(s.text());
}
contact->setEmailAddresses(list, preferredIndex);
}
if (!vcard.geo().empty()) {
std::vector<Geo> 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 (!vcard.key().empty()) {
BOOST_FOREACH(const vcard_4_0::keyPropType &k, vcard.key()) {
std::string mimetype;
const std::string &key = uriInlineDecoding(k.uri(), mimetype);
if (mimetype == MIME_PGP_KEYS) {
c.setPGPKey(key);
} else if (mimetype == MIME_PKCS7_MIME) {
c.setSMIMEKey(key);
} else {
WARNING("wrong mimetype on key");
}
}
}
if (crypto.encryptpref()) {
c.setEncryptPref(toCryptoPref(crypto.encryptpref()->text()));
}
if (crypto.signpref()) {
c.setSignPref(toCryptoPref(crypto.signpref()->text()));
}
contact->setCrypto(c);
}
return contact;
}
template <>
boost::shared_ptr<Kolab::DistList> readCard <Kolab::DistList> (const vcard_4_0::VcardsType::vcard_type &vcard)
{
using namespace vcard_4_0;
boost::shared_ptr<Kolab::DistList> distlist(new Kolab::DistList);
if (!vcard.member().empty()) {
std::vector<Kolab::ContactReference> members;
BOOST_FOREACH(const vcard_4_0::vcard::member_type & m, vcard.member()) {
members.push_back(Shared::toContactReference(m.uri()));
}
distlist->setMembers(members);
} else {
WARNING("empty distlist");
}
return distlist;
}
template <typename T>
boost::shared_ptr<T> deserializeCard(const std::string& s, bool isUrl)
{
clearErrors();
try {
std::auto_ptr<vcard_4_0::VcardsType> vcards;
if (isUrl) {
xsd::cxx::xml::dom::auto_ptr <xercesc::DOMDocument > doc = XMLParserWrapper::inst().parseFile(s);
if (doc.get()) {
vcards = vcard_4_0::vcards(doc);
}
} else {
xsd::cxx::xml::dom::auto_ptr <xercesc::DOMDocument > 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<T>();
}
boost::shared_ptr<T> card = readCard<T>(vcards->vcard());
card->setUid(Shared::fromURN(vcards->vcard().uid().uri()));
card->setName(vcards->vcard().fn().text());
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<Kolab::CustomProperty> 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;
CRITICAL("Failed to read card!");
}
return boost::shared_ptr<T>();
}
}
} //Namespace
#endif
diff --git a/tests/bindingstest.cpp b/tests/bindingstest.cpp
index c1f6a20..efae01f 100644
--- a/tests/bindingstest.cpp
+++ b/tests/bindingstest.cpp
@@ -1,559 +1,559 @@
#include "bindingstest.h"
#include <QObject>
#include <QtTest/QtTest>
#include "bindings/iCalendar-props.hxx"
#include "bindings/iCalendar-valtypes.hxx"
#include "bindings/kolabformat.hxx"
#include <iostream>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <src/kolabformat.h>
// #include <kolab/kolabkcalconversion.h>
#include <iostream>
#include <fstream>
#include "serializers.h"
#include <src/utils.h>
#include <src/kolabjournal.h>
void BindingsTest::noteCompletness()
{
Kolab::Note note;
note.setUid("UID");
note.setCreated(Kolab::cDateTime(2006,1,6,12,0,0)); //UTC
note.setClassification(Kolab::ClassConfidential);
note.addCategory("Category");
note.setSummary("summary");
note.setDescription("description");
note.setColor("color");
const std::string &result = Kolab::writeNote(note);
// std::cout << result << std::endl;
const Kolab::Note &re = Kolab::readNote(result, false);
QCOMPARE(re.uid(), note.uid());
QCOMPARE(re.created(), note.created());
QCOMPARE(re.classification(), note.classification());
QCOMPARE(re.categories(), note.categories());
QCOMPARE(re.summary(), note.summary());
QCOMPARE(re.description(), note.description());
QCOMPARE(re.color(), note.color());
}
// void BindingsTest::eventCompletness_data()
template <typename T>
void setIncidence(T &ev)
{
ev.setUid("UID");
ev.setCreated(Kolab::cDateTime(2006,1,6,12,0,0)); //UTC
ev.setSequence(1);
ev.setClassification(Kolab::ClassConfidential);
ev.addCategory("Category");
ev.setStart(Kolab::cDateTime("Europe/Zurich", 2006,1,6,12,0,0));
Kolab::RecurrenceRule rule;
rule.setFrequency(Kolab::RecurrenceRule::Daily);
rule.setCount(5);
std::vector<int> list;
list.push_back(1);
list.push_back(3);
rule.setBysecond(list);
rule.setByminute(list);
rule.setByhour(list);
std::vector<Kolab::DayPos> byday;
byday.push_back(Kolab::DayPos(15, Kolab::Friday));
byday.push_back(Kolab::DayPos(0, Kolab::Monday));
byday.push_back(Kolab::DayPos(-3, Kolab::Monday));
rule.setByday(byday);
rule.setBymonthday(list);
rule.setByyearday(list);
rule.setByweekno(list);
rule.setBymonth(list);
ev.setRecurrenceRule(rule);
ev.addRecurrenceDate(Kolab::cDateTime("Europe/Zurich", 2006,1,6,12,0,0));
ev.addExceptionDate(Kolab::cDateTime("Europe/Zurich", 2006,1,6,12,0,0));
ev.setRecurrenceID(Kolab::cDateTime("Europe/Zurich", 2006,1,6,12,0,0), true);
ev.setSummary("summary");
ev.setDescription("description");
ev.setPriority(3);
ev.setStatus(Kolab::StatusConfirmed);
ev.setLocation("location");
ev.setOrganizer(Kolab::ContactReference("mail", "name", "uid"));
Kolab::Attendee attendee(Kolab::ContactReference("mail", "name", "uid"));
attendee.setPartStat(Kolab::PartDelegated);
attendee.setRole(Kolab::Chair);
attendee.setRSVP(true);
ev.setAttendees(std::vector<Kolab::Attendee>() << attendee << attendee);
std::vector<Kolab::Attachment> attachments;
Kolab::Attachment attach;
attach.setData("data????*?*?*?*?*?", "mimetype");
attach.setLabel("label");
attachments.push_back(attach);
Kolab::Attachment attach2;
attach2.setUri("../../tests/testfiles/icalEvent.xml", "mimetype");
attach2.setLabel("labe2l");
attachments.push_back(attach2);
Kolab::Attachment attach3;
using namespace std;
ifstream file ("../../tests/testfiles/icalEvent.xml", ios::in|ios::binary|ios::ate);
if (file.is_open()) {
int size = file.tellg();
char *memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
attach3.setData(string(memblock, size), "mimetype");
delete[] memblock;
}
attach3.setLabel("labe3l");
attachments.push_back(attach3);
ev.setAttachments(attachments);
std::vector<Kolab::CustomProperty> properties;
properties.push_back(Kolab::CustomProperty("ident", "value"));
properties.push_back(Kolab::CustomProperty("ident", "value"));
ev.setCustomProperties(properties);
std::vector<Kolab::Alarm> alarms;
// Kolab::Alarm dispAlarm("ident");
// dispAlarm.setRelativeStart(Kolab::Duration(3, true), Kolab::Start);
// alarms.push_back(dispAlarm);
std::vector<Kolab::ContactReference> att;
att.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name"));
att.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name"));
Kolab::Alarm emailAlarm("ident", "value", att);
emailAlarm.setStart(Kolab::cDateTime(2003,2,3,2,3,4, true));
alarms.push_back(emailAlarm);
// Kolab::Attachment audiofile;
// audiofile.setUri("ksdjlksdflj", "sdkljdfl");
// Kolab::Alarm audio(audiofile);
// audio.setStart(Kolab::cDateTime(2003,2,3,2,3,4, true));
// alarms.push_back(audio);
ev.setAlarms(alarms);
}
template <typename T>
void checkIncidence(const T &ev, const T &re)
{
//Common to all
QCOMPARE(ev.uid(), re.uid());
QCOMPARE(ev.created(), re.created());
QVERIFY(re.lastModified().isValid()); //TODO can we check this better?
QCOMPARE(ev.sequence(), re.sequence());
QCOMPARE(ev.classification(), re.classification());
QCOMPARE(ev.categories(), re.categories());
QCOMPARE(ev.start(), re.start());
//Recurrence
const Kolab::RecurrenceRule &r1 = ev.recurrenceRule();
const Kolab::RecurrenceRule &r2 = re.recurrenceRule();
QCOMPARE(r1.isValid(), r2.isValid());
QCOMPARE(r1.frequency(), r2.frequency());
QCOMPARE(r1.interval(), r2.interval());
QCOMPARE(r1.weekStart(), r2.weekStart());
QCOMPARE(r1.count(), r2.count());
QCOMPARE(r1.end(), r2.end());
QCOMPARE(r1.bysecond(), r2.bysecond());
QCOMPARE(r1.byminute(), r2.byminute());
QCOMPARE(r1.byhour(), r2.byhour());
QCOMPARE(r1.byday(), r2.byday());
QCOMPARE(r1.bymonthday(), r2.bymonthday());
QCOMPARE(r1.byyearday(), r2.byyearday());
QCOMPARE(r1.byweekno(), r2.byweekno());
QCOMPARE(r1.bymonth(), r2.bymonth());
//Rest
QCOMPARE(ev.recurrenceDates(), re.recurrenceDates());
QCOMPARE(ev.exceptionDates(), re.exceptionDates());
QCOMPARE(ev.recurrenceID(), re.recurrenceID());
QCOMPARE(ev.thisAndFuture(), re.thisAndFuture());
QCOMPARE(ev.summary(), re.summary());
QCOMPARE(ev.description(), re.description());
QCOMPARE(ev.priority(), re.priority());
QCOMPARE(ev.status(), re.status());
QCOMPARE(ev.location(), re.location());
QCOMPARE(ev.organizer(), re.organizer());
QCOMPARE(ev.attendees(), re.attendees());
QCOMPARE(ev.attachments(), re.attachments());
QCOMPARE(ev.customProperties(), re.customProperties());
QCOMPARE(ev.alarms(), re.alarms());
}
void BindingsTest::eventCompletness()
{
Kolab::Event ev;
setIncidence(ev);
ev.setEnd(Kolab::cDateTime("Europe/Zurich", 2006,1,8,12,0,0));
ev.setTransparency(true);
std::string result = Kolab::writeEvent(ev);
QVERIFY(Kolab::error() == Kolab::NoError);
// std::cout << result << endl;
Kolab::Event e = Kolab::readEvent(result, false);
QVERIFY(Kolab::error() == Kolab::NoError);
checkIncidence(ev, e);
QCOMPARE(ev.end(), e.end());
QCOMPARE(ev.transparency(), e.transparency());
}
void BindingsTest::eventDuration()
{
Kolab::Event ev;
ev.setStart(Kolab::cDateTime("Europe/Zurich", 2006,1,8,12,0,0));
ev.setDuration(Kolab::Duration(11,22,33,44, true));
const std::string result = Kolab::writeEvent(ev);
QVERIFY(Kolab::error() == Kolab::NoError);
// std::cout << result << endl;
const Kolab::Event e = Kolab::readEvent(result, false);
QVERIFY(Kolab::error() == Kolab::NoError);
QVERIFY(ev.duration().isValid());
QCOMPARE(ev.duration(), e.duration());
}
void BindingsTest::todoCompletness()
{
Kolab::Todo ev;
setIncidence(ev);
ev.setDue(Kolab::cDateTime("Europe/Zurich", 2006,1,8,12,0,0));
ev.addRelatedTo("rel1");
ev.addRelatedTo("rel2");
ev.setPercentComplete(50);
std::string result = Kolab::writeTodo(ev);
QVERIFY(Kolab::error() == Kolab::NoError);
// std::cout << result << endl;
Kolab::Todo e = Kolab::readTodo(result, false);
QVERIFY(Kolab::error() == Kolab::NoError);
checkIncidence(ev, e);
QCOMPARE(ev.due(), e.due());
QCOMPARE(ev.relatedTo(), e.relatedTo());
QCOMPARE(ev.percentComplete(), e.percentComplete());
}
void BindingsTest::journalCompletness()
{
Kolab::Journal ev;
ev.setUid("UID");
ev.setCreated(Kolab::cDateTime(2006,1,6,12,0,0)); //UTC
ev.setSequence(1);
ev.setClassification(Kolab::ClassConfidential);
ev.addCategory("Category");
ev.setStart(Kolab::cDateTime("Europe/Zurich", 2006,1,6,12,0,0));
Kolab::Attendee attendee(Kolab::ContactReference("mail", "name", "uid"));
attendee.setPartStat(Kolab::PartDelegated);
attendee.setRole(Kolab::Chair);
attendee.setRSVP(true);
ev.setAttendees(std::vector<Kolab::Attendee>() << attendee << attendee);
std::vector<Kolab::Attachment> attachments;
Kolab::Attachment attach;
attach.setData("data????*?*?*?*?*?", "mimetype");
attach.setLabel("label");
attachments.push_back(attach);
Kolab::Attachment attach2;
attach2.setUri("../../tests/testfiles/icalEvent.xml", "mimetype");
attach2.setLabel("labe2l");
attachments.push_back(attach2);
Kolab::Attachment attach3;
using namespace std;
ifstream file ("../../tests/testfiles/icalEvent.xml", ios::in|ios::binary|ios::ate);
if (file.is_open()) {
int size = file.tellg();
char *memblock = new char [size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
attach3.setData(string(memblock, size), "mimetype");
delete[] memblock;
}
attach3.setLabel("labe3l");
attachments.push_back(attach3);
ev.setAttachments(attachments);
std::vector<Kolab::CustomProperty> properties;
properties.push_back(Kolab::CustomProperty("ident", "value"));
properties.push_back(Kolab::CustomProperty("ident", "value"));
ev.setCustomProperties(properties);
std::string result = Kolab::writeJournal(ev);
QVERIFY(Kolab::error() == Kolab::NoError);
// std::cout << result << endl;
Kolab::Journal re = Kolab::readJournal(result, false);
QVERIFY(Kolab::error() == Kolab::NoError);
QCOMPARE(ev.uid(), re.uid());
QCOMPARE(ev.created(), re.created());
QVERIFY(re.lastModified().isValid()); //TODO can we check this better?
QCOMPARE(ev.sequence(), re.sequence());
QCOMPARE(ev.classification(), re.classification());
QCOMPARE(ev.categories(), re.categories());
QCOMPARE(ev.start(), re.start());
QCOMPARE(ev.summary(), re.summary());
QCOMPARE(ev.description(), re.description());
QCOMPARE(ev.status(), re.status());
QCOMPARE(ev.attendees(), re.attendees());
QCOMPARE(ev.attachments(), re.attachments());
QCOMPARE(ev.customProperties(), re.customProperties());
}
void BindingsTest::contactCompletness()
{
std::vector<std::string> stringlist;
stringlist.push_back("lbksdfbklsd");
stringlist.push_back("sdf");
Kolab::Contact c;
c.setUid("1045b57d-ff7f-0000-d814-867b4d7f0000");
c.setCategories(stringlist);
c.setName("name");
Kolab::NameComponents nc;
nc.setSurnames(stringlist);
nc.setGiven(stringlist);
nc.setAdditional(stringlist);
nc.setPrefixes(stringlist);
nc.setSuffixes(stringlist);
c.setNameComponents(nc);
c.setNote("note");
c.setFreeBusyUrl("freebusy");
c.setUrls(stringlist);
c.setNickNames(stringlist);
std::vector <Kolab::Related> relateds;
Kolab::Related r1(Kolab::Related::Text, "text");
r1.setRelationTypes(Kolab::Related::Child);
relateds.push_back(r1);
Kolab::Related r2(Kolab::Related::Uid, "urn");
r2.setRelationTypes(Kolab::Related::Child|Kolab::Related::Spouse);
relateds.push_back(r2);
c.setRelateds(relateds);
c.setBDay(Kolab::cDateTime(2001,12,10,12,12,12,false));
c.setAnniversary(Kolab::cDateTime(2001,3,2,1,1,1,false));
c.setPhoto("photo", "mimetype");
c.setGender(Kolab::Contact::Male);
c.setLanguages(stringlist);
c.setIMaddresses(stringlist,1);
c.setEmailAddresses(stringlist,1);
c.setTitles(stringlist);
std::vector<Kolab::Affiliation> list;
Kolab::Affiliation aff;
aff.setOrganisation("org");
aff.setOrganisationalUnits(stringlist);
aff.setLogo("logo", "mime/miem");
aff.setRoles(stringlist);
std::vector<Kolab::Related> relateds2;
relateds2.push_back(Kolab::Related(Kolab::Related::Text, "textRelation", Kolab::Related::Assistant));
relateds2.push_back(Kolab::Related(Kolab::Related::Uid, "textRelation", Kolab::Related::Manager));
aff.setRelateds(relateds2);
std::vector<Kolab::Address> adrs;
Kolab::Address adr1;
adr1.setLabel("label");
adrs.push_back(adr1);
Kolab::Address adr2;
adr2.setStreet("street");
adr2.setTypes(Kolab::Address::Work);
adrs.push_back(adr2);
aff.setAddresses(adrs);
list.push_back(aff);
Kolab::Affiliation aff2;
list.push_back(aff2);
c.setAffiliations(list);
Kolab::Address address;
address.setCode("oiuoiu");
address.setCountry("werwer");
address.setLabel("lkjlkj");
address.setLocality("alla");
address.setRegion("skjdfkd");
address.setStreet("sldkflsdfj");
address.setTypes( Kolab::Address::Work | Kolab::Address::Home );
std::vector<Kolab::Address> addresses;
addresses.push_back(address);
addresses.push_back(address);
c.setAddresses(addresses);
Kolab::Telephone phone;
phone.setNumber("lkjsdflkjfds");
phone.setTypes(Kolab::Telephone::Work|
Kolab::Telephone::Home|
Kolab::Telephone::Text|
Kolab::Telephone::Voice|
Kolab::Telephone::Fax|
Kolab::Telephone::Cell|
Kolab::Telephone::Video|
Kolab::Telephone::Pager|
Kolab::Telephone::Textphone|
Kolab::Telephone::Car
);
std::vector<Kolab::Telephone> telephones;
telephones.push_back(phone);
telephones.push_back(phone);
c.setTelephones(telephones, 1);
std::vector<Kolab::Geo> geo;
geo << Kolab::Geo(1.3, -40.3);
c.setGPSpos(geo);
Kolab::Crypto crypto;
crypto.setAllowed(Kolab::Crypto::PGPinline | Kolab::Crypto::SMIMEopaque);
crypto.setPGPKey("pgp");
crypto.setSignPref(Kolab::Crypto::IfPossible);
crypto.setEncryptPref(Kolab::Crypto::Never);
crypto.setSMIMEKey("smime");
c.setCrypto(crypto);
std::vector<Kolab::CustomProperty> properties;
properties.push_back(Kolab::CustomProperty("ident", "value"));
properties.push_back(Kolab::CustomProperty("ident", "value"));
c.setCustomProperties(properties);
const std::string result = Kolab::writeContact(c);
QVERIFY(Kolab::error() == Kolab::NoError);
std::cout << result << endl;
Kolab::Contact e = Kolab::readContact(result, false);
QVERIFY(Kolab::error() == Kolab::NoError);
QCOMPARE(e.uid(), c.uid());
QCOMPARE(e.categories(), c.categories());
QCOMPARE(e.name(), c.name());
QCOMPARE(e.nameComponents(), c.nameComponents());
QCOMPARE(e.note(), c.note());
QCOMPARE(e.freeBusyUrl(), c.freeBusyUrl());
QCOMPARE(e.titles(), c.titles());
QCOMPARE(e.affiliations(), c.affiliations());
QCOMPARE(e.urls(), c.urls());
QCOMPARE(e.addresses(), c.addresses());
QCOMPARE(e.addressPreferredIndex(), c.addressPreferredIndex());
QCOMPARE(e.nickNames(), c.nickNames());
QCOMPARE(e.relateds(), c.relateds());
QCOMPARE(e.bDay(), c.bDay());
QCOMPARE(e.anniversary(), c.anniversary());
QCOMPARE(e.photo(), c.photo());
QCOMPARE(e.photoMimetype(), c.photoMimetype());
QCOMPARE(e.gender(), c.gender());
QCOMPARE(e.languages(), c.languages());
QCOMPARE(e.telephones(), c.telephones());
QCOMPARE(e.telephonesPreferredIndex(), c.telephonesPreferredIndex());
QCOMPARE(e.imAddresses(), c.imAddresses());
QCOMPARE(e.imAddressPreferredIndex(), c.imAddressPreferredIndex());
QCOMPARE(e.emailAddresses(), c.emailAddresses());
QCOMPARE(e.emailAddressPreferredIndex(), c.emailAddressPreferredIndex());
QCOMPARE(e.gpsPos(), c.gpsPos());
QCOMPARE(e.crypto(), c.crypto());
QCOMPARE(e.customProperties(), c.customProperties());
}
void BindingsTest::distlistCompletness()
{
std::vector<std::string> stringlist;
stringlist.push_back("lbksdfbklsd");
stringlist.push_back("sdf");
Kolab::DistList c;
c.setName("name");
c.setUid("uid");
std::vector<Kolab::ContactReference> members;
members.push_back(Kolab::ContactReference(Kolab::ContactReference::EmailReference, "mail", "name"));
members.push_back(Kolab::ContactReference(Kolab::ContactReference::UidReference, "urn"));
c.setMembers(members);
std::vector<Kolab::CustomProperty> properties;
properties.push_back(Kolab::CustomProperty("ident", "value"));
properties.push_back(Kolab::CustomProperty("ident", "value"));
c.setCustomProperties(properties);
const std::string result = Kolab::writeDistlist(c);
QVERIFY(Kolab::error() == Kolab::NoError);
// std::cout << result << endl;
Kolab::DistList e = Kolab::readDistlist(result, false);
QVERIFY(Kolab::error() == Kolab::NoError);
QCOMPARE(e.uid(), c.uid());
QCOMPARE(e.name(), c.name());
QCOMPARE(e.members(), c.members());
QCOMPARE(e.customProperties(), c.customProperties());
}
void BindingsTest::versionTest()
{
Kolab::Todo ev;
setIncidence(ev);
std::string result = Kolab::writeTodo(ev);
Kolab::Todo e = Kolab::readTodo(result, false);
- QCOMPARE(Kolab::productId(), std::string(Kolab::KOLAB_LIBNAME) + std::string(Kolab::KOLAB_LIB_VERSION));
- QCOMPARE(Kolab::xKolabVersion(), std::string(Kolab::KOLAB_FORMAT_VERSION));
+ QCOMPARE(Kolab::productId(), std::string(KOLAB_LIB_VERSION_STRING));
+ QCOMPARE(Kolab::xKolabVersion(), std::string(KOLAB_FORMAT_VERSION));
QCOMPARE(Kolab::xCalVersion(), std::string("2.0"));
}
void BindingsTest::errorTest()
{
Kolab::Todo e = Kolab::readTodo("klbsdfbklsdbkl", false);
QCOMPARE(Kolab::error(), Kolab::Critical);
QVERIFY(!Kolab::errorMessage().empty());
}
//Don't break due to an error
void BindingsTest::errorRecoveryTest()
{
Kolab::Todo e = Kolab::readTodo("klbsdfbklsdbkl", false);
QCOMPARE(Kolab::error(), Kolab::Critical);
Kolab::Todo ev;
setIncidence(ev);
const std::string result = Kolab::writeTodo(ev);
Kolab::readTodo(result, false);
QCOMPARE(Kolab::error(), Kolab::NoError);
}
void BindingsTest::BenchmarkRoundtripKolab()
{
const Kolab::Event &event = Kolab::readEvent("../../tests/testfiles/icalEvent.xml", true);
std::string result = Kolab::writeEvent(event);
QBENCHMARK {
Kolab::readEvent(result, false);
}
}
void BindingsTest::BenchmarkRoundtrip()
{
const Kolab::Event &event = Kolab::readEvent("../../tests/testfiles/icalEvent.xml", true);
std::string result;
QBENCHMARK {
result = Kolab::writeEvent(event);
Kolab::readEvent(result, false);
}
}
QTEST_MAIN( BindingsTest )
#include "bindingstest.moc"

File Metadata

Mime Type
text/x-diff
Expires
Mon, Apr 6, 1:25 AM (6 h, 58 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18831836
Default Alt Text
(136 KB)

Event Timeline