Commit f5267cae authored by Nicolas Mora's avatar Nicolas Mora

New upstream version.

parent e34d264b
......@@ -98,7 +98,7 @@ endif()
set(LIBICAL_LIB_MAJOR_VERSION "3")
set(LIBICAL_LIB_MINOR_VERSION "0")
set(LIBICAL_LIB_PATCH_VERSION "3")
set(LIBICAL_LIB_PATCH_VERSION "4")
set(LIBICAL_LIB_VERSION_STRING
"${LIBICAL_LIB_MAJOR_VERSION}.${LIBICAL_LIB_MINOR_VERSION}.${LIBICAL_LIB_PATCH_VERSION}"
)
......
# <a name="title"></a> Libical [![Build Status](https://travis-ci.org/libical/libical.svg?branch=master)](https://travis-ci.org/libical/libical) [![Coverity Scan Build Status](https://scan.coverity.com/projects/2367/badge.svg)](https://scan.coverity.com/projects/2367)
# <a name="title"></a> Libical [![Travis Build Status](https://travis-ci.org/libical/libical.svg?branch=master)](https://travis-ci.org/libical/libical) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/libical/libical?branch=master?svg=true)](https://ci.appveyor.com/api/projects/status/github/libical/libical) [![Coverity Scan Build Status](https://scan.coverity.com/projects/2367/badge.svg)](https://scan.coverity.com/projects/2367) [![Packaging status](https://repology.org/badge/tiny-repos/libical.svg)](https://repology.org/metapackage/libical)
## Introduction
......@@ -13,14 +13,16 @@ and protocol data units. The iCalendar specification describes how
calendar clients can communicate with calendar servers so users can
store their calendar data and arrange meetings with other users.
Libical implements [RFC5545][], [RFC5546][], [RFC7529][]; the
iCalendar extensions in [RFC6638][]; and some of [RFC6047][].
Libical implements [RFC5545][], [RFC5546][], [RFC7529][]; the
CalDav scheduling extensions in [RFC6638][]; iCalendar extensions in [RFC7986][];
plus the iCalendar iMIP protocol in [RFC6047][].
[RFC5545]: https://tools.ietf.org/html/rfc5545
[RFC5546]: https://tools.ietf.org/html/rfc5546
[RFC7529]: https://tools.ietf.org/html/rfc7529
[RFC6638]: https://tools.ietf.org/html/rfc6638
[RFC6047]: https://tools.ietf.org/html/rfc6047
[RFC7986]: https://tools.ietf.org/html/rfc7986
## License
......@@ -54,7 +56,7 @@ for libical, which is available [here](http://libical.github.io/libical/apidocs/
Portions of this distribution are (C) Copyright 1996 Apple Computer,
Inc., AT&T Corp., International Business Machines Corporation and
Siemens Rolm Communications Inc. See
Siemens Rolm Communications Inc. See
[src/libicalvcal/README.TXT](src/libicalvcal/README.txt) for
details.
......
Release Highlights
==================
Version 3.0.4:
-------------
* Silently fail RSCALE recurrence clauses when RSCALE is disabled
* Fixed icalcomponent_set_comment() and icalcomponent_set_uid()
* fix FREQ=MONTHLY;BYMONTH
* Skip UTF-8 marker when parsing
* Fix parsing <CR>?<LF> in VCF files produced by Outlook
* Fix TZID on DATE-TIME value can override time specified in UTC
* CMake discovery module for ICU uses pkg-config now
* New publicly available function:
+ icalparameter_kind_is_valid()
* Built-in timezones updated to tzdata2018e
Version 3.0.3:
--------------
* VTODO COMPLETED property can be a DATE-TIME or DATE (for backward compatibility)
......
......@@ -23,16 +23,12 @@ if(WIN32)
file(TO_CMAKE_PATH "$ENV{PROGRAMFILES}" _program_FILES_DIR)
endif()
if(ICU_INCLUDE_DIR AND ICU_LIBRARY)
# Already in cache, be silent
set(ICU_FIND_QUIETLY TRUE)
endif()
#set the root from the ICU_BASE environment
file(TO_NATIVE_PATH "$ENV{ICU_BASE}" icu_root)
#override the root from ICU_BASE defined to cmake
if(DEFINED ICU_BASE)
file(TO_NATIVE_PATH "${ICU_BASE}" icu_root)
else()
find_package(PkgConfig QUIET)
pkg_check_modules(PC_LibICU QUIET icu-i18n)
endif()
# Look for the header file.
......@@ -42,6 +38,7 @@ find_path(
HINTS
${icu_root}/include
${_program_FILES_DIR}/icu/include
${PC_LibICU_INCLUDEDIR}
/usr/local/opt/icu4c/include
DOC "Include directory for the ICU library"
)
......@@ -56,6 +53,7 @@ find_library(
${icu_root}/lib/
${_program_FILES_DIR}/icu/lib64/
${_program_FILES_DIR}/icu/lib/
${PC_LibICU_LIBDIR}
/usr/local/opt/icu4c/lib/
DOC "Libraries to link against for the common parts of ICU"
)
......@@ -98,6 +96,7 @@ if(ICU_INCLUDE_DIR AND ICU_LIBRARY)
HINTS
${icu_root}/lib/
${_program_FILES_DIR}/icu/lib/
${PC_LibICU_LIBDIR}
/usr/local/opt/icu4c/lib/
DOC "Libraries to link against for ICU internationalization"
)
......
......@@ -8,7 +8,10 @@ and protocol data units. The iCalendar specification describes how
calendar clients can communicate with calendar servers so users can
store their calendar data and arrange meetings with other users.
Libical implements RFC2445, RFC2446 and some of RFC2447.
Libical implements RFC5545, RFC5546, RFC7529;
the CalDav scheduling extensions in RFC6638;
iCalendar extensions in RFC7986;
plus the iCalendar iMIP protocol in RFC6047.
@section license License
......
......@@ -97,7 +97,7 @@ COMPILE_WARNINGS() {
# print warnings found in the cppcheck output
# $1 = file with the cppcheck output
CPPCHECK_WARNINGS() {
CHECK_WARNINGS $1 "\(warning\)" ""
CHECK_WARNINGS $1 "\(warning\|error\|information\|portability\)" ""
}
#function TIDY_WARNINGS:
......@@ -154,7 +154,7 @@ BUILD() {
# $2 = CMake options
GCC_BUILD() {
name="$1-gcc"
if ( test $rungccbuild -eq 0 )
if ( test $rungccbuild -ne 1 )
then
echo "===== GCC BUILD TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
return
......@@ -172,7 +172,7 @@ GCC_BUILD() {
# $2 = CMake options
CLANG_BUILD() {
name="$1-clang"
if ( test $runclangbuild -eq 0 )
if ( test $runclangbuild -ne 1 )
then
echo "===== CLANG BUILD TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
return
......@@ -190,7 +190,7 @@ CLANG_BUILD() {
# $2 = CMake options
ASAN_BUILD() {
name="$1-asan"
if ( test $runasanbuild -eq 0 )
if ( test $runasanbuild -ne 1 )
then
echo "===== ASAN BUILD TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
return
......@@ -207,7 +207,7 @@ ASAN_BUILD() {
# $2 = CMake options
TSAN_BUILD() {
name="$1-tsan"
if ( test $runtsanbuild -eq 0 )
if ( test $runtsanbuild -ne 1 )
then
echo "===== TSAN BUILD TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
return
......@@ -224,7 +224,7 @@ TSAN_BUILD() {
# $2 = CMake options
CPPCHECK() {
name="$1-cppcheck"
if ( test $runcppcheck -eq 0 )
if ( test $runcppcheck -ne 1 )
then
echo "===== CPPCHECK TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
return
......@@ -249,6 +249,11 @@ CPPCHECK() {
-D size_t="unsigned long" \
-D bswap32="" \
-D PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP="" \
-D _unused="(void)" \
-D F_OK=0 \
-D R_OK=0 \
-U YYSTYPE \
-U PVL_USE_MACROS \
-I $BDIR \
-I $BDIR/src/libical \
-I $BDIR/src/libicalss \
......@@ -260,7 +265,8 @@ CPPCHECK() {
grep -v 'cannot find all the include files' | \
grep -v Net-ICal | \
grep -v icalssyacc\.c | \
grep -v icalsslexer\.c | tee cppcheck.out
grep -v icalsslexer\.c | \
grep -v _cxx\. | tee cppcheck.out
CPPCHECK_WARNINGS cppcheck.out
rm -f cppcheck.out
CLEAN
......@@ -273,9 +279,9 @@ CPPCHECK() {
# $2 = CMake options
SPLINT() {
name="$1-splint"
if ( test $runsplint -eq 0 )
if ( test $runsplint -ne 1 )
then
echo "===== SPLIT TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
echo "===== SPLINT TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
return
fi
COMMAND_EXISTS "splint"
......@@ -338,6 +344,8 @@ SPLINT() {
-I $TOP/src/libicalss \
-I $TOP/src/libicalvcal \
-I $TOP/src/libical-glib | \
grep -v '[[:space:]]Location[[:space:]]unknown[[:space:]]' | \
grep -v '[[:space:]]Code[[:space:]]cannot[[:space:]]be[[:space:]]parsed.' | \
cat - 2>&1 | tee splint-$name.out
status=${PIPESTATUS[0]}
if ( test $status -gt 0 )
......@@ -355,7 +363,7 @@ SPLINT() {
# $1 = the name of the test (which will have "-tidy" appended)
# $2 = CMake options
CLANGTIDY() {
if ( test $runtidy -eq 0 )
if ( test $runtidy -ne 1 )
then
echo "===== CLANG-TIDY TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
return
......@@ -376,7 +384,7 @@ CLANGTIDY() {
# $1 = the name of the test (which will have "-scan" appended)
# $2 = CMake options
CLANGSCAN() {
if ( test $runscan -eq 0 )
if ( test $runscan -ne 1 )
then
echo "===== SCAN-BUILD TEST $1 DISABLED DUE TO COMMAND LINE OPTION ====="
return
......@@ -401,7 +409,7 @@ CLANGSCAN() {
#function KRAZY
# runs a krazy2 test
KRAZY() {
if ( test $runkrazy -eq 0 )
if ( test $runkrazy -ne 1 )
then
echo "===== KRAZY TEST DISABLED DUE TO COMMAND LINE OPTION ====="
return
......@@ -423,7 +431,7 @@ KRAZY() {
##### END FUNCTIONS #####
#TEMP=`getopt -o hkctbslgad --long help,no-krazy,no-cppcheck,no-tidy,no-scan,no-splint,no-clang-build,no-gcc-build,no-asan-build,no-tsan-build -- "$@"`
TEMP=`getopt hkctbslgad: $*`
TEMP=`getopt hkctbslgad $*`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
......@@ -448,7 +456,7 @@ while true ; do
-l|--no-clang-build) runclangbuild=0; shift;;
-g|--no-gcc-build) rungccbuild=0; shift;;
-a|--no-asan-build) runasanbuild=0; shift;;
-d|--no-tsan-build) runtsanbuild=0;shift;;
-d|--no-tsan-build) runtsanbuild=0; shift;;
--) shift; break;;
*) echo "Internal error!"; exit 1;;
esac
......@@ -462,6 +470,7 @@ TOP=`pwd`
BDIR=""
CMAKEOPTS="-DCMAKE_BUILD_TYPE=Debug -DGOBJECT_INTROSPECTION=False -DICAL_GLIB=False -DICAL_BUILD_DOCS=False"
UUCCMAKEOPTS="$CMAKEOPTS -DCMAKE_DISABLE_FIND_PACKAGE_ICU=True"
TZCMAKEOPTS="$CMAKEOPTS -DUSE_BUILTIN_TZDATA=True"
#Static code checkers
......@@ -478,10 +487,12 @@ CLANGTIDY test2builtin "$TZCMAKEOPTS"
#GCC based build tests
GCC_BUILD test1 ""
GCC_BUILD test2 "$CMAKEOPTS"
GCC_BUILD test3 "$UUCCMAKEOPTS"
if (test "`uname -s`" = "Linux")
then
GCC_BUILD test1cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake"
GCC_BUILD test2cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake $CMAKEOPTS"
echo "Temporarily disable cross-compile tests"
# GCC_BUILD test1cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake"
# GCC_BUILD test2cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake $CMAKEOPTS"
fi
GCC_BUILD test1builtin "-DUSE_BUILTIN_TZDATA=True"
GCC_BUILD test2builtin "$TZCMAKEOPTS"
......@@ -489,20 +500,24 @@ GCC_BUILD test2builtin "$TZCMAKEOPTS"
#Clang based build tests
CLANG_BUILD test1 ""
CLANG_BUILD test2 "$CMAKEOPTS"
CLANG_BUILD test3 "$UUCCMAKEOPTS"
if (test "`uname -s`" = "Linux")
then
CLANG_BUILD test1cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake"
CLANG_BUILD test2cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake $CMAKEOPTS"
echo "Temporarily disable cross-compile tests"
# CLANG_BUILD test1cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake"
# CLANG_BUILD test2cross "-DCMAKE_TOOLCHAIN_FILE=$TOP/cmake/Toolchain-Linux-GCC-i686.cmake $CMAKEOPTS"
fi
#Address sanitizer
ASAN_BUILD test1asan ""
ASAN_BUILD test2asan "$CMAKEOPTS"
ASAN_BUILD test3asan "$TZCMAKEOPTS"
ASAN_BUILD test4asan "$UUCCMAKEOPTS"
#Thread sanitizer
TSAN_BUILD test1tsan ""
TSAN_BUILD test2tsan "$CMAKEOPTS"
TSAN_BUILD test3tsan "$TZCMAKEOPTS"
TSAN_BUILD test4tsan "$UUCCMAKEOPTS"
echo "ALL TESTS COMPLETED SUCCESSFULLY"
......@@ -86,7 +86,7 @@ sub insert_code
next if !$prop;
next if $prop eq 'NO';
next if $prop eq 'NO' or $prop eq 'ANY';
my ($uc, $lc, $lcvalue, $ucvalue, $type, @comp_types) = fudge_data($prop);
my $defvalue = $propmap{$prop}->{'default_value'};
......@@ -285,29 +285,8 @@ EOM
print <<EOM;
$type icalproperty_get_${lc}(const icalproperty *prop)
{
#ifndef _MSC_VER
struct icaltimetype itt;
icalparameter *param;
icaltimezone *zone;
#endif
icalerror_check_arg((prop != 0), "prop");
#ifndef _MSC_VER
/*
* Code by dirk\@objectpark.net:
* Set the time zone manually. I am really puzzled that
* it doesnot work automatically like in the other functions
* like icalproperty_get_dtstart().
*/
itt = icalvalue_get_datetime(icalproperty_get_value(prop));
param = icalproperty_get_first_parameter((icalproperty *)prop, ICAL_TZID_PARAMETER);
if (param) {
zone = icaltimezone_get_builtin_timezone(icalparameter_get_tzid(param));
(void)icaltime_set_timezone(&itt, zone);
}
return itt;
#else
return icalvalue_get_datetime(icalproperty_get_value(prop));
#endif
icalerror_check_arg((prop != 0), "prop");
return icalproperty_get_datetime_with_component((icalproperty *)prop, NULL);
}
EOM
......
......@@ -110,4 +110,9 @@
<returns type="ICalParameterKind" comment="The #ICalParameterKind converted from @string" />
<comment xml:space="preserve">Convert a string to the #ICalParameterKind</comment>
</method>
<method name="i_cal_parameter_kind_is_valid" corresponds="icalparameter_kind_is_valid" since="3.0.4">
<parameter type="const ICalParameterKind" name="kind" comment="The #ICalPropertyKind"/>
<returns type="gint" comment="1 if valid, 0 if not."/>
<comment xml:space="preserve">Check whether #ICalParameterKind is valid.</comment>
</method>
</structure>
......@@ -1142,7 +1142,6 @@ void generate_forward_declarations_header_file(GList *structures)
if (c == '$') {
if ((c = fgetc(in)) != '{' && c != '^') {
printf("The following char is not {");
g_free (buffer);
fclose(in);
fclose(out);
return;
......@@ -1446,6 +1445,7 @@ static gboolean is_enum_type(const gchar *type)
structureKind = g_hash_table_lookup(type2kind, trueType);
res = g_strcmp0(structureKind, "enum") == 0;
}
g_free (trueType);
return res;
}
......@@ -2059,7 +2059,7 @@ gchar *get_source_run_time_checkers(Method *method, const gchar *namespace)
if (parameter && parameter->type && parameter->type[strlen(parameter->type) - 1] == '*') {
trueType = get_true_type(parameter->type);
for (i = 0;
trueType[i] && i < namespace_len && namespace[i] == trueType[i];
i < namespace_len && trueType[i] && namespace[i] == trueType[i];
i++);
if (i == namespace_len) {
......
......@@ -37,7 +37,7 @@ file(APPEND ${ICAL_FILE_H_FILE} "extern \"C\" {\n")
file(APPEND ${ICAL_FILE_H_FILE} "#endif\n")
foreach(_current_FILE ${COMBINEDHEADERSICAL})
file(STRINGS ${_current_FILE} _lines)
file(STRINGS ${_current_FILE} _lines NEWLINE_CONSUME)
foreach(_currentLINE ${_lines})
string(REGEX REPLACE "#include \"ical.*\\.h\"" "" _currentLINE "${_currentLINE}")
string(REGEX REPLACE "#include \"config.*\\.h\"" "" _currentLINE "${_currentLINE}")
......
......@@ -46,7 +46,7 @@ typedef struct icalattach_impl icalattach;
/**
* @typedef icalattach_free_fn_t
* @brief (*unused*) Function to be called to free the data of an ::icalattach object.
* @warn Currently not used
* @warning Currently not used
*
* This function type is used to free the data from an ::icalattach object created
* with icalattach_new_from_data(). It is currently not used
......
......@@ -24,6 +24,7 @@
#include "icalerror.h"
#include "icalmemory.h"
#include "icalparser.h"
#include "icalproperty_p.h"
#include "icalrestriction.h"
#include "icaltimezone.h"
......@@ -64,7 +65,6 @@ static void icalcomponent_rename_tzids(icalcomponent *comp, icalarray *rename_ta
static void icalcomponent_rename_tzids_callback(icalparameter *param, void *data);
static int icalcomponent_compare_vtimezones(icalcomponent *vtimezone1, icalcomponent *vtimezone2);
static int icalcomponent_compare_timezone_fn(const void *elem1, const void *elem2);
static struct icaltimetype icalcomponent_get_datetime(icalcomponent *comp, icalproperty *prop);
void icalcomponent_add_children(icalcomponent *impl, va_list args)
{
......@@ -749,7 +749,7 @@ int icalproperty_recurrence_is_excluded(icalcomponent *comp,
for (exdate = icalcomponent_get_first_property(comp, ICAL_EXDATE_PROPERTY);
exdate != NULL; exdate = icalcomponent_get_next_property(comp, ICAL_EXDATE_PROPERTY)) {
struct icaltimetype exdatetime = icalcomponent_get_datetime(comp, exdate);
struct icaltimetype exdatetime = icalproperty_get_datetime_with_component(exdate, comp);
if ((icaltime_is_date(exdatetime) &&
icaltime_compare_date_only(*recurtime, exdatetime) == 0) ||
......@@ -945,12 +945,21 @@ void icalcomponent_foreach_recurrence(icalcomponent *comp,
struct icalrecurrencetype recur = icalproperty_get_rrule(rrule);
icalrecur_iterator *rrule_itr = icalrecur_iterator_new(recur, dtstart);
struct icaltimetype rrule_time;
while (rrule_itr) {
struct icaltimetype rrule_time = icalrecur_iterator_next(rrule_itr);
if (!rrule_itr) continue;
if (icaltime_is_null_time(rrule_time))
break;
if (recur.count == 0) {
icaltimetype mystart = start;
/* make sure we include any recurrence that ends in timespan */
icaltime_adjust(&mystart, 0, 0, 0, -(int)dtduration);
icalrecur_iterator_set_start(rrule_itr, mystart);
}
for (rrule_time = icalrecur_iterator_next(rrule_itr);
!icaltime_is_null_time(rrule_time);
rrule_time = icalrecur_iterator_next(rrule_itr)) {
/* if we have iterated past end time,
then no need to check any further */
......@@ -1417,43 +1426,6 @@ void icalcomponent_set_dtstart(icalcomponent *comp, struct icaltimetype v)
}
}
/** @brief Get a DATE or DATE-TIME property as an icaltime
*
* If the property is a DATE-TIME with a timezone parameter and a
* corresponding VTIMEZONE is present in the component, the
* returned component will already be in the correct timezone;
* otherwise the caller is responsible for converting it.
*
* FIXME this is useless until we can flag the failure
*/
static struct icaltimetype icalcomponent_get_datetime(icalcomponent *comp, icalproperty *prop)
{
icalcomponent *c;
icalparameter *param;
struct icaltimetype ret;
ret = icalvalue_get_datetime(icalproperty_get_value(prop));
if ((param = icalproperty_get_first_parameter(prop, ICAL_TZID_PARAMETER)) != NULL) {
const char *tzid = icalparameter_get_tzid(param);
icaltimezone *tz = NULL;
for (c = comp; c != NULL; c = icalcomponent_get_parent(c)) {
tz = icalcomponent_get_timezone(c, tzid);
if (tz != NULL)
break;
}
if (tz == NULL)
tz = icaltimezone_get_builtin_timezone_from_tzid(tzid);
if (tz != NULL)
ret = icaltime_set_timezone(&ret, tz);
}
return ret;
}
/** @brief Get DTSTART property as an icaltime
*
* If DTSTART is a DATE-TIME with a timezone parameter and a
......@@ -1473,7 +1445,7 @@ struct icaltimetype icalcomponent_get_dtstart(icalcomponent *comp)
return icaltime_null_time();
}
return icalcomponent_get_datetime(comp, prop);
return icalproperty_get_datetime_with_component(prop, comp);
}
/** @brief Get DTEND property as an icaltime
......@@ -1496,7 +1468,7 @@ struct icaltimetype icalcomponent_get_dtend(icalcomponent *comp)
struct icaltimetype ret = icaltime_null_time();
if (end_prop != 0) {
ret = icalcomponent_get_datetime(comp, end_prop);
ret = icalproperty_get_datetime_with_component(end_prop, comp);
} else if (dur_prop != 0) {
struct icaltimetype start = icalcomponent_get_dtstart(inner);
......@@ -1678,7 +1650,7 @@ void icalcomponent_set_comment(icalcomponent *comp, const char *v)
icalcomponent_add_property(inner, prop);
}
icalproperty_set_summary(prop, v);
icalproperty_set_comment(prop, v);
}
const char *icalcomponent_get_comment(icalcomponent *comp)
......@@ -1713,7 +1685,7 @@ void icalcomponent_set_uid(icalcomponent *comp, const char *v)
icalcomponent_add_property(inner, prop);
}
icalproperty_set_summary(prop, v);
icalproperty_set_uid(prop, v);
}
const char *icalcomponent_get_uid(icalcomponent *comp)
......@@ -2495,7 +2467,7 @@ struct icaltimetype icalcomponent_get_due(icalcomponent *comp)
icalproperty *dur_prop = icalcomponent_get_first_property(inner, ICAL_DURATION_PROPERTY);
if (due_prop != 0) {
return icalcomponent_get_datetime(comp, due_prop);
return icalproperty_get_datetime_with_component(due_prop, comp);
} else if (dur_prop != 0) {
struct icaltimetype start = icalcomponent_get_dtstart(inner);
......
......@@ -71,9 +71,16 @@ LIBICAL_ICAL_EXPORT void icalcomponent_remove_property(icalcomponent *component,
LIBICAL_ICAL_EXPORT int icalcomponent_count_properties(icalcomponent *component,
icalproperty_kind kind);
/**
* Sets the parent icalcomponent for the specified icalproperty @p property.
* @since 3.0
*/
LIBICAL_ICAL_EXPORT void icalproperty_set_parent(icalproperty *property,
icalcomponent *component);
/**
* Returns the parent @p icalcomponent for the specified @p icalproperty.
*/
LIBICAL_ICAL_EXPORT icalcomponent *icalproperty_get_parent(const icalproperty *property);
/* Iterate through the properties */
......@@ -183,13 +190,13 @@ LIBICAL_ICAL_EXPORT void icalcomponent_set_dtstart(icalcomponent *comp, struct i
LIBICAL_ICAL_EXPORT struct icaltimetype icalcomponent_get_dtstart(icalcomponent *comp);
/* For the icalcomponent routines only, dtend and duration are tied
together. If you call the set routine for one and the other exists,
the routine will calculate the change to the other. That is, if
there is a DTEND and you call set_duration, the routine will modify
DTEND to be the sum of DTSTART and the duration. If you call a get
routine for one and the other exists, the routine will calculate
the return value. If you call a set routine and neither exists, the
routine will create the apcompriate comperty */
together. If you call the get routine for one and the other exists,
the routine will calculate the return value. That is, if there is a
DTEND and you call get_duration, the routine will return the difference
between DTEND and DTSTART. However, if you call a set routine for
one and the other exists, no action will be taken and icalerrno will
be set to ICAL_MALFORMEDDATA_ERROR. If you call a set routine and
neither exists, the routine will create the appropriate property. */
LIBICAL_ICAL_EXPORT struct icaltimetype icalcomponent_get_dtend(icalcomponent *comp);
......@@ -273,6 +280,10 @@ LIBICAL_ICAL_EXPORT void icalcomponent_foreach_recurrence(icalcomponent *comp,
span, void *data),
void *callback_data);
/**
* Normalizes (reorders and sorts the properties) the specified icalcomponent @p comp.
* @since 3.0
*/
LIBICAL_ICAL_EXPORT void icalcomponent_normalize(icalcomponent *comp);
/*************** Type Specific routines ***************/
......
......@@ -65,11 +65,30 @@ struct icalparameter_map
<insert_code_here>
int icalparameter_kind_is_valid(const icalparameter_kind kind)
{
int i = 0;
int num_params = (int)(sizeof(parameter_map) / sizeof(parameter_map[0]));
if (kind == ICAL_ANY_PARAMETER) {
return 0;
}
num_params--;
do {
if (parameter_map[i].kind == kind) {
return 1;
}
} while (i++ < num_params);
return 0;
}
const char *icalparameter_kind_to_string(icalparameter_kind kind)
{
int i;
int i, num_params;
for (i = 0; parameter_map[i].kind != ICAL_NO_PARAMETER; i++) {
num_params = (int)(sizeof(parameter_map) / sizeof(parameter_map[0]));
for (i = 0; i < num_params; i++) {
if (parameter_map[i].kind == kind) {
return parameter_map[i].name;
}
......@@ -131,12 +150,13 @@ icalvalue_kind icalparameter_value_to_value_kind(icalparameter_value value)
const char *icalparameter_enum_to_string(int e)
{
int i;
int i, num_params;
icalerror_check_arg_rz(e >= ICALPARAMETER_FIRST_ENUM, "e");
icalerror_check_arg_rz(e <= ICALPARAMETER_LAST_ENUM, "e");
for (i = 0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++) {
num_params = (int)(sizeof(icalparameter_map) / sizeof(icalparameter_map[0]));
for (i = 0; i < num_params; i++) {
if (e == icalparameter_map[i].enumeration) {
return icalparameter_map[i].str;
}
......@@ -147,11 +167,12 @@ const char *icalparameter_enum_to_string(int e)
int icalparameter_string_to_enum(const char *str)
{
int i;
int i, num_params;
icalerror_check_arg_rz(str != 0, "str");
for (i = 0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++) {
num_params = (int)(sizeof(icalparameter_map) / sizeof(icalparameter_map[0]));
for (i = 0; i < num_params; i++) {
if (strcasecmp(str, icalparameter_map[i].str) == 0) {
return icalparameter_map[i].enumeration;
}
......@@ -164,17 +185,19 @@ icalparameter *icalparameter_new_from_value_string(icalparameter_kind kind, cons
{
struct icalparameter_impl *param = 0;
int found_kind = 0;
int i;
int i, num_params;
icalerror_check_arg_rz((val != 0), "val");
/* Search through the parameter map to find a matching kind */
param = icalparameter_new_impl(kind);
if (!param)
if (!param) {
return 0;
}
for (i = 0; icalparameter_map[i].kind != ICAL_NO_PARAMETER; i++) {
num_params = (int)(sizeof(icalparameter_map) / sizeof(icalparameter_map[0]));
for (i = 0; i < num_params; i++) {
if (kind == icalparameter_map[i].kind) {
found_kind = 1;
if (strcasecmp(val, icalparameter_map[i].str) == 0) {
......
......@@ -22,10 +22,10 @@
#include "icalderivedproperty.h"
#include "icalproperty.h"
#include "icalproperty_p.h"
#include "icalcomponent.h"
#include "icalerror.h"
#include "icalmemory.h"
#include "icaltimezone.h"
#include <string.h>
......@@ -74,20 +74,28 @@ struct icalproperty_enum_map
int icalproperty_kind_is_valid(const icalproperty_kind kind)
{
int i = 0;
int num_props = (int)(sizeof(property_map) / sizeof(property_map[0]));
if (kind == ICAL_ANY_PROPERTY) {
return 0;
}
num_props--;
do {
if (property_map[i].kind == kind)
if (property_map[i].kind == kind) {
return 1;
} while (property_map[i++].kind != ICAL_NO_PROPERTY);
}
} while (i++ < num_props);