diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 (patch) | |
tree | 67208f7c145782a7e90b123b982ca78d88cc2c87 /libkcal/libical/doc/UsingLibical.lyx | |
download | tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.tar.gz tdepim-460c52653ab0dcca6f19a4f492ed2c5e4e963ab0.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'libkcal/libical/doc/UsingLibical.lyx')
-rw-r--r-- | libkcal/libical/doc/UsingLibical.lyx | 2578 |
1 files changed, 2578 insertions, 0 deletions
diff --git a/libkcal/libical/doc/UsingLibical.lyx b/libkcal/libical/doc/UsingLibical.lyx new file mode 100644 index 000000000..c29a61f6e --- /dev/null +++ b/libkcal/libical/doc/UsingLibical.lyx @@ -0,0 +1,2578 @@ +#LyX 1.1 created this file. For more info see http://www.lyx.org/ +\lyxformat 2.16 +\textclass article +\language default +\inputencoding latin1 +\fontscheme default +\graphics default +\paperfontsize default +\spacing single +\papersize Default +\paperpackage a4 +\use_geometry 0 +\use_amsmath 0 +\paperorientation portrait +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\defskip medskip +\quotes_language english +\quotes_times 2 +\papercolumns 1 +\papersides 1 +\paperpagestyle default + +\layout Title + +Using Libical +\layout Author + +Eric Busboom (eric@softwarestudio.org) +\layout Date + +January 2001 +\layout Standard + + +\begin_inset LatexCommand \tableofcontents{} + +\end_inset + + +\layout Section + +Introduction +\layout Standard + +Libical is an Open Source implementation of the iCalendar protocols 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. + +\layout Standard + +Libical implements RFC2445, RFC2446 and some of RFC2447 and the CAP draft. + +\layout Standard + +This documentation assumes that you are familiar with the iCalendar standards + RFC2445 and RFC2446. + these specifications are online on the CALSCH webpage at: +\layout LyX-Code + +http://www.imc.org/ietf-calendar/ +\layout Subsection + +The libical project +\layout Standard + +This code is under active development. + If you would like to contribute to the project, you can contact me, Eric + Busboom, at eric@softwarestudio.org. + The project has a webpage at +\layout LyX-Code + +http://softwarestudio.org/libical/index.html +\layout Standard + +and a mailing list that you can join by sending the following mail: +\layout LyX-Code + +To: minimalist@softwarestudio.org +\layout LyX-Code + +Subject: subscribe libical +\layout Subsection + +License +\layout Standard + +The code and datafiles in this distribution are licensed under the Mozilla + Public License. + See http://www.mozilla.org/NPL/MPL-1.0.html for a copy of the license. + Alternately, you may use libical under the terms of the GNU Library General + Public License. + See http://www.fsf.org/copyleft/lesser.html for a copy of the LGPL. +\layout Standard + +This dual license ensures that the library can be incorporated into both + proprietary code and GPL'd programs, and will benefit from improvements + made by programmers in both realms. + I will only accept changes into my version of the library if they are similarly + dual-licensed. +\layout Subsection + +Example Code +\layout Standard + +A lot of the documentation for this library is in the form of example code. + These examples are in the +\begin_inset Quotes eld +\end_inset + +examples +\begin_inset Quotes erd +\end_inset + + directory of the distribution. + Also look in +\begin_inset Quotes eld +\end_inset + +src/test +\begin_inset Quotes erd +\end_inset + + for additional annotated examples. + +\layout Section + +Building and Installing the Library +\layout Standard + +Libical uses autoconf to generate makefiles. + It should built with no adjustments on Linux, FreeBSD and Solaris under + gcc. + Some version have been successfully been build on MacOS, Solaris, UnixWare, + And Tru64 UNIX without gcc, but you may run into problems with a particular + later version. + +\layout Standard + +For a more complete guide to building the library, see the README file in + the distribution. + +\layout Standard + + +\begin_inset Quotes eld +\end_inset + +make install +\begin_inset Quotes erd +\end_inset + + will install the libraries and header files for three modules: libical, + libicalss. + and libicalvcal. + If you build shared objects, then these files will be installed: +\layout Itemize + +ical.h +\layout Itemize + +libical.a +\layout Itemize + +libical.so +\layout Itemize + +icalss.h +\layout Itemize + +libicalss.a +\layout Itemize + +libicalss.so +\layout Itemize + +icalvcal.h +\layout Itemize + +libicalvcal.a +\layout Itemize + +libicalvcal.so +\layout Standard + +The header files ical.h and icalss.h are combined header files, generated + by concatenating together all of the header files in src/libical and src/libica +lss respectively. + +\layout Section + +Structure +\layout Standard + +The iCal calendar model is based on four types of objects: components, propertie +s, values and parameters. + +\layout Standard + +Properties are the fundamental unit of information in iCal, and they work + a bit like a hash entry, with a constant key and a variable value. + Properties may also have modifiers, called parameters. + In the iCal content line +\layout LyX-Code + +ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com +\layout Standard + +The property name is +\begin_inset Quotes eld +\end_inset + +ORGANIZER, +\begin_inset Quotes erd +\end_inset + + the value of the property is +\begin_inset Quotes eld +\end_inset + +mrbig@host.com +\begin_inset Quotes erd +\end_inset + + and the +\begin_inset Quotes eld +\end_inset + +ROLE +\begin_inset Quotes erd +\end_inset + + parameter specifies that Mr Big is the chair of the meetings associated + with this property. + +\layout Standard + +Components are groups of properties that represent the core objects of a + calendar system, such as events or timezones. + Components are delimited by +\begin_inset Quotes eld +\end_inset + +BEGIN +\begin_inset Quotes erd +\end_inset + + and +\begin_inset Quotes eld +\end_inset + +END +\begin_inset Quotes erd +\end_inset + + tags. + +\layout Standard +\added_space_bottom 0.3cm +When a component is sent across a network, if it is un-encrypted, it will + look something like: +\layout LyX-Code + +BEGIN:VCALENDAR +\layout LyX-Code + +METHOD:REQUEST +\layout LyX-Code + +PRODID: -//hacksw/handcal//NONSGML v1.0//EN +\layout LyX-Code + +BEGIN:VEVENT +\layout LyX-Code + +DTSTAMP:19980309T231000Z +\layout LyX-Code + +UID:guid-1.host1.com +\layout LyX-Code + +ORGANIZER;ROLE=CHAIR:MAILTO:mrbig@host.com +\layout LyX-Code + +ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP: +\layout LyX-Code + + MAILTO:employee-A@host.com +\layout LyX-Code + +DESCRIPTION:Project XYZ Review Meeting +\layout LyX-Code + +CATEGORIES:MEETING +\layout LyX-Code + +CLASS:PUBLIC +\layout LyX-Code + +CREATED:19980309T130000Z +\layout LyX-Code + +SUMMARY:XYZ Project Review +\layout LyX-Code + +DTSTART;TZID=US-Eastern:19980312T083000 +\layout LyX-Code + +DTEND;TZID=US-Eastern:19980312T093000 +\layout LyX-Code + +LOCATION:1CP Conference Room 4350 +\layout LyX-Code + +END:VEVENT +\layout LyX-Code + +END:VCALENDAR +\layout Standard + +Note that components can be nested; this example has both a VCALENDAR and + a VEVENT component, one nested inside the other. + +\layout Standard + +The main goal of Libical is to offer a structured, type-safe to create, + access and manipulate components and their properties, values and parameters. + +\layout Subsection + +Core iCal classes +\layout Standard + +Libical is an object-based, data-oriented library. + There are no real-objects, but the way the routines are named and organized + results in the same sort of encapsulations and abstraction that are major + features of Object-Orieted languages. + Nearly all of the routines in the library are associated with an opaque + data types and perform some operation on that data type. + For instnace, a Property is declared as: +\layout LyX-Code + +icalproperty *prop; +\layout Standard + +Icalproperty is typedef'd to void, so the only way to manipulate it is through + the accessor routines, all of which have a form similar to: +\layout LyX-Code + +char* icalproperty_as_ical_string(icalproperty* prop); +\layout Standard + +That is, the name of the 'class' is the first word in the routine name, + and the first parameter is a pointer to the 'object.' +\layout Standard + +Although the library does not actually have classes, we will use those terms + since the behavior of these associations of data and routines is very similar + to a class. + +\layout Subsubsection + +Properties +\layout LyX-Code + +icalproperty *prop; +\layout Standard + +Properties are represented with the icalproperty class and its many +\begin_inset Quotes eld +\end_inset + +derived +\begin_inset Quotes erd +\end_inset + + classes with on +\begin_inset Quotes eld +\end_inset + +derived +\begin_inset Quotes erd +\end_inset + + class per property type in RFC2445. + Again, there is no actual inheritance relations, but there are clusters + of routines that make this term useful. + A property is a container for a single value and a set of parameters. + +\layout Subsubsection + +Components +\layout LyX-Code + +icalcomponent *comp; +\layout Standard + +In libical, components are represented with the icalcomponent class. + Icalcomponent is a container for a set of other components and properties. +\layout Subsubsection + +Values +\layout LyX-Code + +icalvalue *value; +\layout Standard + +Values are represented in a similar way to properties; a base class and + many +\begin_inset Quotes eld +\end_inset + +derived +\begin_inset Quotes eld +\end_inset + + classes. + A value is essentially a abstract handle on a single fundamental type, + a structure or a union. + You probably will never use a value directly, since for most operations + you can get to its data through the property that holds it. + +\layout Subsubsection + +Parameters +\layout LyX-Code + +icalparameter *param; +\layout Standard + +Parameters are represetned in a similar way to properties, except that they + contain only one value +\layout Subsection + +Other elements of libical +\layout Standard + +In addition to the core iCal classes, libical has many other types, structures, + classes that aid in creating and using iCal components. + +\layout Subsubsection + +Enumerations and types +\layout Standard + +Libical is strongly typed, so every component, property, parameter, and + value type has an enumeration, and some have an associated structure or + union. + +\layout Subsubsection + +The parser +\layout Standard + +The libical parser offers a variety of ways to convert RFC2445 text into + a libical iinsteral component structure. + the parser can parse blocks of text as a string, or it can parse lin-by-line. +\layout Subsubsection + +Error objects +\layout Standard + +Libical has a substantial error reporting system for both programming errors + and component usage errors. + +\layout Subsubsection + +Memory Management +\layout Standard + +Since many of libicals interfaces return strings, the library has its own + memory management system to elimiate the need to free every string returned + from the libraru. + +\layout Subsubsection + +Storage classes +\layout Standard + +The library also offers several classes to store components to flies, memory + or databases. + +\layout Section + +Differences From RFCs +\layout Standard + +Libical has been designed to follow the standards as closely as possible, + so that the key objects in the standards are also key objects in the library. + However, there are a few areas where the specifications are (arguably) + irregular, and following them exactly would result in an unfriendly interface. + These deviations make libical easier to use by maintaining a self-similar + interface. + +\layout Subsection + +Pseudo Components +\layout Standard + +Libical defines components for groups of properties that look and act like + components, but are not defined as components in the specification. + XDAYLIGHT and XSTANDARD are notable examples. + These pseudo components group properties within the VTIMEZONE components. + For instanace, the timezone properties associated with daylight savings + time starts with +\begin_inset Quotes eld +\end_inset + +BEGIN:DAYLIGHT +\begin_inset Quotes erd +\end_inset + + and ends with +\begin_inset Quotes eld +\end_inset + +END:DAYLIGHT, just like other components, but is not defined as a component + in RFC2445. + ( See RFC2445, page 61 ) In Libical,this grouping is represented by the + XDAYLIGHT component. + Standard iCAL components all start with the letter +\begin_inset Quotes eld +\end_inset + +V, +\begin_inset Quotes erd +\end_inset + + while pseudo components start with +\begin_inset Quotes erd +\end_inset + +X. +\begin_inset Quotes erd +\end_inset + + +\layout Standard + +There are also pseudo components that are conceptually derived classes of + VALARM. + RFC2446 defines what properties may be included in each component, and + for VALARM, the set of properties it may have depends on the value of the + ACTION property. + +\layout Standard + +For instance, if a VALARM component has an ACTION property with the value + of +\begin_inset Quotes eld +\end_inset + +AUDIO, +\begin_inset Quotes erd +\end_inset + + the component must also have an +\begin_inset Quotes eld +\end_inset + +ATTACH +\begin_inset Quotes erd +\end_inset + + property. + However, if the ACTION value is +\begin_inset Quotes eld +\end_inset + +DISPLAY, +\begin_inset Quotes erd +\end_inset + + the component must have a DESCRIPTION property. + +\layout Standard + +To handle these various, complex restrictions, libical has pseudo components + for each type of alarm: XAUDIOALARM, XDISPLAYALARM, XEMAILALARM and XPROCEDUREA +LARM. + +\layout Subsection + +Combined Values +\layout Standard + +Many values can take more than one type. + TRIGGER, for instance, can have a value type of with DURATION or of DATE-TIME. + These multiple types make it difficult to create routines to return the + value associated with a property. + +\layout Standard + +It is natural to have interfaces that would return the value of a property, + but it is cumbersome for a single routine to return multiple types. + So, in libical, properties that can have multiple types are given a single + type that is the union of their RFC2445 types. + For instance, in libical, the value of the TRIGGER property resolves to + struct icaltriggertype. + This type is a union of a DURATION and a DATE-TIME. + +\layout Subsection + +Multi-Valued Properties +\layout Standard + +Some properties, such as CATEGORIES have only one value type, but each CATEGORIE +S property can have multiple value instances. + This also results in a cumbersome interface -- CATEGORIES accessors would + have to return a list while all other accessors returned a single value. + In libical, all properties have a single value, and multi-valued properties + are broken down into multiple single valued properties during parsing. + That is, an input line like, +\layout LyX-Code + +CATEGORIES: work, home +\layout Standard + +becomes in libical's internal representation +\layout LyX-Code + +CATEGORIES: work +\layout LyX-Code + +CATEGORIES: home +\layout Standard + +Oddly, RFC2445 allows some multi-valued properties ( like FREEBUSY ) to + exist as both a multi-values property and as multiple single value properties, + while others ( like CATEGORIES ) can only exist as single multi-valued + properties. + This makes the internal representation for CATEGORIES illegal. + However when you convert a component to a string, the library will collect + all of the CATEGORIES properties into one. + +\layout Section + +Using libical +\layout Subsection + +Creating Components +\layout Standard + +There are three ways to create components in Libical: +\layout Itemize + +Create individual components, properties and parameters and assemble them + into structures +\layout Itemize + +Build complete components with nested vaargs calls +\layout Itemize + +Parse bits of text +\layout Itemize + +Parse entire files +\layout Subsubsection + +Constructor Interfaces +\layout Standard + +Using constructor interfaces, you create each of the objects separately + and then assemble them in to components: +\layout LyX-Code + +icalcomponent *event; +\layout LyX-Code + +icalproperty *prop; +\layout LyX-Code + +icalparameter *param; +\layout LyX-Code + +struct icaltimetype atime; +\layout LyX-Code + +\layout LyX-Code + +event = icalcomponent_new(ICAL_VEVENT_COMPONENT); +\layout LyX-Code + +prop = icalproperty_new_dtstamp(atime); +\layout LyX-Code + +icalcomponent_add_property(event, prop); +\layout LyX-Code + +\layout LyX-Code + +prop = icalproperty_new_uid(''guid-1.host1.com'') ); +\layout LyX-Code + +icalcomponent_add_property(event,prop); +\layout LyX-Code + +\layout LyX-Code + +prop=icalproperty_new_organizer(''mrbig@host.com''); +\layout LyX-Code + +param = icalparameter_new_role(ICAL_ROLE_CHAIR) +\layout LyX-Code + +icalproperty_add_parameter(prop, param); +\layout LyX-Code + +\layout LyX-Code + +icalcomponent_add_property(event,prop); +\layout Standard + +Notice that libical uses a semi-object-oriented style of interface. + Most things you work with are objects, that are instantiated with a constructor + that has +\begin_inset Quotes eld +\end_inset + +new +\begin_inset Quotes erd +\end_inset + + in the name. + Also note that, other than the object reference, most structure data is + passed in to libical routines by value. + Libical has some complex but very regular memory handling rules. + These are detailed in section +\begin_inset LatexCommand \ref{sec:memory} + +\end_inset + +. +\layout Standard + +If any of the constructors fail, they will return 0. + If you try to insert 0 into a property or component, or use a zero-valued + object reference, libical will either silently ignore the error or will + abort with an error message. + This behavior is controlled by a compile time flag (ICAL_ERRORS_ARE_FATAL), + and will abort by default. + +\layout Subsubsection + +vaargs Constructors +\layout Standard + +There is another way to create complex components, which is arguably more + elegant, if you are not horrified by varargs. + The varargs constructor interface allows you to create intricate components + in a single block of code. + Here is the previous examples in the vaargs style. + +\layout LyX-Code + + calendar = +\layout LyX-Code + + icalcomponent_vanew( +\layout LyX-Code + + ICAL_VCALENDAR_COMPONENT, +\layout LyX-Code + + icalproperty_new_version(''2.0''), +\layout LyX-Code + + icalproperty_new_prodid( +\layout LyX-Code + + ''-//RDU Software//NONSGML HandCal//EN''), +\layout LyX-Code + + icalcomponent_vanew( +\layout LyX-Code + + ICAL_VEVENT_COMPONENT, +\layout LyX-Code + + icalproperty_new_dtstamp(atime), +\layout LyX-Code + + icalproperty_new_uid(''guid-1.host1.com''), +\layout LyX-Code + + icalproperty_vanew_organizer( +\layout LyX-Code + + ''mrbig@host.com''), +\layout LyX-Code + + icalparameter_new_role(ICAL_ROLE_CHAIR), +\layout LyX-Code + + 0 +\layout LyX-Code + + ), +\layout LyX-Code + + icalproperty_vanew_attendee( +\layout LyX-Code + + ''employee-A@host.com'', +\layout LyX-Code + + icalparameter_new_role( +\layout LyX-Code + + ICAL_ROLE_REQPARTICIPANT), +\layout LyX-Code + + icalparameter_new_rsvp(1), +\layout LyX-Code + + icalparameter_new_cutype(ICAL_CUTYPE_GROUP), +\layout LyX-Code + + 0 +\layout LyX-Code + + ), +\layout LyX-Code + + icalproperty_new_location( +\layout LyX-Code + + "1CP Conference Room 4350"), +\layout LyX-Code + + 0 +\layout LyX-Code + + ), +\layout LyX-Code + + 0 +\layout LyX-Code + + ); +\layout Standard + +This form is similar to the constructor form , except that the constructors + have +\begin_inset Quotes eld +\end_inset + +vanew +\begin_inset Quotes erd +\end_inset + + instead of +\begin_inset Quotes eld +\end_inset + +new +\begin_inset Quotes erd +\end_inset + + in the name. + The arguments are similar too, except that the component constructor can + have a list of properties, and the property constructor can have a list + of parameters. + Be sure to terminate every list with a '0', or your code will crash, if + you are lucky. + +\layout Subsubsection + +Parsing Text +\layout Standard + +Several routines are available for generating objects from text. + For properties, use: +\layout LyX-Code + +icalproperty* p; +\layout LyX-Code + +p = icalproperty_new_from_string("DTSTART:19970101T120000Z +\backslash +n"); +\layout Standard + +For parameters, use: +\layout LyX-Code + +icalparameter *param +\layout LyX-Code + +param = icalparameter_new_from_string("PARTSTAT=ACCEPTED"); +\layout Standard + +The final way to create components will probably be the most common; you + can create components from RFC2445 compliant text. + If you have the string in memory, use +\layout LyX-Code + +icalcomponent* icalcomponent_new_from_string(char* str); +\layout Standard + +If the string contains only one component, the routine will return the component + in libical form. + If the string contains multiple components, the multiple components will + be returned as the children of an ICAL_XROOT_COMPONENT component. + This routine is identical to ( and actually uses ) icalparser_parse_string(char +* str). +\layout Standard + +Parsing a whole string may seem wasteful if you want to pull a large component + off of the network or from a file; you may prefer to parse the component + line by line. + This is possible too by using: +\layout LyX-Code + +icalparser* icalparser_new(); +\layout LyX-Code + +void icalparser_free(icalparser* parser); +\layout LyX-Code + +icalparser_get_line(parser,read_stream); +\layout LyX-Code + +icalparser_add_line(parser,line); +\layout LyX-Code + +icalparser_set_gen_data(parser,stream) +\layout Standard + +These routines will construct a parser object to which you can add lines + of input and retrieve any components that the parser creates from the input. + These routines work by specifing an adaptor routine to get string data + from a source. + For an example: +\layout LyX-Code + +char* read_stream(char *s, size_t size, void *d) +\layout LyX-Code + +{ +\layout LyX-Code + + char *c = fgets(s,size, (FILE*)d); +\layout LyX-Code + + return c; +\layout LyX-Code + +} +\layout LyX-Code + +main() { +\layout LyX-Code + + char* line; +\layout LyX-Code + + icalcomponent *c; +\layout LyX-Code + + icalparser *parser = icalparser_new(); +\layout LyX-Code + + FILE* stream = fopen(argv[1],"r"); +\layout LyX-Code + + icalparser_set_gen_data(parser,stream); +\layout LyX-Code + + do{ +\layout LyX-Code + + line = icalparser_get_line(parser,read_stream); +\layout LyX-Code + + c = icalparser_add_line(parser,line); +\layout LyX-Code + + if (c != 0){ +\layout LyX-Code + + printf("%s",icalcomponent_as_ical_string(c)); +\layout LyX-Code + + icalparser_claim(parser); +\layout LyX-Code + + printf(" +\backslash +n--------------- +\backslash +n"); +\layout LyX-Code + + icalcomponent_free(c); +\layout LyX-Code + + } +\layout LyX-Code + + } while ( line != 0); +\layout LyX-Code + +} +\layout Standard + +The parser object parameterizes the routine used to get input lines with + icalparser_set_gen_data() and +\emph on + +\emph default +icalparser_get_line(). + In this example, the routine read_stream() will fetch the next line from + a stream, with the stream passed in as the void* parameter d. + The parser calls read_stream() from icalparser_get_line(), but it also + needs to know what stream to use. + This is set by the call to icalparser_set_gen_data(). + By using a different routine for read_stream or passing in different data + with icalparser_set_gen_data, you can connect to any data source. + +\layout Standard + +Using the same mechanism, other implementations could read from memory buffers, + sockets or other interfaces. + +\layout Standard + +Since the example code is a very common way to use the parser, there is + a convenience routine; +\layout LyX-Code + +icalcomponent* icalparser_parse(icalparser *parser, +\layout LyX-Code + + char* (*line_gen_func)(char *s, size_t size, void* d)) +\layout Standard + +To use this routine, you still must construct the parser object and pass + in a reference to a line reading routine. + If the parser can create a single component from the input, it will return + a pointer to the newly constructed component. + If the parser can construct multiple components from the input, it will + return a reference to an XROOT component ( of type ICAL_XROOT_COMPONENT.) + This XROOT component will hold all of the components constructed from the + input as children. + +\layout Subsection + +Accessing Components +\layout Standard + +Given a reference to a component, you probably will want to access the propertie +s, parameters and values inside. + Libical interfaces let you find sub-components, add and remove sub-components, + and do the same three operations on properties. + +\layout Subsubsection + +Finding Components +\layout Standard + +To find a sub-component of a component, use: +\layout LyX-Code + +icalcomponent* icalcomponent_get_first_component( +\layout LyX-Code + + icalcomponent* component, +\layout LyX-Code + + icalcomponent_kind kind); +\layout Standard + +This routine will return a reference to the first component of the type + 'kind.' The key kind values, listed in icalenums.h are: +\layout LyX-Code + +ICAL_ANY_COMPONENT +\layout LyX-Code + +ICAL_VEVENT_COMPONENT +\layout LyX-Code + +ICAL_VTODO_COMPONENT +\layout LyX-Code + +ICAL_VJOURNAL_COMPONENT +\layout LyX-Code + +ICAL_VCALENDAR_COMPONENT +\layout LyX-Code + +ICAL_VFREEBUSY_COMPONENT +\layout LyX-Code + +ICAL_VALARM_COMPONENT +\layout Standard + +These are only the most common components; there are many more listed in + icalenums.h. +\layout Standard + +As you might guess, if there is more than one subcomponent of the type you + have chosen, this routine will return only the first. + to get at the others, you need to iterate through the component. + +\layout Subsubsection + +Iterating Through Components +\layout Standard + +Iteration requires a second routine to get the next subcomponent after the + first: +\layout LyX-Code + +icalcomponent* icalcomponent_get_next_component( +\layout LyX-Code + + icalcomponent* component, +\layout LyX-Code + + icalcomponent_kind kind); +\layout Standard + +With the 'first' and 'next' routines, you can create a for loop to iterate + through all of a components subcomponents +\layout LyX-Code + + for(c = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT); +\layout LyX-Code + + c != 0; +\layout LyX-Code + + c = icalcomponent_get_next_component(comp,ICAL_ANY_COMPONENT)) +\layout LyX-Code + +{ +\layout LyX-Code + + do_something(c); +\layout LyX-Code + +} +\layout Standard + +This code bit wil iterate through all of the subcomponents in 'comp' but + you can select a specific type of component by changing ICAL_ANY_COMPONENT + to another component type. +\layout Subsubsection + +Using Component Iterators +\layout Standard + +The iteration model in the previous section requires the component to keep + the state of the iteration. + So, you could not use this model to perform a sorting operations, since + you'd need two iterators and there is only space for one. + If you ever call icalcomponent_get_first_component() when an iteration + is in progress, the pointer will be reset to the beginning. + +\layout Standard + +To solve this problem, there are also external iterators for components. + The routines associated with these external iterators are: +\layout LyX-Code + +icalcompiter icalcomponent_begin_component(icalcomponent* component, icalcompone +nt_kind kind); +\layout LyX-Code + +icalcompiter icalcomponent_end_component(icalcomponent* component, icalcomponent +_kind kind); +\layout LyX-Code + +icalcomponent* icalcompiter_next(icalcompiter* i); +\layout LyX-Code + +icalcomponent* icalcompiter_prior(icalcompiter* i); +\layout LyX-Code + +icalcomponent* icalcompiter_deref(icalcompiter* i); +\layout Standard + +The _begin_() and _end_() routines return a new iterator that points to + the beginning and ending of the list of subcomponent for the given component, + and the kind argument works like the kind argument for internal iterators. + +\layout Standard + +After creating an iterators, use _next_() and _prior_() to step forward + and backward through the list and get the component that the iterator points + to, and use _deref() to return the component that the iterator points to + without moving the iterator. + All routines will return 0 when they move to point off the end of the list. + +\layout Standard + +Here is an example of a loop using these routines: +\layout LyX-Code + +for( +\layout LyX-Code + + i = icalcomponent_begin_component(impl->cluster,ICAL_ANY_COMPONENT); + +\layout LyX-Code + + icalcompiter_deref(&i)!= 0; +\layout LyX-Code + + icalcompiter_next(&i) +\layout LyX-Code + +) { +\layout LyX-Code + + icalcomponent *this = icalcompiter_deref(&i); +\layout LyX-Code + +} +\layout Subsubsection + +Removing Components +\layout Standard + +Removing an element from a list while iterating through the list with the + internal iterators can cause problems, since you will probably be removing + the element that the internal iterator points to. + The _remove() routine will keep the iterator valid by moving it to the + next component, but in a normal loop, this will result in two advances + per iteration, and you will remove only every other component. + To avoid the problem, you will need to step the iterator ahead of the + element you are going to remove, like this: +\layout LyX-Code + +for(c = icalcomponent_get_first_component(parent_comp,ICAL_ANY_COMPONENT); + +\layout LyX-Code + + c != 0; +\layout LyX-Code + + c = next +\layout LyX-Code + +{ +\layout LyX-Code + + next = icalcomponent_get_next_component(parent_comp,ICAL_ANY_COMPONENT); +\layout LyX-Code + + icalcomponent_remove_component(parent_comp,c); +\layout LyX-Code + +} +\layout Standard + +Another way to remove components is to rely on the side effect of icalcomponent_ +remove_component: if component iterator in the parent component is pointing + to the child that will be removed, it will move the iterator to the component + after the child. + The following code will exploit this behavior: +\layout LyX-Code + +icalcomponent_get_first_component(parent_comp,ICAL_VEVENT_COMPONENT); +\layout LyX-Code + +while((c=icalcomponent_get_current_component(c)) != 0 ){ +\layout LyX-Code + + if(icalcomponent_isa(c) == ICAL_VEVENT_COMPONENT){ +\layout LyX-Code + + icalcomponent_remove_component(parent_comp,inner); +\layout LyX-Code + + } else { +\layout LyX-Code + + icalcomponent_get_next_component(parent_comp,ICAL_VEVENT_COMPONENT); + +\layout LyX-Code + + } +\layout LyX-Code + +} +\layout Subsubsection + +Working with properties and parameters +\layout Standard + +Finding, iterating and removing properties works the same as it does for + components, using the property-specific or parameter-specific interfaces: + +\layout LyX-Code + +icalproperty* icalcomponent_get_first_property( +\layout LyX-Code + + icalcomponent* component, +\layout LyX-Code + + icalproperty_kind kind); +\layout LyX-Code + +icalproperty* icalcomponent_get_next_property( +\layout LyX-Code + + icalcomponent* component, +\layout LyX-Code + + icalproperty_kind kind); +\layout LyX-Code + +void icalcomponent_add_property( +\layout LyX-Code + + icalcomponent* component, +\layout LyX-Code + + icalproperty* property); +\layout LyX-Code + +void icalcomponent_remove_property( +\layout LyX-Code + + icalcomponent* component, +\layout LyX-Code + + icalproperty* property); +\layout Standard + +For parameters: +\layout LyX-Code + +icalparameter* icalproperty_get_first_parameter( +\layout LyX-Code + + icalproperty* prop, +\layout LyX-Code + + icalparameter_kind kind); +\layout LyX-Code + +icalparameter* icalproperty_get_next_parameter( +\layout LyX-Code + + icalproperty* prop, +\layout LyX-Code + + icalparameter_kind kind); +\layout LyX-Code + +void icalproperty_add_parameter( +\layout LyX-Code + + icalproperty* prop, +\layout LyX-Code + + icalparameter* parameter); +\layout LyX-Code + +void icalproperty_remove_parameter( +\layout LyX-Code + + icalproperty* prop, +\layout LyX-Code + + icalparameter_kind kind); +\layout Standard + +Note that since there should be only one parameter of each type in a property, + you will rarely need to use icalparameter_get_nect_paameter. +\layout Subsubsection + +Working with values +\layout Standard + +Values are typically part of a property, although they can exist on their + own. + You can manipulate them either as part of the property or independently. +\layout Standard + +The most common way to work with values to is to manipulate them from they + properties that contain them. + This involves fewer routine calls and intermediate variables than working + with them independently, and it is type-safe. + +\layout Standard + +For each property, there are a _get_ and a _set_ routine that access the + internal value. + For instanace, for the UID property, the routines are: +\layout LyX-Code + +void icalproperty_set_uid(icalproperty* prop, const char* v) +\layout LyX-Code + +const char* icalproperty_get_uid(icalproperty* prop) +\layout Standard + +For multi-valued properties, like ATTACH, the value type is usually a struct + or union that holds both possible types. + +\layout Standard + +If you want to work with the underlying value object, you can get and set + it with: +\layout LyX-Code + +icalvalue* icalproperty_get_value (icalproperty* prop) +\layout LyX-Code + +void icalproperty_set_value(icalproperty* prop, icalvalue* value); +\layout Standard + +Icalproperty_get_value() will return a reference that you can manipulate + with other icalvalue routines. + Most of the time, you will have to know what the type of the value is. + For instance, if you know that the value is a DATETIME type, you can manipulate + it with: +\layout LyX-Code + +struct icaltimetype icalvalue_get_datetime(icalvalue* value); +\layout LyX-Code + +void icalvalue_set_datetime(icalvalue* value, struct icaltimetype v); +\layout Standard + +When working with an extension property or value (and X-PROPERTY or a property + that has the parameter VALUE=x-name ) the value type is always a string. + To get and set the value, use: +\layout LyX-Code + +void icalproperty_set_x(icalproperty* prop, char* v); +\layout LyX-Code + +char* icalproperty_get_x(icalproperty* prop); +\layout Standard + +All X properties have the type of ICAL_X_PROPERTY, so you will need these + routines to get and set the name of the property: +\layout LyX-Code + +char* icalproperty_get_x_name(icalproperty* prop) +\layout LyX-Code + +void icalproperty_set_x_name(icalproperty* prop, char* name); +\layout Subsubsection + +Checking Component Validity +\layout Standard + +RFC 2446 defines rules for what properties must exist in a component to + be used for transferring scheduling data. + Most of these rules relate to the existence of properties relative to the + METHOD property, which declares what operation a remote receiver should + use to process a component. + For instance, if the METHOD is REQUEST and the component is a VEVENT, the + sender is probably asking the receiver to join in a meeting. + In this case, RFC2446 says that the component must specify a start time + (DTSTART) and list the receiver as an attendee (ATTENDEE). + +\layout Standard + +Libical can check these restrictions with the routine: +\layout LyX-Code + +int icalrestriction_check(icalcomponent* comp); +\layout Standard + +This routine returns 0 if the component does not pass RFC2446 restrictions, + or if the component is malformed. + The component you pass in +\emph on +must +\emph default + be a VCALENDAR, with one or more children, like the examples in RFC2446. + +\layout Standard + +When this routine runs, it will insert new properties into the component + to indicate any errors it finds. + See section 6.5.3, X-LIC-ERROR for more information about these error properties. + +\layout Subsubsection + +Converting Components to Text +\layout Standard + +To create an RFC2445 compliant text representation of an object, use one + of the *_as_ical_string() routines: +\layout LyX-Code + +char* icalcomponent_as_ical_string (icalcomponent* component) +\layout LyX-Code + +char* icalproperty_as_ical_string (icalproperty* property) +\layout LyX-Code + +char* icalparameter_as_ical_string (icalparameter* parameter) +\layout LyX-Code + +char* icalvalue_as_ical_string (icalvalue* value) +\layout Standard + +In most cases, you will only use icalcomponent_as_ical_string (), since + it will cascade and convert all of the parameters, properties and values + that are attached to the root component. +\layout Standard + +Icalproperty_as_ical_string() will terminate each line with the RFC2445 + specified line terminator +\begin_inset Quotes eld +\end_inset + + +\backslash + +\backslash +n +\begin_inset Quotes erd +\end_inset + + However, if you compile with the symbol ICAL_UNIX_NEWLINE undefined, ( + it is defined by default) it will terminate lines with +\begin_inset Quotes eld +\end_inset + + +\backslash + +\backslash +n +\backslash + +\backslash +r +\begin_inset Quotes erd +\end_inset + + +\layout Standard + +Remember that the string returned by these routines is owned by the library, + and will eventually be re-written. + You should copy it if you want to preserve it. + +\layout Subsection + +Time +\layout Subsubsection + +Time structure +\layout Standard + +LIbical defines it's own time structure for storing all dates and times. + It would have been nice to re-use the C library's +\emph on +struct tm, +\emph default +but that structure does not differentiate between dates and times, and between + local time and UTC. + The libical structure is: +\layout LyX-Code + +struct icaltimetype { +\layout LyX-Code + + int year; +\layout LyX-Code + + int month; +\layout LyX-Code + + int day; +\layout LyX-Code + + int hour; +\layout LyX-Code + + int minute; +\layout LyX-Code + + int second; +\layout LyX-Code + + int is_utc; /* 1-> time is in UTC timezone */ +\layout LyX-Code + + int is_date; /* 1 -> interpret this as date. + */ }; +\layout Standard + +The year, month, day, hour, minute and second fields hold the broken-out + time values. + The is_utc field distinguishes between times in UTC and a local time zone. + The is_date field indicates if the time should be interpreted only as a + date. + If it is a date, the hour, minute and second fields are assumed to be zero, + regardless of their actual vaules. + +\layout Subsubsection + +Creating time structures +\layout Standard + +There are several ways to create a new icaltimetype structure: +\layout LyX-Code + +struct icaltimetype icaltime_from_string(const char* str); +\layout LyX-Code + +struct icaltimetype icaltime_from_timet(time_t v, int is_date); +\layout LyX-Code + +\layout Standard + +Icaltime_from_string takes any RFC2445 compliant time string: +\layout LyX-Code + +struct icaltimetype tt = icaltime_from_string("19970101T103000"); +\layout Standard + +Icaltime_from_timet takes a timet value, representing seconds past the POSIX + epoch, and a flag to indicate if the time is a date. + Dates have an identical structure to a time, but the time portion ( hours, + minuts and seconds ) is always 00:00:00. + Dates act differently in sorting an comparision, and they have a different + string representation in RFC2445. + +\layout Subsubsection + +Time manipulating routines +\layout Standard + +The null time value is used to indicate that the data in the structure is + not a valid time. +\layout LyX-Code + +struct icaltimetype icaltime_null_time(void); +\layout LyX-Code + +int icaltime_is_null_time(struct icaltimetype t); +\layout Standard + +It is sensible for the broken-out time fields to contain values that are + not permitted in an ISO compliant time string. + For instance, the seconds field can hold values greater than 59, and the + hours field can hold values larger than 24. + The excessive values will be rolled over into the next larger field when + the structure is normalized. + +\layout LyX-Code + +struct icaltimetype icaltime_normalize(struct icaltimetype t); +\layout Standard + +Normalizing allows you to do arithmetic operations on time values. + +\layout LyX-Code + +struct icaltimetype tt = icaltime_from_string( +\begin_inset Quotes eld +\end_inset + +19970101T103000 +\begin_inset Quotes erd +\end_inset + +); +\layout LyX-Code + +tt.days +=3 +\layout LyX-Code + +tt.second += 70; +\layout LyX-Code + +tt = icaltime_normalize(tt); +\layout Standard + +There are several routines to get the day of the week or month, etc, from + a time structure. +\layout LyX-Code + +short icaltime_day_of_year(struct icaltimetype t); +\layout LyX-Code + +struct icaltimetype icaltime_from_day_of_year(short doy, short year); +\layout LyX-Code + +short icaltime_day_of_week(struct icaltimetype t); +\layout LyX-Code + +short icaltime_start_doy_of_week(struct icaltimetype t); +\layout LyX-Code + +short icaltime_week_number(short day_of_month, short month, short year); +\layout LyX-Code + +struct icaltimetype icaltime_from_week_number(short week_number, short year); +\layout LyX-Code + +short icaltime_days_in_month(short month,short year); +\layout Standard + +Two routines convert time structures to and from the number of seconds since + the POSIX epoch. + The is_date field indicates whether or not the hour, minute and second + fields should be used in the conversion. +\layout LyX-Code + +struct icaltimetype icaltime_from_timet(time_t v, int is_date); +\layout LyX-Code + +time_t icaltime_as_timet(struct icaltimetype); +\layout Standard + +The compare routine works exactly like strcmp, but on time structures. + +\layout LyX-Code + +int icaltime_compare(struct icaltimetype a,struct icaltimetype b); +\layout Standard + +The following routines convert between UTC and a named timezone. + The tzid field must be a timezone name from the Olsen database, such as + +\begin_inset Quotes eld +\end_inset + +America/Los_Angeles. +\begin_inset Quotes erd +\end_inset + + +\layout Standard + +The utc_offset routine returns the offset of the named time zone from UTC, + in seconds. + +\layout Standard + +The tt parameter in the following routines indicates the date on which the + conversion should be made. + The tt parameter is necessary because timezones have many different rules + for when daylight savings time is used, and these rules can change over + time. + So, for a single timezone one year may have daylight savings time on March + 15, but for other years March 15 may be standard time, and some years may + have standard time all year. + +\layout LyX-Code + +int icaltime_utc_offset(struct icaltimetype tt, char* tzid); +\layout LyX-Code + +int icaltime_local_utc_offset(); +\layout LyX-Code + +struct icaltimetype icaltime_as_utc(struct icaltimetype tt,char* tzid); +\layout LyX-Code + +struct icaltimetype icaltime_as_zone(struct icaltimetype tt,char* tzid); +\layout LyX-Code + +struct icaltimetype icaltime_as_local(struct icaltimetype tt); +\layout Subsection + +Storing Objects +\layout Standard + +The libical distribution includes a separate library, libicalss, that allows + you to store iCal component data to disk in a variety of ways. + This library also includes code to implement the CSTP protocol of CAP and + has some routines for deciphering incomming messages. + +\layout Standard + +The file storage routines are organized in an inheritance heirarchy that + is rooted in icalset, with the derived class icalfileset and icaldirset. + Icalfileset stores components to a file, while icaldirset stores components + to multiple files, one per month based on DTSTAMP. + Other storages classess, for storage to a heap or a mysql database are + planned for the future. + +\layout Standard + +All of the icalset derived classes have the same interface: +\layout LyX-Code + +\layout LyX-Code + +icaldirset* icaldirset_new(const char* path); +\layout LyX-Code + +void icaldirset_free(icaldirset* store); +\layout LyX-Code + +const char* icaldirset_path(icaldirset* store); +\layout LyX-Code + +void icaldirset_mark(icaldirset* store); +\layout LyX-Code + +icalerrorenum icaldirset_commit(icaldirset* store); +\layout LyX-Code + +icalerrorenum icaldirset_add_component(icaldirset* store, icalcomponent* + comp); +\layout LyX-Code + +icalerrorenum icaldirset_remove_component(icaldirset* store, icalcomponent* + comp); +\layout LyX-Code + +int icaldirset_count_components(icaldirset* store, icalcomponent_kind kind); +\layout LyX-Code + +icalerrorenum icaldirset_select(icaldirset* store, icalcomponent* gauge); +\layout LyX-Code + +void icaldirset_clear(icaldirset* store); +\layout LyX-Code + +icalcomponent* icaldirset_fetch(icaldirset* store, const char* uid); +\layout LyX-Code + +int icaldirset_has_uid(icaldirset* store, const char* uid); +\layout LyX-Code + +icalcomponent* icaldirset_fetch_match(icaldirset* set, icalcomponent *c); +\layout LyX-Code + +icalerrorenum icaldirset_modify(icaldirset* store, icalcomponent *oldc, + icalcomponent *newc); +\layout LyX-Code + +icalcomponent* icaldirset_get_current_component(icaldirset* store); +\layout LyX-Code + +icalcomponent* icaldirset_get_first_component(icaldirset* store); +\layout LyX-Code + +icalcomponent* icaldirset_get_next_component(icaldirset* store); +\layout Subsubsection + +Creating a new set +\layout Standard + +You can create a new set from either the base class or the direved class. + From the base class use one of: +\layout LyX-Code + +icalset* icalset_new_file(const char* path); +\layout LyX-Code + +icalset* icalset_new_dir(const char* path); +\layout LyX-Code + +icalset* icalset_new_heap(void); +\layout LyX-Code + +icalset* icalset_new_mysql(const char* path); +\layout Standard + +You can also create a new set based on the derived class, For instance, + with icalfileset: +\layout LyX-Code + +icalfileset* icalfileset_new(const char* path); +\layout LyX-Code + +icalfileset* icalfileset_new_open(const char* path, int flags, mode_t mode); +\layout Standard + +Icaset_new_file is identical to icalfileset_new. + BOth routines will open an existing file for readinga and writing, or create + a new file if it does not exist. + Icalfilset_new_open takes the same arguments as the open() system routine + and behaves in the same way. + +\layout Standard + +The icalset and icalfilset objects are somewhat interchangable -- you can + use an icalfileset* as an argument to any of the icalset routines. +\layout Standard + +The following examples will all use icalfileset routines; using the other + icalset derived classess will be similar. + +\layout Subsubsection + +Adding, Finding and Removing Components +\layout Standard + +To add components to a set, use: +\layout LyX-Code + +icalerrorenum icalfileset_add_component(icalfileset* cluster, icalcomponent* + child); +\layout Standard + +The fileset keeps an inmemory copy of the components, and this set must + be written back to the file ocassionally. + There are two routines to manage this: +\layout LyX-Code + +void icalfileset_mark(icalfileset* cluster); +\layout LyX-Code + +icalerrorenum icalfileset_commit(icalfileset* cluster); +\layout Standard + +Icalfileset_mark indicates that the in-memory components have changed. + Calling the _add_component routine will call _mark automatically, but you + may need to call it yourself if you have made a change to an existing component. + The _commit routine writes the data base to disk, but only if it is marked. + The _commit routine is called automatically when the icalfileset is freed. + +\layout Standard + +To iterate through the components in a set, use: +\layout LyX-Code + +icalcomponent* icalfileset_get_first_component(icalfileset* cluster); +\layout LyX-Code + +icalcomponent* icalfileset_get_next_component(icalfileset* cluster); +\layout LyX-Code + +icalcomponent* icalfileset_get_current_component (icalfileset* cluster); + +\layout Standard + +These routines work like the corresponding routines from icalcomponent, + except that their output is filtered through a gauge. + A gauge is a test for the properties within a components; only components + that pass the test are returned. + A gauge can be constructed from a MINSQL string with: +\layout LyX-Code + +icalgauge* icalgauge_new_from_sql(char* sql); +\layout Standard + +Then, you can add the gauge to the set with : +\layout LyX-Code + +icalerrorenum icalfileset_select(icalfileset* store, icalgauge* gauge); +\layout Standard + +Here is an example that puts all of these routines together: +\layout LyX-Code + + +\latex no_latex +void test_fileset() +\layout LyX-Code + + +\latex no_latex +{ +\layout LyX-Code + + +\latex no_latex + icalfileset *fs; +\layout LyX-Code + + +\latex no_latex + icalcomponent *c; +\layout LyX-Code + + +\latex no_latex + int i; +\layout LyX-Code + + +\latex no_latex + char *path = "test_fileset.ics"; +\layout LyX-Code + + +\latex no_latex + icalgauge *g = icalgauge_new_from_sql( +\layout LyX-Code + + +\latex no_latex + "SELECT * FROM VEVENT WHERE DTSTART > '20000103T120000Z' AND DTSTART + <= '20000106T120000Z'"); +\layout LyX-Code + + +\latex no_latex + +\layout LyX-Code + + +\latex no_latex +fs = icalfileset_new(path); +\layout LyX-Code + + +\layout LyX-Code + + +\latex no_latex +for (i = 0; i!= 10; i++){ +\layout LyX-Code + + +\latex no_latex + c = make_component(i); +\latex default + /* Make a new component where DTSTART has month of i */ +\layout LyX-Code + + +\latex no_latex + icalfileset_add_component(fs,c); +\layout LyX-Code + + +\latex no_latex + } +\layout LyX-Code + +\layout LyX-Code + + +\latex no_latex + icalfileset_commit(fs); +\latex default + /* Write to disk */ +\layout LyX-Code + +\layout LyX-Code + + +\latex no_latex + icalfileset_select(fs,g); +\latex default + /* Set the gauge to filter components */ +\layout LyX-Code + + +\latex no_latex + +\layout LyX-Code + + +\latex no_latex + for (c = icalfileset_get_first_component(fs); +\layout LyX-Code + + +\latex no_latex + c != 0; +\layout LyX-Code + + +\latex no_latex + c = icalfileset_get_next_component(fs)){ +\layout LyX-Code + + +\latex no_latex + struct icaltimetype t = icalcomponent_get_dtstart(c); +\layout LyX-Code + + +\latex no_latex + +\layout LyX-Code + + +\latex no_latex + printf("%s +\backslash +n",icaltime_as_ctime(t)); +\layout LyX-Code + + +\latex no_latex + } +\layout LyX-Code + + +\latex no_latex +icalfileset_free(fs); +\layout LyX-Code + + +\latex no_latex +} +\layout Subsubsection + +Other routines +\layout Standard + +There are several other routines in the icalset interface, but they not + fully implemented yet. + +\layout Subsection + + +\begin_inset LatexCommand \label{sec:memory} + +\end_inset + +Memory Management +\layout Standard + +Libical relies heavily on dynamic allocation for both the core objects and + for the strings used to hold values. + Some of this memory the library caller owns and must free, and some of + the memory is managed by the library. + Here is a summary of the memory rules. + +\layout Description + +1) If the function name has "new" in it, the caller gets control of the + memory. + ( such as icalcomponent_new(), or icalproperty_new_clone() ) +\layout Description + +2) If you got the memory from a routine with new in it, you must call the + corresponding *_free routine to free the memory. + ( Use icalcomponent_free() to free objects created with icalcomponent_new()) + +\layout Description + +3) If the function name has "add" in it, the caller is transferring control + of the memory to the routine. + ( icalproperty_add_parameter() ) +\layout Description + +4) If the function name has "remove" in it, the caller passes in a pointer + to an object and after the call returns, the caller owns the object. + So, before you call icalcomponent_remove_property(comp,foo), you do not + own "foo" and after the call returns, you do. + +\layout Description + +5) If the routine returns a string, libical owns the memory and will put + it on a ring buffer to reclaim later. + For example, icalcomponent_as_ical_string(). + You'd better strdup() it if you want to keep it, and you don't have to + delete it. + +\layout Subsection + +Error Handling +\layout Standard + +Libical has several error handling mechanisms for the various types of programmi +ng, semantic and syntactic errors you may encounter. +\layout Subsubsection + +Return values +\layout Standard + +Many library routines signal errors through their return values. + All routines that return a pointer, such as icalcomponent_new(), will return + 0 ( zero ) on a fatal error. + Some routines will return a value of enum icalerrorenum. + +\layout Subsubsection + +icalerrno +\layout Standard + +Most routines will set the global error value icalerrno on errors. + This variable is an enumeration; permissible values can be found in libical/ica +lerror.h. + If the routine returns an enum icalerrorenum, then the return value will + be the same as icalerrno. + You can use icalerror_strerror() to get a string that describes the error. + The enumerations are: +\layout Standard +\added_space_top 0.3cm \added_space_bottom 0.3cm \align center \LyXTable +multicol5 +12 2 0 0 -1 -1 -1 -1 +1 1 0 0 +1 0 0 0 +1 0 0 0 +1 0 0 0 +1 0 0 0 +1 0 0 0 +1 0 0 0 +1 0 0 0 +1 0 0 0 +1 0 0 0 +1 0 0 0 +1 1 0 0 +2 1 0 "" "" +2 1 1 "" "" +0 8 1 0 0 0 0 "" "" +0 8 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" + + +\newline + +\newline +ICAL_BADARG_ERROR +\newline +One of the argument to a routine was bad. + Typically for a null pointer. +\newline +ICAL_NEWFAILED_ERROR +\newline +A new() or malloc() failed +\newline +ICAL_MALFORMEDDATA_ERROR +\newline +An input string was not in the correct format +\newline +ICAL_PARSE_ERROR +\newline +the parser failed to parse an incomming component +\newline +ICAL_INTERNAL_ERROR +\newline +Largely equivalent to an assert; it indicates a bug in the libical code +\newline +ICAL_FILE_ERROR +\newline +A file operation failed. + Check errno for more detai +\newline +ICAL_ALLOCATION_ERROR +\newline + +\newline +ICAL_NO_ERROR +\newline +No error has occurred +\newline +ICAL_TIMEDOUT_ERROR +\newline +Failed to acquire a lock on a file, or the CSTP protocol timed out. + +\newline +ICAL_MULTIPLEINCLUSION_ERROR +\newline + +\newline +ICAL_UNKNOWN_ERROR +\newline + +\layout Subsubsection + +X-LIC-ERROR and X-LIC-INVALID-COMPONENT +\layout Standard + +The library handles semantic and syntactic errors in components by inserting + errors properties into the components. + If the parser cannot parse incoming text ( a syntactic error ) or if the + icalrestriction_check() routine indicates that the component does not meet + the requirements of RFC2446 ( a semantic error) the library will insert + properties of the type X-LIC-ERROR to describe the error. + Here is an example of the error property: +\layout LyX-Code + +X-LIC-ERROR;X-LIC-ERRORTYPE=INVALID_ITIP :Failed iTIP restrictions for property + DTSTART. + +\layout LyX-Code + +Expected 1 instances of the property and got 0 +\layout Standard + +This error resulted from a call to icalrestriction_check(), which discovered + that the component does not have a DTSTART property, as required by RFC2445. + +\layout Standard + +There are a few routines to manipulate error properties: +\layout Standard +\LyXTable +multicol5 +10 2 0 0 -1 -1 -1 -1 +1 1 0 0 +0 0 0 0 +0 1 1 0 +0 0 0 0 +0 1 1 0 +0 1 0 0 +0 1 1 0 +0 1 0 0 +0 1 1 0 +0 1 1 0 +2 1 1 "" "" +2 1 1 "3in" "" +0 2 1 1 0 0 0 "" "" +0 8 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 1 0 1 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 1 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 1 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 1 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 1 1 0 1 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 1 1 0 1 "" "" +0 2 1 0 0 0 0 "" "" +0 2 1 1 0 0 1 "" "" + +Routine +\newline +Purpose +\newline +void icalrestriction_check() +\newline +Check a component against RFC2446 and insert +\newline + +\newline +error properties to indicate non compliance +\newline +int icalcomponent_count_errors() +\newline +Return the number of error properties +\newline + +\newline +in a component +\newline +void icalcomponent_strip_errors() +\newline +Remove all error properties in as +\newline + +\newline +component +\newline +void icalcomponent_convert_errors() +\newline +Convert some error properties into +\newline + +\newline +REQUESTS-STATUS proprties to indicate the inability to +\newline + +\newline +process the component as an iTIP request. + +\layout Standard + +The types of errors are listed in icalerror.h. + They are: +\layout LyX-Code + +ICAL_XLICERRORTYPE_COMPONENTPARSEERROR +\layout LyX-Code + +ICAL_XLICERRORTYPE_PARAMETERVALUEPARSEERROR +\layout LyX-Code + +ICAL_XLICERRORTYPE_PARAMETERNAMEPARSEERROR +\layout LyX-Code + +ICAL_XLICERRORTYPE_PROPERTYPARSEERROR +\layout LyX-Code + +ICAL_XLICERRORTYPE_VALUEPARSEERROR +\layout LyX-Code + +ICAL_XLICERRORTYPE_UNKVCALPROP +\layout LyX-Code + +ICAL_XLICERRORTYPE_INVALIDITIP +\layout Standard + +The libical parser will generate the error that end in PARSEERROR when it + encounters garbage in the input steam. + ICAL_XLICERRORTYPE_INVALIDITIP is inserted by icalrestriction_check(), + and ICAL_XLICERRORTYPE_UNKVCALPROP is generated by icalvcal_convert() when + it encounters a vCal property that it cannot convert or does not know about. + +\layout Standard + +Icalcomponent_convert_errors() converts some of the error properties in + a component into REQUEST-STATUS properties that indicate a failure. + As of libical version0.18, this routine only convert *PARSEERROR errors + and it always generates a 3.x ( failure ) code. + This makes it more of a good idea than a really useful bit of code. + +\layout Subsubsection + +ICAL_ERRORS_ARE_FATAL and icalerror_errors_are_fatal +\layout Standard + +If the global variable icalerror_errors_are_fatal is set to 1, then any + error condition will cause the program to abort. + The abort occurs in icalerror_set_errno(), and is done with an assert(0) + if NDEBUG is undefined, and with icalerror_crash_here if NDEBUG is defined. + The default value of icalerror_errors_are_fatal is 1 when ICAL_ERRORS_ARE_FATAL + is defined, and 0 otherwise. + Since ICAL_ERRORS_ARE_FATAL is defined by default, icalerror_errors_are_fatal + is also defined by default. + +\layout Subsection + +Naming Standard +\layout Standard + +Structures that you access with the +\begin_inset Quotes eld +\end_inset + +struct +\begin_inset Quotes erd +\end_inset + + keyword, such as +\begin_inset Quotes eld +\end_inset + +struct icaltimetype +\begin_inset Quotes erd +\end_inset + + are things that you are allowed to see inside and poke at. + +\layout Standard + +Structures that you access though a typedef, such as +\begin_inset Quotes eld +\end_inset + +icalcomponent +\begin_inset Quotes erd +\end_inset + + are things where all of the data is hidden. + +\layout Standard + +Component names that start with +\begin_inset Quotes eld +\end_inset + +V +\begin_inset Quotes erd +\end_inset + + are part of RFC 2445 or another iCal standard. + Component names that start with +\begin_inset Quotes eld +\end_inset + +X +\begin_inset Quotes erd +\end_inset + + are also part of the spec, but they are not actually components in the + spec. + However, they look and act like components, so they are components in libical. + Names that start with +\begin_inset Quotes eld +\end_inset + +XLIC +\begin_inset Quotes erd +\end_inset + + or +\begin_inset Quotes eld +\end_inset + +X-LIC +\begin_inset Quotes erd +\end_inset + + are not part of any iCal spec. + They are used internally by libical. + +\layout Standard + +Enums that identify a component, property, value or parameter end with +\begin_inset Quotes eld +\end_inset + +_COMPONENT, +\begin_inset Quotes erd +\end_inset + + +\begin_inset Quotes eld +\end_inset + +_PROPERTY, +\begin_inset Quotes erd +\end_inset + + +\begin_inset Quotes eld +\end_inset + +_VALUE, +\begin_inset Quotes erd +\end_inset + + or +\begin_inset Quotes eld +\end_inset + +_PARAMETER +\begin_inset Quotes erd +\end_inset + +s +\layout Standard + +Enums that identify a parameter value have the name of the parameter as + the second word. + For instance: ICAL_ROLE_REQPARTICIPANT or ICAL_PARTSTAT_ACCEPTED. +\layout Standard + +The enums for the parts of a recurarance rule and request statuses are irregular. + +\layout Section + +Hacks and Bugs +\layout Standard + +There are a lot of hacks in the library -- bits of code that I am not proud + of and should probably be changed. + These are marked with the comment string +\begin_inset Quotes eld +\end_inset + +HACK. +\begin_inset Quotes erd +\end_inset + + +\the_end |