Monotone-Parent: 4962ab3aba4ec12e6e80cec90be3bb7824bb7b56
Monotone-Revision: 53a7cdc42e8710e661ce709242c9857ae53542ff Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2007-01-31T17:11:29 Monotone-Branch: ca.inverse.sogomaint-2.0.2
parent
829f96f301
commit
b234f02a47
|
@ -0,0 +1,482 @@
|
|||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
|
@ -0,0 +1,4 @@
|
|||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
|
||||
Contact: info@skyrix.com
|
|
@ -0,0 +1,109 @@
|
|||
/* CardElement.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef CARDELEMENT_H
|
||||
#define CARDELEMENT_H
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
@class NSArray;
|
||||
@class NSDictionary;
|
||||
@class NSMutableArray;
|
||||
@class NSMutableDictionary;
|
||||
@class NSString;
|
||||
|
||||
@class CardGroup;
|
||||
|
||||
@interface CardElement : NSObject <NSCopying>
|
||||
{
|
||||
NSString *tag;
|
||||
NSMutableArray *values;
|
||||
NSMutableDictionary *attributes;
|
||||
NSString *group;
|
||||
CardGroup *parent;
|
||||
}
|
||||
|
||||
+ (id) elementWithTag: (NSString *) aTag;
|
||||
|
||||
+ (id) simpleElementWithTag: (NSString *) aTag
|
||||
value: (NSString *) aValue;
|
||||
|
||||
+ (id) simpleElementWithTag: (NSString *) aTag
|
||||
singleType: (NSString *) aType
|
||||
value: (NSString *) aValue;
|
||||
|
||||
+ (id) elementWithTag: (NSString *) aTag
|
||||
attributes: (NSDictionary *) someAttributes
|
||||
values: (NSArray *) someValues;
|
||||
|
||||
- (void) setParent: (CardGroup *) aParent;
|
||||
- (CardGroup *) parent;
|
||||
|
||||
- (void) setTag: (NSString *) aTag;
|
||||
|
||||
- (void) setGroup: (NSString *) aGroup;
|
||||
- (NSString *) group;
|
||||
|
||||
- (void) addValue: (NSString *) aValue;
|
||||
- (void) addValues: (NSArray *) someValues;
|
||||
|
||||
- (void) setValue: (unsigned int) anInt
|
||||
to: (NSString *) aValue;
|
||||
- (NSString *) value: (unsigned int) anInt;
|
||||
|
||||
- (void) setNamedValue: (NSString *) aValueName
|
||||
to: (NSString *) aValue;
|
||||
- (NSString *) namedValue: (NSString *) aValueName;
|
||||
|
||||
- (void) setValue: (unsigned int) anInt
|
||||
ofAttribute: (NSString *) anAttribute
|
||||
to: (NSString *) aValue;
|
||||
- (NSString *) value: (unsigned int) anInt
|
||||
ofAttribute: (NSString *) anAttribute;
|
||||
|
||||
- (void) addAttribute: (NSString *) anAttribute
|
||||
value: (NSString *) aValue;
|
||||
- (void) addAttributes: (NSDictionary *) someAttributes;
|
||||
- (void) removeValue: (NSString *) aValue
|
||||
fromAttribute: (NSString *) anAttribute;
|
||||
|
||||
- (void) addType: (NSString *) aType;
|
||||
|
||||
- (NSString *) tag;
|
||||
- (NSArray *) values;
|
||||
- (NSDictionary *) attributes;
|
||||
- (BOOL) hasAttribute: (NSString *) aType
|
||||
havingValue: (NSString *) aValue;
|
||||
|
||||
- (BOOL) isVoid;
|
||||
|
||||
- (NSString *) versitString;
|
||||
|
||||
- (CardGroup *) searchParentOfClass: (Class) parentClass;
|
||||
|
||||
- (CardElement *) elementWithClass: (Class) elementClass;
|
||||
- (void) setValuesAsCopy: (NSMutableArray *) someValues;
|
||||
- (void) setAttributesAsCopy: (NSMutableDictionary *) someAttributes;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* CARDELEMENT_H */
|
|
@ -0,0 +1,500 @@
|
|||
/* CardElement.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "NSArray+NGCards.h"
|
||||
#import "NSDictionary+NGCards.h"
|
||||
#import "CardVersitRenderer.h"
|
||||
|
||||
#import "CardElement.h"
|
||||
#import "CardGroup.h"
|
||||
|
||||
@implementation CardElement
|
||||
|
||||
+ (id) elementWithTag: (NSString *) aTag
|
||||
{
|
||||
id newElement;
|
||||
|
||||
newElement = [self new];
|
||||
[newElement autorelease];
|
||||
[newElement setTag: aTag];
|
||||
|
||||
return newElement;
|
||||
}
|
||||
|
||||
+ (id) simpleElementWithTag: (NSString *) aTag
|
||||
value: (NSString *) aValue
|
||||
{
|
||||
id newElement;
|
||||
|
||||
newElement = [self elementWithTag: aTag];
|
||||
[newElement addValue: aValue];
|
||||
|
||||
return newElement;
|
||||
}
|
||||
|
||||
+ (id) simpleElementWithTag: (NSString *) aTag
|
||||
singleType: (NSString *) aType
|
||||
value: (NSString *) aValue
|
||||
{
|
||||
id newElement;
|
||||
|
||||
newElement = [self simpleElementWithTag: aTag
|
||||
value: aValue];
|
||||
[newElement addType: aType];
|
||||
|
||||
return newElement;
|
||||
}
|
||||
|
||||
+ (id) elementWithTag: (NSString *) aTag
|
||||
attributes: (NSDictionary *) someAttributes
|
||||
values: (NSArray *) someValues
|
||||
{
|
||||
id newElement;
|
||||
|
||||
newElement = [self new];
|
||||
[newElement autorelease];
|
||||
[newElement setTag: aTag];
|
||||
[newElement addAttributes: someAttributes];
|
||||
[newElement addValues: someValues];
|
||||
|
||||
return newElement;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
parent = nil;
|
||||
tag = nil;
|
||||
group = nil;
|
||||
values = [NSMutableArray new];
|
||||
attributes = [NSMutableDictionary new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (tag)
|
||||
[tag release];
|
||||
[values release];
|
||||
[attributes release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void) setParent: (CardGroup *) aParent
|
||||
{
|
||||
parent = aParent;
|
||||
}
|
||||
|
||||
- (CardGroup *) parent
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
- (void) setTag: (NSString *) aTag
|
||||
{
|
||||
if (tag)
|
||||
[tag release];
|
||||
tag = aTag;
|
||||
if (tag)
|
||||
[tag retain];
|
||||
}
|
||||
|
||||
- (void) setGroup: (NSString *) aGroup
|
||||
{
|
||||
if (group)
|
||||
[group release];
|
||||
group = aGroup;
|
||||
if (group)
|
||||
[group retain];
|
||||
}
|
||||
|
||||
- (NSString *) group
|
||||
{
|
||||
return group;
|
||||
}
|
||||
|
||||
- (void) addValue: (NSString *) aValue
|
||||
{
|
||||
[values addObject: aValue];
|
||||
}
|
||||
|
||||
- (void) addValues: (NSArray *) someValues
|
||||
{
|
||||
[values addObjectsFromArray: someValues];
|
||||
}
|
||||
|
||||
- (void) addAttribute: (NSString *) anAttribute
|
||||
value: (NSString *) aType
|
||||
{
|
||||
NSMutableArray *attrValues;
|
||||
|
||||
attrValues = [attributes objectForCaseInsensitiveKey: anAttribute];
|
||||
if (!attrValues)
|
||||
{
|
||||
attrValues = [NSMutableArray new];
|
||||
[attrValues autorelease];
|
||||
[attributes setObject: attrValues forKey: anAttribute];
|
||||
}
|
||||
|
||||
[attrValues addObject: aType];
|
||||
}
|
||||
|
||||
- (void) removeValue: (NSString *) aValue
|
||||
fromAttribute: (NSString *) anAttribute
|
||||
{
|
||||
NSMutableArray *attrValues;
|
||||
NSString *currentValue;
|
||||
|
||||
attrValues = [attributes objectForCaseInsensitiveKey: anAttribute];
|
||||
if (attrValues)
|
||||
{
|
||||
currentValue = [attrValues valueForCaseInsensitiveString: aValue];
|
||||
while (currentValue)
|
||||
{
|
||||
[attrValues removeObject: currentValue];
|
||||
currentValue = [attrValues valueForCaseInsensitiveString: aValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) addAttributes: (NSDictionary *) someAttributes
|
||||
{
|
||||
NSEnumerator *keys;
|
||||
NSString *currentKey;
|
||||
NSMutableArray *oldValues;
|
||||
NSArray *newValues;
|
||||
|
||||
keys = [[someAttributes allKeys] objectEnumerator];
|
||||
currentKey = [keys nextObject];
|
||||
while (currentKey)
|
||||
{
|
||||
oldValues = [attributes objectForCaseInsensitiveKey: currentKey];
|
||||
newValues = [someAttributes objectForKey: currentKey];
|
||||
if (oldValues)
|
||||
[oldValues addObjectsFromArray: newValues];
|
||||
else
|
||||
[attributes setObject: newValues forKey: currentKey];
|
||||
currentKey = [keys nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) addType: (NSString *) aType
|
||||
{
|
||||
[self addAttribute: @"type" value: aType];
|
||||
}
|
||||
|
||||
- (NSString *) tag
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
|
||||
- (NSArray *) values
|
||||
{
|
||||
return values;
|
||||
}
|
||||
|
||||
- (NSDictionary *) attributes
|
||||
{
|
||||
return attributes;
|
||||
}
|
||||
|
||||
- (BOOL) hasAttribute: (NSString *) anAttribute
|
||||
havingValue: (NSString *) aValue
|
||||
{
|
||||
NSArray *attribute;
|
||||
|
||||
attribute = [attributes objectForCaseInsensitiveKey: anAttribute];
|
||||
|
||||
return (attribute && [attribute hasCaseInsensitiveString: aValue]);
|
||||
}
|
||||
|
||||
- (void) setValue: (unsigned int) anInt
|
||||
to: (NSString *) aValue
|
||||
{
|
||||
while ([values count] <= anInt)
|
||||
[self addValue: @""];
|
||||
[values replaceObjectAtIndex: anInt withObject: aValue];
|
||||
}
|
||||
|
||||
- (NSString *) value: (unsigned int) anInt
|
||||
{
|
||||
NSString *value;
|
||||
|
||||
if ([values count] <= anInt)
|
||||
value = @"";
|
||||
else
|
||||
value = [values objectAtIndex: anInt];
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
- (unsigned int) _namedValue: (NSString *) aValueName
|
||||
{
|
||||
NSString *prefix, *value;
|
||||
unsigned int count, max, result;
|
||||
|
||||
result = NSNotFound;
|
||||
|
||||
prefix = [NSString stringWithFormat: @"%@=", [aValueName uppercaseString]];
|
||||
max = [values count];
|
||||
count = 0;
|
||||
|
||||
while (result == NSNotFound && count < max)
|
||||
{
|
||||
value = [[values objectAtIndex: count] uppercaseString];
|
||||
if ([value hasPrefix: prefix])
|
||||
result = count;
|
||||
else
|
||||
count++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) setNamedValue: (NSString *) aValueName
|
||||
to: (NSString *) aValue
|
||||
{
|
||||
NSString *newValue;
|
||||
unsigned int index;
|
||||
|
||||
newValue = [NSString stringWithFormat: @"%@=%@",
|
||||
[aValueName uppercaseString],
|
||||
aValue];
|
||||
index = [self _namedValue: aValueName];
|
||||
if (index == NSNotFound)
|
||||
[self addValue: newValue];
|
||||
else
|
||||
{
|
||||
if (aValue)
|
||||
[self setValue: index to: newValue];
|
||||
else
|
||||
[values removeObjectAtIndex: index];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *) namedValue: (NSString *) aValueName
|
||||
{
|
||||
unsigned int index, equalSign;
|
||||
NSString *value;
|
||||
|
||||
index = [self _namedValue: aValueName];
|
||||
if (index == NSNotFound)
|
||||
value = @"";
|
||||
else
|
||||
{
|
||||
value = [values objectAtIndex: index];
|
||||
equalSign = [value indexOfString: @"="];
|
||||
if (equalSign != NSNotFound)
|
||||
value = [value substringFromIndex: equalSign + 1];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
- (void) setValue: (unsigned int) anInt
|
||||
ofAttribute: (NSString *) anAttribute
|
||||
to: (NSString *) aValue
|
||||
{
|
||||
NSMutableArray *attrValues;
|
||||
|
||||
attrValues = [attributes objectForCaseInsensitiveKey: anAttribute];
|
||||
if (!attrValues)
|
||||
{
|
||||
attrValues = [NSMutableArray new];
|
||||
[attrValues autorelease];
|
||||
[attributes setObject: attrValues forKey: anAttribute];
|
||||
}
|
||||
|
||||
while ([attrValues count] <= anInt)
|
||||
[attrValues addObject: @""];
|
||||
[attrValues replaceObjectAtIndex: anInt
|
||||
withObject: aValue];
|
||||
}
|
||||
|
||||
- (NSString *) value: (unsigned int) anInt
|
||||
ofAttribute: (NSString *) anAttribute
|
||||
{
|
||||
NSArray *attrValues;
|
||||
NSString *value;
|
||||
|
||||
attrValues = [attributes objectForCaseInsensitiveKey: anAttribute];
|
||||
if (attrValues && [attrValues count] > anInt)
|
||||
value = [attrValues objectAtIndex: anInt];
|
||||
else
|
||||
value = @"";
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
- (NSString *) description
|
||||
{
|
||||
NSArray *attrs;
|
||||
NSMutableString *str;
|
||||
unsigned int count, max;
|
||||
NSString *attr;
|
||||
|
||||
str = [NSMutableString stringWithCapacity:64];
|
||||
[str appendFormat:@"<%p[%@]:", self, NSStringFromClass([self class])];
|
||||
if (group)
|
||||
[str appendFormat: @"%@ (group: %@)\n", tag, group];
|
||||
else
|
||||
[str appendFormat: @"%@\n", tag, group];
|
||||
|
||||
attrs = [attributes allKeys];
|
||||
max = [attrs count];
|
||||
if (max > 0)
|
||||
{
|
||||
[str appendFormat: @"\n %d attributes: {\n", [attrs count]];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
attr = [attrs objectAtIndex: count];
|
||||
[str appendFormat: @" %@: %@\n",
|
||||
attr, [attributes objectForKey: attr]];
|
||||
}
|
||||
[str appendFormat: @"}"];
|
||||
}
|
||||
|
||||
max = [values count];
|
||||
if (max > 0)
|
||||
{
|
||||
[str appendFormat: @"\n %d values: {\n", [values count]];
|
||||
for (count = 0; count < max; count++)
|
||||
[str appendFormat: @" %@\n", [values objectAtIndex: count]];
|
||||
[str appendFormat: @"}"];
|
||||
}
|
||||
|
||||
[str appendString:@">"];
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
- (BOOL) isVoid
|
||||
{
|
||||
BOOL result;
|
||||
NSString *value;
|
||||
NSEnumerator *enu;
|
||||
|
||||
result = YES;
|
||||
|
||||
enu = [values objectEnumerator];
|
||||
value = [enu nextObject];
|
||||
while (value && result)
|
||||
{
|
||||
result = ([value length] == 0);
|
||||
value = [enu nextObject];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString *) versitString
|
||||
{
|
||||
CardVersitRenderer *renderer;
|
||||
NSString *string;
|
||||
|
||||
renderer = [CardVersitRenderer new];
|
||||
string = [renderer render: self];
|
||||
[renderer release];
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
- (CardElement *) elementWithClass: (Class) elementClass
|
||||
{
|
||||
CardElement *newElement;
|
||||
|
||||
if ([self isKindOfClass: elementClass])
|
||||
newElement = self;
|
||||
else
|
||||
{
|
||||
newElement = [elementClass new];
|
||||
[newElement autorelease];
|
||||
[newElement setTag: tag];
|
||||
[newElement setValuesAsCopy: values];
|
||||
[newElement setAttributesAsCopy: attributes];
|
||||
if (group)
|
||||
[newElement setGroup: group];
|
||||
if (parent)
|
||||
{
|
||||
[newElement setParent: parent];
|
||||
[parent replaceThisElement: self
|
||||
withThisOne: newElement];
|
||||
}
|
||||
}
|
||||
|
||||
return newElement;
|
||||
}
|
||||
|
||||
- (void) setValuesAsCopy: (NSMutableArray *) someValues
|
||||
{
|
||||
[values release];
|
||||
values = someValues;
|
||||
[values retain];
|
||||
}
|
||||
|
||||
- (void) setAttributesAsCopy: (NSMutableDictionary *) someAttributes
|
||||
{
|
||||
[attributes release];
|
||||
attributes = someAttributes;
|
||||
[attributes retain];
|
||||
}
|
||||
|
||||
- (CardGroup *) searchParentOfClass: (Class) parentClass
|
||||
{
|
||||
CardGroup *current;
|
||||
CardGroup *found;
|
||||
|
||||
found = nil;
|
||||
current = parent;
|
||||
while (current && !found)
|
||||
if ([current isKindOfClass: parentClass])
|
||||
found = current;
|
||||
else
|
||||
current = [current parent];
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* NSCopying */
|
||||
|
||||
- (id) copyWithZone: (NSZone *) aZone
|
||||
{
|
||||
CardElement *new;
|
||||
|
||||
new = [[self class] new];
|
||||
[new setTag: [tag copyWithZone: aZone]];
|
||||
[new setGroup: [group copyWithZone: aZone]];
|
||||
[new setParent: parent];
|
||||
[new setValuesAsCopy: [values copyWithZone: aZone]];
|
||||
[new setAttributesAsCopy: [attributes copyWithZone: aZone]];
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,39 @@
|
|||
/* CardGroup+iCal.h - this file is part of $PROJECT_NAME_HERE$
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef CARDGROUP_ICAL_H
|
||||
#define CARDGROUP_ICAL_H
|
||||
|
||||
@class NSString;
|
||||
@class NSCalendarDate;
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
@interface CardGroup (iCalExtensions)
|
||||
|
||||
- (void) setDate: (NSCalendarDate *) _value
|
||||
forDateTimeValue: (NSString *) valueName;
|
||||
- (NSCalendarDate *) dateForDateTimeValue: (NSString *) valueName;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* CARDGROUP_ICAL_H */
|
|
@ -0,0 +1,48 @@
|
|||
/* CardGroup+iCal.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import "iCalDateTime.h"
|
||||
|
||||
#import "CardGroup+iCal.h"
|
||||
|
||||
@implementation CardGroup (iCalExtensions)
|
||||
|
||||
- (void) setDate: (NSCalendarDate *) _value
|
||||
forDateTimeValue: (NSString *) valueName
|
||||
{
|
||||
iCalDateTime *dateValue;
|
||||
|
||||
dateValue = (iCalDateTime *) [self uniqueChildWithTag: valueName];
|
||||
|
||||
[dateValue setDateTime: _value];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) dateForDateTimeValue: (NSString *) valueName
|
||||
{
|
||||
iCalDateTime *dateValue;
|
||||
|
||||
dateValue = (iCalDateTime *) [self uniqueChildWithTag: valueName];
|
||||
|
||||
return [dateValue dateTime];
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,76 @@
|
|||
/* CardGroup.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef CARDGROUP_H
|
||||
#define CARDGROUP_H
|
||||
|
||||
#import "CardElement.h"
|
||||
|
||||
@class NSArray;
|
||||
@class NSMutableArray;
|
||||
@class NSString;
|
||||
|
||||
@interface CardGroup : CardElement <NSCopying>
|
||||
{
|
||||
NSMutableArray *children;
|
||||
}
|
||||
|
||||
+ (id) parseSingleFromSource: (id) source;
|
||||
+ (NSArray *) parseFromSource: (id) source;
|
||||
|
||||
+ (id) groupWithTag: (NSString *) aTag;
|
||||
+ (id) groupWithTag: (NSString *) aTag
|
||||
children: (NSArray *) someChildren;
|
||||
|
||||
- (Class) classForTag: (NSString *) tagClass;
|
||||
|
||||
- (CardElement *) uniqueChildWithTag: (NSString *) aTag;
|
||||
- (void) setUniqueChild: (CardElement *) aChild;
|
||||
|
||||
- (void) addChild: (CardElement *) aChild;
|
||||
- (void) addChildren: (NSArray *) someChildren;
|
||||
|
||||
- (NSArray *) children;
|
||||
- (NSArray *) childrenWithTag: (NSString *) aTag;
|
||||
- (NSArray *) childrenWithAttribute: (NSString *) anAttribute
|
||||
havingValue: (NSString *) aValue;
|
||||
- (NSArray *) childrenWithTag: (NSString *) aTag
|
||||
andAttribute: (NSString *) anAttribute
|
||||
havingValue: (NSString *) aValue;
|
||||
- (NSArray *) childrenGroupWithTag: (NSString *) aTag
|
||||
withChild: (NSString *) aChild
|
||||
havingSimpleValue: (NSString *) aValue;
|
||||
|
||||
- (void) addChildWithTag: (NSString *) aTag
|
||||
types: (NSArray *) someTypes
|
||||
singleValue: (NSString *) aValue;
|
||||
|
||||
|
||||
- (CardGroup *) groupWithClass: (Class) groupClass;
|
||||
- (void) setChildrenAsCopy: (NSMutableArray *) someChildren;
|
||||
|
||||
- (void) replaceThisElement: (CardElement *) oldElement
|
||||
withThisOne: (CardElement *) newElement;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* CARDGROUP_H */
|
|
@ -0,0 +1,386 @@
|
|||
/* CardGroup.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <SaxObjC/SaxXMLReader.h>
|
||||
#import <SaxObjC/SaxXMLReaderFactory.h>
|
||||
|
||||
#import "NGCardsSaxHandler.h"
|
||||
#import "NSArray+NGCards.h"
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
static id<NSObject,SaxXMLReader> parser = nil;
|
||||
static NGCardsSaxHandler *sax = nil;
|
||||
|
||||
@implementation CardGroup
|
||||
|
||||
+ (id<NSObject,SaxXMLReader>) cardParser
|
||||
{
|
||||
if (!sax)
|
||||
sax = [NGCardsSaxHandler new];
|
||||
|
||||
if (!parser)
|
||||
{
|
||||
parser =
|
||||
[[[SaxXMLReaderFactory standardXMLReaderFactory]
|
||||
createXMLReaderForMimeType:@"text/x-vcard"]
|
||||
retain];
|
||||
if (parser)
|
||||
{
|
||||
[parser setContentHandler:sax];
|
||||
[parser setErrorHandler:sax];
|
||||
}
|
||||
else
|
||||
NSLog(@"ERROR(%s): did not find a parser for text/x-vcard!",
|
||||
__PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
return parser;
|
||||
}
|
||||
|
||||
+ (NSArray *) parseFromSource: (id) source
|
||||
{
|
||||
static id <NSObject,SaxXMLReader> cardParser;
|
||||
NSMutableArray *cardGroups;
|
||||
NSEnumerator *cards;
|
||||
CardGroup *currentCard;
|
||||
|
||||
cardParser = [self cardParser];
|
||||
[sax setTopElementClass: [self class]];
|
||||
|
||||
if (parser)
|
||||
{
|
||||
cardGroups = [NSMutableArray new];
|
||||
[cardGroups autorelease];
|
||||
|
||||
[parser parseFromSource: source];
|
||||
cards = [[sax cards] objectEnumerator];
|
||||
|
||||
currentCard = [cards nextObject];
|
||||
while (currentCard)
|
||||
{
|
||||
[cardGroups addObject: currentCard];
|
||||
currentCard = [cards nextObject];
|
||||
}
|
||||
}
|
||||
else
|
||||
cardGroups = nil;
|
||||
|
||||
return cardGroups;
|
||||
}
|
||||
|
||||
+ (id) parseSingleFromSource: (id) source
|
||||
{
|
||||
NSArray *cards;
|
||||
CardGroup *card;
|
||||
|
||||
cards = [self parseFromSource: source];
|
||||
if (cards && [cards count])
|
||||
card = [cards objectAtIndex: 0];
|
||||
else
|
||||
card = nil;
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
+ (id) groupWithTag: (NSString *) aTag
|
||||
{
|
||||
id newGroup;
|
||||
|
||||
newGroup = [self new];
|
||||
[newGroup autorelease];
|
||||
[newGroup setTag: aTag];
|
||||
|
||||
return newGroup;
|
||||
}
|
||||
|
||||
+ (id) groupWithTag: (NSString *) aTag
|
||||
children: (NSArray *) someChildren
|
||||
{
|
||||
id newGroup;
|
||||
|
||||
newGroup = [self new];
|
||||
[newGroup autorelease];
|
||||
[newGroup setTag: aTag];
|
||||
[newGroup addChildren: someChildren];
|
||||
|
||||
return newGroup;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
children = [NSMutableArray new];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[children release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (Class) classForTag: (NSString *) tagClass
|
||||
{
|
||||
NSLog (@"class '%@': '%@'", NSStringFromClass([self class]),
|
||||
tagClass);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) addChild: (CardElement *) aChild
|
||||
{
|
||||
Class mappedClass;
|
||||
NSString *childTag;
|
||||
CardElement *newChild;
|
||||
|
||||
childTag = [aChild tag];
|
||||
newChild = nil;
|
||||
mappedClass = [self classForTag: [childTag uppercaseString]];
|
||||
if (mappedClass)
|
||||
{
|
||||
if (![aChild isKindOfClass: mappedClass])
|
||||
{
|
||||
NSLog (@"warning: new child to entity '%@': '%@' converted to '%@'",
|
||||
tag, childTag, NSStringFromClass(mappedClass));
|
||||
if ([aChild isKindOfClass: [CardGroup class]])
|
||||
newChild = [(CardGroup *) aChild groupWithClass: mappedClass];
|
||||
else
|
||||
newChild = [aChild elementWithClass: mappedClass];
|
||||
}
|
||||
}
|
||||
else
|
||||
NSLog (@"warning: no mapped class for tag '%@'",
|
||||
childTag);
|
||||
|
||||
if (!newChild)
|
||||
newChild = aChild;
|
||||
[children addObject: newChild];
|
||||
[newChild setParent: self];
|
||||
}
|
||||
|
||||
- (CardElement *) uniqueChildWithTag: (NSString *) aTag
|
||||
{
|
||||
NSArray *existing;
|
||||
Class elementClass;
|
||||
CardElement *uniqueChild;
|
||||
|
||||
existing = [self childrenWithTag: aTag];
|
||||
if ([existing count] > 0)
|
||||
uniqueChild = [existing objectAtIndex: 0];
|
||||
else
|
||||
{
|
||||
elementClass = [self classForTag: [aTag uppercaseString]];
|
||||
if (!elementClass)
|
||||
elementClass = [CardElement class];
|
||||
|
||||
uniqueChild = [elementClass new];
|
||||
[uniqueChild autorelease];
|
||||
[uniqueChild setTag: aTag];
|
||||
[self addChild: uniqueChild];
|
||||
}
|
||||
|
||||
return uniqueChild;
|
||||
}
|
||||
|
||||
- (void) setUniqueChild: (CardElement *) aChild
|
||||
{
|
||||
CardElement *currentChild;
|
||||
NSString *childTag;
|
||||
NSEnumerator *existing;
|
||||
|
||||
childTag = [aChild tag];
|
||||
existing = [[self childrenWithTag: childTag] objectEnumerator];
|
||||
|
||||
currentChild = [existing nextObject];
|
||||
while (currentChild)
|
||||
{
|
||||
[children removeObject: currentChild];
|
||||
currentChild = [existing nextObject];
|
||||
}
|
||||
|
||||
[self addChild: aChild];
|
||||
}
|
||||
|
||||
- (void) addChildren: (NSArray *) someChildren
|
||||
{
|
||||
CardElement *currentChild;
|
||||
NSEnumerator *newChildren;
|
||||
|
||||
newChildren = [someChildren objectEnumerator];
|
||||
currentChild = [newChildren nextObject];
|
||||
while (currentChild)
|
||||
{
|
||||
[self addChild: currentChild];
|
||||
currentChild = [newChildren nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *) children
|
||||
{
|
||||
return children;
|
||||
}
|
||||
|
||||
- (NSArray *) childrenWithTag: (NSString *) aTag
|
||||
{
|
||||
return [children cardElementsWithTag: aTag];
|
||||
}
|
||||
|
||||
- (NSArray *) childrenWithAttribute: (NSString *) anAttribute
|
||||
havingValue: (NSString *) aValue
|
||||
{
|
||||
return [children cardElementsWithAttribute: anAttribute
|
||||
havingValue: aValue];
|
||||
}
|
||||
|
||||
- (NSArray *) childrenWithTag: (NSString *) aTag
|
||||
andAttribute: (NSString *) anAttribute
|
||||
havingValue: (NSString *) aValue
|
||||
{
|
||||
NSArray *elements;
|
||||
|
||||
elements = [self childrenWithTag: aTag];
|
||||
|
||||
return [elements cardElementsWithAttribute: anAttribute
|
||||
havingValue: aValue];
|
||||
}
|
||||
|
||||
- (NSArray *) childrenGroupWithTag: (NSString *) aTag
|
||||
withChild: (NSString *) aChild
|
||||
havingSimpleValue: (NSString *) aValue
|
||||
{
|
||||
NSEnumerator *allElements;
|
||||
NSMutableArray *elements;
|
||||
CardGroup *element;
|
||||
NSString *value;
|
||||
|
||||
elements = [NSMutableArray new];
|
||||
[elements autorelease];
|
||||
|
||||
allElements = [[self childrenWithTag: aTag] objectEnumerator];
|
||||
element = [allElements nextObject];
|
||||
while (element)
|
||||
{
|
||||
if ([element isKindOfClass: [CardGroup class]])
|
||||
{
|
||||
value = [[element uniqueChildWithTag: aChild] value: 0];
|
||||
if ([value isEqualToString: aValue])
|
||||
[elements addObject: element];
|
||||
}
|
||||
element = [allElements nextObject];
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
#warning should be renamed to elementWithClass...
|
||||
- (CardGroup *) groupWithClass: (Class) groupClass
|
||||
{
|
||||
CardGroup *newGroup;
|
||||
|
||||
if ([self isKindOfClass: groupClass])
|
||||
newGroup = self;
|
||||
else
|
||||
{
|
||||
newGroup = (CardGroup *) [self elementWithClass: groupClass];
|
||||
[newGroup setChildrenAsCopy: children];
|
||||
}
|
||||
|
||||
return newGroup;
|
||||
}
|
||||
|
||||
- (void) setChildrenAsCopy: (NSMutableArray *) someChildren
|
||||
{
|
||||
[children release];
|
||||
children = someChildren;
|
||||
[children retain];
|
||||
}
|
||||
|
||||
- (void) addChildWithTag: (NSString *) aTag
|
||||
types: (NSArray *) someTypes
|
||||
singleValue: (NSString *) aValue
|
||||
{
|
||||
CardElement *newChild;
|
||||
NSEnumerator *types;
|
||||
NSString *type;
|
||||
|
||||
newChild = [CardElement simpleElementWithTag: aTag value: aValue];
|
||||
types = [someTypes objectEnumerator];
|
||||
type = [types nextObject];
|
||||
while (type)
|
||||
{
|
||||
[newChild addType: type];
|
||||
type = [types nextObject];
|
||||
}
|
||||
|
||||
[self addChild: newChild];
|
||||
}
|
||||
|
||||
- (NSString *) description
|
||||
{
|
||||
NSMutableString *str;
|
||||
unsigned int count, max;
|
||||
|
||||
str = [NSMutableString stringWithCapacity:64];
|
||||
[str appendFormat:@"<%p[%@]:%@",
|
||||
self, NSStringFromClass([self class]), [self tag]];
|
||||
max = [children count];
|
||||
if (max > 0)
|
||||
{
|
||||
[str appendFormat: @"\n %d children: {\n", [children count]];
|
||||
for (count = 0; count < max; count++)
|
||||
[str appendFormat: @" %@\n",
|
||||
[[children objectAtIndex: count] description]];
|
||||
[str appendFormat: @"}"];
|
||||
}
|
||||
[str appendString:@">"];
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
- (void) replaceThisElement: (CardElement *) oldElement
|
||||
withThisOne: (CardElement *) newElement
|
||||
{
|
||||
unsigned int index;
|
||||
|
||||
index = [children indexOfObject: oldElement];
|
||||
if (index != NSNotFound)
|
||||
[children replaceObjectAtIndex: index withObject: newElement];
|
||||
}
|
||||
|
||||
- (id) copyWithZone: (NSZone *) aZone
|
||||
{
|
||||
CardGroup *new;
|
||||
|
||||
new = [super copyWithZone: aZone];
|
||||
[new setChildrenAsCopy: [children copyWithZone: aZone]];
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,37 @@
|
|||
/* CardVersitRenderer.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef CARDCARDRENDERER_H
|
||||
#define CARDCARDRENDERER_H
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
@class CardGroup;
|
||||
@class NSString;
|
||||
|
||||
@interface CardVersitRenderer : NSObject
|
||||
|
||||
- (NSString *) render: (id) anElement;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* CARDCARDRENDERER_H */
|
|
@ -0,0 +1,136 @@
|
|||
/* CardVersitRenderer.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import "CardElement.h"
|
||||
#import "CardGroup.h"
|
||||
|
||||
#import "NSString+NGCards.h"
|
||||
#import "NSArray+NGCards.h"
|
||||
|
||||
#import "CardVersitRenderer.h"
|
||||
|
||||
@interface CardVersitRenderer (PrivateAPI)
|
||||
|
||||
- (NSString *) renderElement: (CardElement *) anElement;
|
||||
- (NSString *) renderGroup: (CardGroup *) aGroup;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CardVersitRenderer
|
||||
|
||||
- (NSString *) render: (id) anElement
|
||||
{
|
||||
return (([anElement isKindOfClass: [CardGroup class]])
|
||||
? [self renderGroup: anElement]
|
||||
: [self renderElement: anElement]);
|
||||
}
|
||||
|
||||
- (NSString *) renderElement: (CardElement *) anElement
|
||||
{
|
||||
NSMutableString *rendering;
|
||||
NSDictionary *attributes;
|
||||
NSEnumerator *keys;
|
||||
NSArray *values, *renderedAttrs;
|
||||
NSString *key, *finalRendering, *tag;
|
||||
|
||||
if (![anElement isVoid])
|
||||
{
|
||||
rendering = [NSMutableString new];
|
||||
[rendering autorelease];
|
||||
if ([anElement group])
|
||||
[rendering appendFormat: @"%@.", [anElement group]];
|
||||
tag = [anElement tag];
|
||||
if (!(tag && [tag length]))
|
||||
{
|
||||
tag = @"<no-tag>";
|
||||
[self warnWithFormat: @"card element of class '%@' has an empty tag",
|
||||
NSStringFromClass([anElement class])];
|
||||
}
|
||||
|
||||
[rendering appendString: [tag uppercaseString]];
|
||||
attributes = [anElement attributes];
|
||||
keys = [[attributes allKeys] objectEnumerator];
|
||||
key = [keys nextObject];
|
||||
while (key)
|
||||
{
|
||||
renderedAttrs = [[attributes objectForKey: key] renderedForCards];
|
||||
[rendering appendFormat: @";%@=%@",
|
||||
[key uppercaseString],
|
||||
[renderedAttrs componentsJoinedByString: @","]];
|
||||
key = [keys nextObject];
|
||||
}
|
||||
|
||||
values = [anElement values];
|
||||
if ([values count] > 0)
|
||||
[rendering appendFormat: @":%@",
|
||||
[[values renderedForCards] componentsJoinedByString: @";"]];
|
||||
|
||||
if ([rendering length] > 0)
|
||||
[rendering appendString: @"\r\n"];
|
||||
|
||||
finalRendering = [rendering foldedForVersitCards];
|
||||
}
|
||||
else
|
||||
finalRendering = @"";
|
||||
|
||||
return finalRendering;
|
||||
}
|
||||
|
||||
- (NSString *) renderGroup: (CardGroup *) aGroup
|
||||
{
|
||||
NSEnumerator *children;
|
||||
CardElement *currentChild;
|
||||
NSMutableString *rendering;
|
||||
NSString *groupTag;
|
||||
|
||||
rendering = [NSMutableString new];
|
||||
[rendering autorelease];
|
||||
|
||||
groupTag = [aGroup tag];
|
||||
if (!(groupTag && [groupTag length]))
|
||||
{
|
||||
groupTag = @"<no-tag>";
|
||||
[self warnWithFormat: @"card group of class '%@' has an empty tag",
|
||||
NSStringFromClass([aGroup class])];
|
||||
}
|
||||
|
||||
groupTag = [groupTag uppercaseString];
|
||||
[rendering appendFormat: @"BEGIN:%@\r\n", groupTag];
|
||||
children = [[aGroup children] objectEnumerator];
|
||||
currentChild = [children nextObject];
|
||||
while (currentChild)
|
||||
{
|
||||
[rendering appendString: [self render: currentChild]];
|
||||
currentChild = [children nextObject];
|
||||
}
|
||||
[rendering appendFormat: @"END:%@\r\n", groupTag];
|
||||
|
||||
return rendering;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,600 @@
|
|||
2006-08-03 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* NGVCardSaxHandler.m: fixed a bug with returning parsing results.
|
||||
Properly make a copy of the vCard array so that -clear doesn't
|
||||
destroy references. Thanks go to Wolfgang Sourdeau for documenting
|
||||
the issue! (v4.5.76)
|
||||
|
||||
2006-07-04 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* use %p for pointer formats, fixed gcc 4.1 warnings (v4.5.75)
|
||||
|
||||
2006-05-16 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalDataSource.h, common.h: changed EOControl related includes into
|
||||
imports to enable compilation against MulleEOF (v4.5.74)
|
||||
|
||||
2006-04-07 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalEntityObject.h: added missing forward declaration for
|
||||
gstep-base compile (v4.5.73)
|
||||
|
||||
2006-04-06 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.72
|
||||
|
||||
* iCalEntityObject.[hm]: added "url" property - unfortunately
|
||||
this was missing before. Increased class version to "1".
|
||||
|
||||
* iCalRepeatableEntityObject.m, iCalEvent.m, iCalToDo.m: adjusted
|
||||
super class version check.
|
||||
|
||||
2006-01-16 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalRecurrenceRule.m: properly include NSString+Ext.h to avoid a
|
||||
warning during Cocoa compilation (v4.5.71)
|
||||
|
||||
2005-11-17 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* include string.h where required (v4.5.70)
|
||||
|
||||
2005-10-05 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalMonthlyRecurrenceCalculator.m: implemented calculation of
|
||||
negative byday occurrences (eg -1TH) (v4.5.69)
|
||||
|
||||
2005-09-22 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* iCalRecurrenceRule.m: added direct parser support for 'interval',
|
||||
allow 'until' values w/o Z marker for date-only values (v4.5.68)
|
||||
|
||||
2005-09-22 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* v4.5.67
|
||||
|
||||
* iCalMonthlyRecurrenceCalculator.m: finished 'byday' calculation
|
||||
|
||||
* iCalRecurrenceRule.m: added support for 'bymonthday', fixed handling
|
||||
of occurrence1
|
||||
|
||||
2005-09-21 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* v4.5.66
|
||||
|
||||
* iCalRecurrenceRule.m: temporarily expose byDayOccurence1 until the
|
||||
API is fixed
|
||||
|
||||
* iCalMonthlyRecurrenceCalculator.m: prepared for byday/bymonthday
|
||||
rule specs
|
||||
|
||||
* v4.5.65
|
||||
|
||||
* iCalMonthlyRecurrenceCalculator.m: fixed calculation of 'count' field
|
||||
|
||||
* iCalRecurrenceCalculator.m: minor code cleanups
|
||||
|
||||
* iCalRecurrenceRule.m: improved rrule parser
|
||||
|
||||
2005-09-20 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalMonthlyRecurrenceCalculator.m: stop calculation if a byday part
|
||||
was detected in the rule (v4.5.64)
|
||||
|
||||
* iCalRecurrenceCalculator.m: moved cluster subclasses to own source
|
||||
files (v4.5.63)
|
||||
|
||||
* iCalRecurrenceRule.m: added some parsing/gen support for BYDAY
|
||||
(v4.5.62)
|
||||
|
||||
2005-09-19 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalRecurrenceRule.m: minor code improvements, more tolerant on
|
||||
invalid iCal rrule input (v4.5.61)
|
||||
|
||||
2005-08-16 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* GNUmakefile, GNUmakefile.preamble: added OSX framework compilation
|
||||
(v4.5.60)
|
||||
|
||||
2005-08-06 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalCalendar.m, NGVCardName.m: fixed gcc 4.0 warnings (v4.5.59)
|
||||
|
||||
2005-08-05 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* NGVCardSaxHandler.h: fixed a gcc 4.0 warning (v4.5.58)
|
||||
|
||||
2005-07-18 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalPerson.m: added -partStatWithDefault method to retrieve the
|
||||
partstat and return NEEDS-ACTION in case none is set (v4.5.57)
|
||||
|
||||
2005-07-15 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalObject.[hm], iCalEntityObject.m, iCalToDo.m, iCalAlarm.m,
|
||||
iCalPerson.m, iCalCalendar.m, iCalEvent.m, iCalTrigger.m,
|
||||
iCalObject.m, iCalFreeBusy.m, iCalRepeatableEntityObject.m:
|
||||
fixed NSCopying (v4.5.56)
|
||||
|
||||
2005-07-15 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* added fragile base class version checks (v4.5.55)
|
||||
|
||||
2005-07-15 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalObject.[hm], iCalEntityObject.m, iCalToDo.m, iCalAlarm.m,
|
||||
iCalPerson.m, iCalCalendar.m, iCalEvent.m, iCalTrigger.m,
|
||||
iCalObject.m, iCalFreeBusy.m, iCalRepeatableEntityObject.m:
|
||||
added NSCopying (v4.5.54)
|
||||
|
||||
2005-07-15 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* v4.5.53
|
||||
|
||||
* iCalCalendar.m: added +parseCalendarFromSource: convenience method
|
||||
|
||||
* NGVCard.m: properly reset sax driver after parsing
|
||||
|
||||
2005-07-15 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalEntityObject.[hm]: added -increaseSequence (v4.5.52)
|
||||
|
||||
* iCalPerson.m: fixed -hasSameEmailAddress: to lowercase email
|
||||
addresses before attempting comparison (v4.5.51)
|
||||
|
||||
2005-07-15 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* v4.5.50
|
||||
|
||||
* NGiCal.xmap: fixed mapping of 'method' property (is an attribute of
|
||||
the calendar)
|
||||
|
||||
* iCalCalendar.m: use ASSIGNCOPY in accessors, added 'method' to
|
||||
-description
|
||||
|
||||
2005-07-14 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.49
|
||||
|
||||
* iCalCalendar.[hm]: added 'method'
|
||||
|
||||
* iCalEntityObject.[hm]: added 'userComment', changed all email
|
||||
related comparisons to lowercase all strings before comparison
|
||||
|
||||
* iCalEvent.h: pretty printed iVars
|
||||
|
||||
* NGiCal.xmap: added mapping for 'comment' -> 'userComment' and
|
||||
'method' -> 'method'
|
||||
|
||||
2005-07-13 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* v4.5.48
|
||||
|
||||
* NGVCard.m: added some convenience methods to access the preferred
|
||||
email, tel and adr
|
||||
|
||||
* NGVCardOrg.m: added a convenience method to access the first orgunit
|
||||
|
||||
2005-07-05 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NSCalendarDate+ICal.m: fixed 'gmtcalfmt' which removed seconds from
|
||||
format for no obvious reason (v4.5.47)
|
||||
|
||||
2005-05-31 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* NGVCardSaxHandler.m: ensure that types are always uppercase, improved
|
||||
check for DUPs (v4.5.46)
|
||||
|
||||
2005-05-16 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NGiCal.xcode: reorganized ordering of headers/classes
|
||||
|
||||
2005-05-15 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NGiCal.xcode: added vCard related stuff
|
||||
|
||||
2005-05-10 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* NGVCard.m: added support for profile, source, name (v4.5.45)
|
||||
|
||||
2005-05-09 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* first version of working vCard SAX handler (v4.5.54)
|
||||
|
||||
2005-05-08 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* more work on vCard parsing (v4.5.53)
|
||||
|
||||
* work on vCard objects (incomplete) (v4.5.52)
|
||||
|
||||
2005-04-25 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalDateHolder.m, iCalDataSource.m: fixed gcc 4.0 warnings (v4.5.51)
|
||||
|
||||
2005-03-23 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.50
|
||||
|
||||
* iCalRenderer.h: added missing paranthesis for iVar declarations
|
||||
|
||||
* iCalTrigger.m, iCalEntityObject.m, iCalToDo.m,
|
||||
iCalRecurrenceCalculator.m, iCalDateHolder.m, iCalDataSource.m,
|
||||
iCalPerson.m, iCalCalendar.m: numerous dealloc bugs/leaks fixed
|
||||
|
||||
2005-03-02 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalRecurrenceCalculator.m: bugfix for monthly and yearly recurrences
|
||||
(v4.5.49)
|
||||
|
||||
* iCalRecurrenceCalculator.m: optimized exception date handling in
|
||||
complex calculation method quite a bit. Fixed bugs in all calculation
|
||||
methods by introducing checks on the desired range. (v4.5.48)
|
||||
|
||||
2005-02-28 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.47
|
||||
|
||||
* iCalRepeatableEntityObject.m: shifted code to
|
||||
iCalRecurrenceCalculator
|
||||
|
||||
* iCalRecurrenceCalculator.[hm]: new class method to calculate
|
||||
complex recurrences. In SOGo this information is stored in quick
|
||||
fields to reduce the complexity of lookups, hence we need to offer
|
||||
a proper API to calculate date ranges from this information.
|
||||
Fixed all calculations to explicitly set timeZone for all newly
|
||||
created startDates - it seems the timeZone information is not
|
||||
properly retained by the hour:minute:second: method from NGExtensions
|
||||
which lead to improper DST related shifts.
|
||||
|
||||
* iCalDateHolder.h: exposed the API
|
||||
|
||||
* NSCalendarDate+ICal.[hm]: new convenience constructor for calendar
|
||||
dates from iCal representations (uses iCalDateHolder internally)
|
||||
|
||||
* iCalRecurrenceRule.m: changed setUntil: to utilize new public
|
||||
NSCalendarDate+ICal category
|
||||
|
||||
* NGiCal.h: added NSCalendarDate+ICal.h to the public headers
|
||||
|
||||
* GNUmakefile: NSCalendarDate+ICal.h is public now
|
||||
|
||||
2005-02-20 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* NGiCal.xmap: fixed a missing semicolon (did not load on MacOSX)
|
||||
(v.4.5.46)
|
||||
|
||||
2005-02-17 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* GNUmakefile.preamble: fixed linking locations for dependencies
|
||||
(v4.5.45)
|
||||
|
||||
2005-02-17 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.44
|
||||
|
||||
* iCalEntityObject.[hm]: added convenience API
|
||||
|
||||
* iCalRepeatableEntityObject.[hm]: added convenience API
|
||||
|
||||
* iCalRecurrenceRule.m: bugfixes in -byDayList and
|
||||
-iCalRepresentationForWeekDay:
|
||||
|
||||
* iCalRecurrenceCalculator.m: implemented 'BYDAY' calculations for
|
||||
weekly frequency. Note that 'COUNT' is still broken for this case.
|
||||
|
||||
* iCalRenderer.m: updated rendering, now can render recurrence rules
|
||||
and accompanied stuff properly.
|
||||
|
||||
2005-02-15 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.43
|
||||
|
||||
* iCalRecurrenceRule.[hm]: exposed some more of the API
|
||||
|
||||
* iCalRecurrenceCalculator.m: some bugfixes. Split the code and gave
|
||||
iCalWeeklyRecurrenceCalculator its own calculation - there are a
|
||||
number of foreseeable differences to daily calculation that make
|
||||
this necessary in the near future anyways.
|
||||
|
||||
* v4.5.42
|
||||
|
||||
* iCalRepeatableEntityObject.[hm]: added ability to properly calculate
|
||||
the recurrence ranges within a specific calendar date range, taking
|
||||
all possible exceptions into account.
|
||||
|
||||
* iCalEvent.[hm]: convenience wrapper for the new method found in
|
||||
iCalRepeatableEntityObject.
|
||||
|
||||
2005-02-14 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* v4.5.41
|
||||
|
||||
* GNUmakefile.preamble: added missing dependency on libNGExtensions
|
||||
(which also adds the dependency on libDOM)
|
||||
|
||||
* iCalRecurrenceCalculator.h: fixed missing forward declaration in
|
||||
header
|
||||
|
||||
2005-02-12 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.40
|
||||
|
||||
* iCalRecurrenceCalculator.[hm]: implemented all required (and simple)
|
||||
calculations. Added some convenience API to query some of the more
|
||||
obvious ranges suitable as limits for fetching/comparison.
|
||||
|
||||
* iCalRepeatableEntityObject.[hm]: new method for calculating the
|
||||
last possible recurrence start date. This can be used for fetches
|
||||
as well.
|
||||
|
||||
* iCalEvent.[hm]: more convenient wrapper for the new method found in
|
||||
iCalRepeatableEntityObject.
|
||||
|
||||
* NSCalendarDate+ICal.[hm]: convenience methods for calculating
|
||||
"distances" between dates.
|
||||
|
||||
* tests/*: updated
|
||||
|
||||
2005-02-11 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.39
|
||||
|
||||
* README: updated
|
||||
|
||||
* iCalRepeatableEntityObject.[hm]: new base class for all other
|
||||
repeatable entity objects. Offers a convenience API for generating
|
||||
recurrence ranges and tests, taking all exceptions into account.
|
||||
|
||||
* iCalRecurrenceRule.[hm]: an iCal recurrence rule, modeled as closely
|
||||
as possible to RFC2445. Please note that this is work in progress
|
||||
and far from being complete, yet.
|
||||
|
||||
* iCalRecurrenceCalculator.[hm]: a controller implementing RFC2445
|
||||
to properly generate recurrence ranges and accompanied functionality.
|
||||
|
||||
* iCalEvent.[hm], iCalToDo.[hm]: now subclasses from
|
||||
iCalRepeatableEntityObject, thus removed code dealing with
|
||||
recurrences
|
||||
|
||||
* NGiCal.h: added new headers
|
||||
|
||||
* NGiCal.xmap: changed recurrenceRule mappings due to model change
|
||||
|
||||
* tests/*: contains unit tests for stuff dealing with recurrences. See
|
||||
accompanied README for details
|
||||
|
||||
2004-12-17 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalPerson.[hm]: formalized participationStatus according to RFC2445.
|
||||
Provided convenience API to set status without concrete knowledge
|
||||
of string values involved. (v4.5.38)
|
||||
|
||||
2004-12-16 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.5.37
|
||||
|
||||
* iCalEvent.[hm]: Added transparency 'TRANSP'. Also multiple
|
||||
convenience methods provided.
|
||||
|
||||
* NGiCal.xmap: added proper mapping for 'transp'.
|
||||
|
||||
2004-12-14 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NGiCal.xcode: minor changes and updated
|
||||
|
||||
2004-12-13 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalPerson.[hm]: added -cnWithoutQuotes and -rfc822Email convenience
|
||||
methods to simplify client code dealing with these properties
|
||||
(v4.5.36)
|
||||
|
||||
2004-11-07 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NGiCal.xcode: provide SOPE_{MAJOR,MINOR}_VERSION to the build
|
||||
|
||||
2004-11-06 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalRenderer.m: use SOPE version defines for iCalendar product id
|
||||
(v4.5.35)
|
||||
|
||||
2004-11-04 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* use Version file for install directory location of sax mapping
|
||||
|
||||
2004-10-31 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalAlarm.[hm], iCalEvent.[hm], iCalToDo.[hm],
|
||||
NGiCal.xmap: added recurrenceRule (v4.3.34)
|
||||
|
||||
2004-10-20 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NGiCal.xcode: added iCalRenderer.[hm], bumped framework version
|
||||
|
||||
2004-10-20 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalRenderer.m: fixed some issue with Cocoa Foundation (v4.3.33)
|
||||
|
||||
* v4.3.32
|
||||
|
||||
* iCalEvent.m: added -vEvent method to produce an iCalendar
|
||||
representation of an event
|
||||
|
||||
* added iCalRenderer class based on the SOGo render by ZNeK
|
||||
|
||||
2004-10-14 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NGiCal.xmap: added "categories" mapping (v4.3.31)
|
||||
|
||||
2004-10-05 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalEntityObject.[hm]: added categories property (v4.3.30)
|
||||
|
||||
2004-09-22 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NGiCal.xcode: fixed several build parameters
|
||||
|
||||
2004-09-01 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* v4.3.29
|
||||
|
||||
* iCalEventChanges.[hm]: new class for tracking changes between
|
||||
two given events
|
||||
|
||||
* iCalEvent.[hm]: new API to generate iCalEventChanges objects.
|
||||
|
||||
* common.h: inline function and macro for "safe" comparison of
|
||||
object values
|
||||
|
||||
2004-09-01 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* GNUmakefile.postamble: copy sax-model to FHS_INSTALL_ROOT +
|
||||
/share/sope-4.3/saxmappings/ when compiling for FHS (v4.3.28)
|
||||
|
||||
2004-08-29 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* added hack to install the project in FHS locations - the library,
|
||||
its headers, the tools and the resources will be installed in
|
||||
FHS_INSTALL_ROOT if specified (eg make FHS_INSTALL_ROOT=/usr/local)
|
||||
(v4.3.27)
|
||||
|
||||
2004-08-26 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* NGiCal.xcode: new Xcode project
|
||||
|
||||
2004-08-20 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* fixed for SOPE 3.3 directory layout (v4.3.26)
|
||||
|
||||
* moved to sope-ical
|
||||
|
||||
* moved to SOPE 4.3 (v4.3.25)
|
||||
|
||||
2004-08-14 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalEntityObject.m: changed "sequence" attribute from NSString to
|
||||
NSNumber (this might break some code, though some care was taken to
|
||||
accept NSString parameters) (v4.2.24)
|
||||
|
||||
2004-07-14 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalEvent.h: moved 'status' field to iCalEntityObject, because it is
|
||||
also available in todo objects (v4.2.23)
|
||||
|
||||
2004-06-30 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* iCalEntityObject.m: added -removeAllAttendees and -removeAllAlarms.
|
||||
These are necessary in case you want to remake the contents of these
|
||||
collections, but keep all other attributes otherwise. (v4.2.22)
|
||||
|
||||
2004-06-09 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* v4.2.21
|
||||
|
||||
* GNUmakefile.preamble: added prebinding
|
||||
|
||||
* GNUmakefile: create GNUmakefile.preamble, GNUmakefile.postamble
|
||||
|
||||
2004-05-05 Marcus Mueller <znek@mulle-kybernetik.com>
|
||||
|
||||
* GNUmakefile: added support for building with
|
||||
GNUSTEP_BUILD_DIR environment variable set for recent
|
||||
gnustep-make package. (v4.2.20)
|
||||
|
||||
2004-01-23 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* iCalDataSource.m: added some sanity checks, improved to work better
|
||||
with Mozilla generated iCal files (v4.2.19)
|
||||
|
||||
2003-12-22 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* iCalDateHolder.m: small fix not to print a warning for "YYYYMMDD"
|
||||
style dates (which are supported) (v4.2.18)
|
||||
|
||||
2003-12-21 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* v4.2.17
|
||||
|
||||
* iCalEvent.m: added parsing of duration values and calculation of
|
||||
end-dates based on that (eg required for Panther iCal.app)
|
||||
|
||||
* iCalEvent.m: added support for 'status' and 'duration' fields
|
||||
|
||||
Thu Nov 20 16:31:15 2003 Martin Hoerning <martin@opengroupware.org>
|
||||
|
||||
* iCalDateHolder.m: added timeless date format: YYYYMMDD
|
||||
(solves ogo bug 424) (v4.2.16)
|
||||
|
||||
Wed Oct 29 22:04:32 2003 Martin Hoerning <martin@opengroupware.org>
|
||||
|
||||
* iCalDateHolder.m, iCalObject.[m|h]: added iCalDefaultTimeZone to
|
||||
create date from iCalDates without timeZone. (solves OGoo bug 257)
|
||||
(v4.2.15)
|
||||
|
||||
2003-10-12 Helge Hess <helge@opengroupware.org>
|
||||
|
||||
* GNUmakefile (libNGiCal_LIBRARIES_DEPEND_UPON): link against
|
||||
libSaxObjC on MacOSX (v4.2.14)
|
||||
|
||||
Fri Jul 18 17:04:55 2003 Martin Hoerning <mh@skyrix.com>
|
||||
|
||||
* iCalToDo.h, iCalPerson.h, iCalEvent.h, iCalEntityObject.h: added
|
||||
accessor-methods to interface (v4.2.13)
|
||||
|
||||
2003-07-18 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* iCalDateHolder.m: replaces and indexOfString with rangeOfString,
|
||||
thanks to Filip Van Raemdonck for pointing that out (v4.2.12)
|
||||
|
||||
2003-03-21 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* added some method prototypes
|
||||
|
||||
2003-03-13 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* moved iCalEntityObject to a separate file (v4.2.11)
|
||||
|
||||
Mon Mar 10 18:41:10 2003 Bjoern Stierand <bjoern@skyrix.com>
|
||||
|
||||
* NGiCal.xmap: added missing attendee attributes (as dictated by
|
||||
mh on the phone)
|
||||
|
||||
2003-03-10 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* iCalPerson.h: added some method prototypes
|
||||
|
||||
2003-02-24 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* iCalObject.h: added some accessors (v4.2.10)
|
||||
|
||||
2003-02-12 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* moved to skyrix-core (v4.2.9)
|
||||
|
||||
2003-01-13 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* added some support for timezones to be able to parse Evolution
|
||||
apt creation requests (v4.2.7)
|
||||
|
||||
2002-10-14 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* added iCalDateHolder for decoding xCal date values with timezone
|
||||
attributes to a NSCalendarDate
|
||||
|
||||
* iCalObject.m: ignore X- keys
|
||||
|
||||
* removed all the old stuff (v4.2.4)
|
||||
|
||||
* ICalVEvent.m: renamed -class to -eventClass since -class conflicts
|
||||
with the NSObject method
|
||||
|
||||
* started XML based iCal (v4.2.3)
|
||||
|
||||
2002-10-10 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* ICalParser.m: small cleanups (v4.2.2)
|
||||
|
||||
2002-10-04 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* created ChangeLog, created NGiCal library into SkyCore
|
||||
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
# GNUstep makefile
|
||||
|
||||
-include ../../config.make
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
include ./Version
|
||||
|
||||
SUBPROJECTS += versitCardsSaxDriver
|
||||
|
||||
ifneq ($(frameworks),yes)
|
||||
LIBRARY_NAME = libNGCards
|
||||
else
|
||||
FRAMEWORK_NAME = NGCards
|
||||
endif
|
||||
|
||||
FHS_HEADER_DIRS = NGCards
|
||||
|
||||
libNGCards_PCH_FILE = common.h
|
||||
libNGCards_HEADER_FILES_DIR = .
|
||||
libNGCards_HEADER_FILES_INSTALL_DIR = /NGCards
|
||||
libNGCards_SOVERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
|
||||
libNGCards_VERSION=$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBMINOR_VERSION)
|
||||
|
||||
libNGCards_HEADER_FILES = \
|
||||
NSArray+NGCards.h \
|
||||
NSCalendarDate+NGCards.h \
|
||||
NSDictionary+NGCards.h \
|
||||
NSString+NGCards.h \
|
||||
NSCalendarDate+ICal.h \
|
||||
\
|
||||
CardElement.h \
|
||||
CardGroup.h \
|
||||
CardGroup+iCal.h \
|
||||
CardVersitRenderer.h \
|
||||
\
|
||||
NGCards.h \
|
||||
iCalAlarm.h \
|
||||
iCalAttachment.h \
|
||||
iCalCalendar.h \
|
||||
iCalDataSource.h \
|
||||
iCalDateTime.m \
|
||||
iCalEntityObject.h \
|
||||
iCalEvent.h \
|
||||
iCalEventChanges.h \
|
||||
iCalFreeBusy.h \
|
||||
iCalJournal.h \
|
||||
iCalObject.h \
|
||||
iCalPerson.h \
|
||||
iCalRecurrenceRule.h \
|
||||
iCalRecurrenceCalculator.h \
|
||||
iCalRepeatableEntityObject.h \
|
||||
iCalTimeZone.h \
|
||||
iCalTimeZonePeriod.h \
|
||||
iCalToDo.h \
|
||||
iCalTrigger.h \
|
||||
\
|
||||
NSCalendarDate+ICal.h \
|
||||
\
|
||||
NGVCard.h \
|
||||
# NGVCardAddress.h \
|
||||
# NGVCardStrArrayValue.h \
|
||||
# NGVCardName.h \
|
||||
# NGVCardOrg.h \
|
||||
# NGVCardPhone.h \
|
||||
NGCardsSaxHandler.h \
|
||||
# NGVCardSimpleValue.h \
|
||||
# NGVCardValue.h \
|
||||
|
||||
# IcalResponse.h \
|
||||
|
||||
libNGCards_OBJC_FILES = \
|
||||
NSArray+NGCards.m \
|
||||
NSCalendarDate+NGCards.m \
|
||||
NSDictionary+NGCards.m \
|
||||
NSString+NGCards.m \
|
||||
NSCalendarDate+ICal.m \
|
||||
iCalDateHolder.m \
|
||||
\
|
||||
CardElement.m \
|
||||
CardGroup.m \
|
||||
CardGroup+iCal.m \
|
||||
CardVersitRenderer.m \
|
||||
\
|
||||
iCalAlarm.m \
|
||||
iCalAttachment.m \
|
||||
iCalCalendar.m \
|
||||
iCalDailyRecurrenceCalculator.m \
|
||||
iCalDateTime.m \
|
||||
iCalDataSource.m \
|
||||
iCalEntityObject.m \
|
||||
iCalEvent.m \
|
||||
iCalEventChanges.m \
|
||||
iCalFreeBusy.m \
|
||||
iCalJournal.m \
|
||||
iCalMonthlyRecurrenceCalculator.m \
|
||||
iCalObject.m \
|
||||
iCalPerson.m \
|
||||
iCalRecurrenceRule.m \
|
||||
iCalRecurrenceCalculator.m \
|
||||
iCalRepeatableEntityObject.m \
|
||||
iCalTimeZone.m \
|
||||
iCalTimeZonePeriod.m \
|
||||
iCalToDo.m \
|
||||
iCalTrigger.m \
|
||||
iCalWeeklyRecurrenceCalculator.m\
|
||||
iCalYearlyRecurrenceCalculator.m\
|
||||
\
|
||||
NGVCard.m \
|
||||
NGCardsSaxHandler.m \
|
||||
# IcalElements.m
|
||||
# IcalResponse.m
|
||||
|
||||
|
||||
# framework support
|
||||
|
||||
NGCards_PCH_FILE = $(libNGCards_PCH_FILE)
|
||||
NGCards_HEADER_FILES = $(libNGCards_HEADER_FILES)
|
||||
NGCards_OBJC_FILES = $(libNGCards_OBJC_FILES)
|
||||
NGCards_SUBPROJECTS = $(libNGCards_SUBPROJECTS)
|
||||
|
||||
# building
|
||||
|
||||
-include GNUmakefile.preamble
|
||||
ifneq ($(frameworks),yes)
|
||||
include $(GNUSTEP_MAKEFILES)/library.make
|
||||
else
|
||||
include $(GNUSTEP_MAKEFILES)/framework.make
|
||||
endif
|
||||
include $(GNUSTEP_MAKEFILES)/aggregate.make
|
||||
-include GNUmakefile.postamble
|
||||
-include ../../fhslib.make
|
|
@ -0,0 +1,13 @@
|
|||
# compilation settings
|
||||
|
||||
ifeq ($(FHS_INSTALL_ROOT),)
|
||||
MAPDIR="$(GNUSTEP_INSTALLATION_DIR)/Library/SaxMappings/"
|
||||
else
|
||||
MAPDIR="$(FHS_INSTALL_ROOT)/share/sope-$(MAJOR_VERSION).$(MINOR_VERSION)/saxmappings/"
|
||||
endif
|
||||
|
||||
mappings-dir ::
|
||||
$(MKDIRS) $(MAPDIR)
|
||||
|
||||
after-install :: mappings-dir
|
||||
cp NGCards.xmap $(MAPDIR)
|
|
@ -0,0 +1,61 @@
|
|||
# compilation settings
|
||||
|
||||
SOPE_ROOT=../..
|
||||
|
||||
ADDITIONAL_CPPFLAGS += \
|
||||
-Wall -DCOMPILE_FOR_GSTEP_MAKE=1 \
|
||||
-DSOPE_MAJOR_VERSION=$(MAJOR_VERSION) \
|
||||
-DSOPE_MINOR_VERSION=$(MINOR_VERSION) \
|
||||
-DSOPE_SUBMINOR_VERSION=$(SUBMINOR_VERSION)
|
||||
|
||||
ADDITIONAL_INCLUDE_DIRS += \
|
||||
-I. -I.. \
|
||||
-I$(SOPE_ROOT)/sope-core/NGExtensions/ \
|
||||
-I$(SOPE_ROOT)/sope-core \
|
||||
-I$(SOPE_ROOT)/sope-xml
|
||||
|
||||
|
||||
# dependencies
|
||||
|
||||
libNGCards_LIBRARIES_DEPEND_UPON += \
|
||||
-lNGExtensions \
|
||||
-lEOControl \
|
||||
-lDOM \
|
||||
-lSaxObjC
|
||||
|
||||
NGCards_LIBRARIES_DEPEND_UPON += \
|
||||
-framework NGExtensions -framework EOControl \
|
||||
-framework DOM -framework SaxObjC
|
||||
|
||||
|
||||
# library/framework search pathes
|
||||
|
||||
DEP_DIRS = \
|
||||
$(SOPE_ROOT)/sope-core/NGExtensions \
|
||||
$(SOPE_ROOT)/sope-core/EOControl \
|
||||
$(SOPE_ROOT)/sope-xml/DOM \
|
||||
$(SOPE_ROOT)/sope-xml/SaxObjC
|
||||
|
||||
ifneq ($(frameworks),yes)
|
||||
ADDITIONAL_LIB_DIRS += \
|
||||
$(foreach dir,$(DEP_DIRS),\
|
||||
-L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME))
|
||||
else
|
||||
ADDITIONAL_LIB_DIRS += \
|
||||
$(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir))
|
||||
endif
|
||||
|
||||
ifeq ($(findstring _64, $(GNUSTEP_TARGET_CPU)), _64)
|
||||
SYSTEM_LIB_DIR += -L/usr/local/lib64 -L/usr/lib64
|
||||
else
|
||||
SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
|
||||
endif
|
||||
|
||||
|
||||
# Apple
|
||||
|
||||
ifeq ($(FOUNDATION_LIB),apple)
|
||||
libNGCards_PREBIND_ADDR="0xC1E00000"
|
||||
libNGCards_LDFLAGS += -seg1addr $(libNGCards_PREBIND_ADDR)
|
||||
NGCards_LDFLAGS += -seg1addr $(libNGCards_PREBIND_ADDR)
|
||||
endif
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <NGObjWeb/WODynamicElement.h>
|
||||
|
||||
@interface IcalComponent : WODynamicElement
|
||||
{
|
||||
WOAssociation *cname;
|
||||
WOElement *template;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface IcalProperty : WODynamicElement
|
||||
{
|
||||
WOAssociation *pname;
|
||||
WOElement *template;
|
||||
NSDictionary *parameters;
|
||||
WOAssociation *value;
|
||||
WOAssociation *valueType;
|
||||
}
|
||||
@end
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static inline NSDictionary *ExtractParameters(NSDictionary *_set) {
|
||||
/* extracts ? parameters */
|
||||
NSMutableDictionary *paras = nil;
|
||||
NSMutableArray *paraKeys = nil;
|
||||
NSEnumerator *keys;
|
||||
NSString *key;
|
||||
|
||||
// locate query parameters
|
||||
keys = [_set keyEnumerator];
|
||||
while ((key = [keys nextObject])) {
|
||||
if ([key hasPrefix:@"?"]) {
|
||||
WOAssociation *value;
|
||||
|
||||
if ([key isEqualToString:@"?wosid"])
|
||||
continue;
|
||||
|
||||
value = [_set objectForKey:key];
|
||||
|
||||
if (paraKeys == nil)
|
||||
paraKeys = [NSMutableArray arrayWithCapacity:8];
|
||||
if (paras == nil)
|
||||
paras = [NSMutableDictionary dictionaryWithCapacity:8];
|
||||
|
||||
[paraKeys addObject:key];
|
||||
[paras setObject:value forKey:[key substringFromIndex:1]];
|
||||
}
|
||||
}
|
||||
|
||||
// remove query parameters
|
||||
if (paraKeys) {
|
||||
unsigned cnt, count;
|
||||
for (cnt = 0, count = [paraKeys count]; cnt < count; cnt++) {
|
||||
[(NSMutableDictionary *)_set removeObjectForKey:
|
||||
[paraKeys objectAtIndex:cnt]];
|
||||
}
|
||||
}
|
||||
|
||||
// assign parameters
|
||||
return [paras copy];
|
||||
}
|
||||
|
||||
static inline id GetProperty(NSDictionary *_set, NSString *_name) {
|
||||
id propValue = [_set objectForKey:_name];
|
||||
|
||||
if (propValue) {
|
||||
propValue = RETAIN(propValue);
|
||||
[(id)_set removeObjectForKey:_name];
|
||||
}
|
||||
return propValue;
|
||||
}
|
||||
|
||||
@implementation IcalComponent
|
||||
|
||||
- (id)initWithName:(NSString *)_name
|
||||
associations:(NSDictionary *)_config
|
||||
template:(WOElement *)_t
|
||||
{
|
||||
if ((self = [super initWithName:_name associations:_config template:_t])) {
|
||||
self->cname = GetProperty(_config, @"name");
|
||||
self->template = RETAIN(_t);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
RELEASE(self->template);
|
||||
RELEASE(self->cname);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
|
||||
NSString *n;
|
||||
|
||||
n = [self->cname stringValueInComponent:[_ctx component]];
|
||||
|
||||
[_response appendContentString:@"BEGIN:"];
|
||||
[_response appendContentString:n];
|
||||
[self->template appendToResponse:_response inContext:_ctx];
|
||||
[_response appendContentString:@"END:"];
|
||||
[_response appendContentString:n];
|
||||
}
|
||||
|
||||
@end /* IcalComponent */
|
||||
|
||||
@implementation IcalProperty
|
||||
|
||||
- (id)initWithName:(NSString *)_name
|
||||
associations:(NSDictionary *)_config
|
||||
template:(WOElement *)_t
|
||||
{
|
||||
if ((self = [super initWithName:_name associations:_config template:_t])) {
|
||||
self->pname = GetProperty(_config, @"name");
|
||||
self->value = GetProperty(_config, @"value");
|
||||
self->valueType = GetProperty(_config, @"valueType");
|
||||
self->template = RETAIN(_t);
|
||||
self->parameters = ExtractParameters(_config);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
RELEASE(self->value);
|
||||
RELEASE(self->valueType);
|
||||
RELEASE(self->parameters);
|
||||
RELEASE(self->template);
|
||||
RELEASE(self->pname);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
|
||||
WOComponent *sComponent;
|
||||
NSString *n;
|
||||
NSEnumerator *keys;
|
||||
NSString *key;
|
||||
id val;
|
||||
NSString *valType;
|
||||
|
||||
sComponent = [_ctx component];
|
||||
n = [self->pname stringValueInComponent:sComponent];
|
||||
val = [self->value valueInComponent:sComponent];
|
||||
valType = [self->valueType stringValueInComponent:sComponent];
|
||||
|
||||
/* add name */
|
||||
[_response appendContentString:n];
|
||||
|
||||
/* add parameters */
|
||||
keys = [self->parameters keyEnumerator];
|
||||
while ((key = [keys nextObject])) {
|
||||
WOAssociation *val;
|
||||
NSString *s;
|
||||
|
||||
val = [self->parameters objectForKey:key];
|
||||
s = [val stringValueInComponent:sComponent];
|
||||
|
||||
if ([s length] > 0) {
|
||||
[_response appendContentString:@";"];
|
||||
[_response appendContentString:key];
|
||||
[_response appendContentString:@"="];
|
||||
[_response appendContentString:s];
|
||||
}
|
||||
}
|
||||
|
||||
/* add value */
|
||||
[_response appendContentString:@":"];
|
||||
|
||||
if ([valType length] == 0) {
|
||||
val = [val stringValue];
|
||||
}
|
||||
else if ([valType isEqualToString:@"datetime"]) {
|
||||
static NSString *calfmt = @"%Y%m%dT%H%M00Z";
|
||||
|
||||
if ([val respondsToSelector:@selector(descriptionWithCalendarFormat:)]) {
|
||||
static NSTimeZone *gmt = nil;
|
||||
if (gmt == nil) gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
|
||||
[val setTimeZone:gmt];
|
||||
val = [val descriptionWithCalendarFormat:calfmt];
|
||||
}
|
||||
else
|
||||
val = [val stringValue];
|
||||
}
|
||||
else
|
||||
val = [val stringValue];
|
||||
|
||||
[_response appendContentString:val];
|
||||
[self->template appendToResponse:_response inContext:_ctx];
|
||||
}
|
||||
|
||||
@end /* IcalProperty */
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SkyDaemon_skyaptd_IcalResponse_H__
|
||||
#define __SkyDaemon_skyaptd_IcalResponse_H__
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
@class NSMutableString, NSData;
|
||||
|
||||
@interface IcalResponse : NSObject
|
||||
{
|
||||
NSMutableString *content;
|
||||
BOOL isFinished;
|
||||
}
|
||||
|
||||
- (id)initWithCapacity:(unsigned)_capacity;
|
||||
|
||||
- (void)finish;
|
||||
- (NSString *)asString;
|
||||
- (BOOL)appendLine:(NSString *)_line;
|
||||
|
||||
// _attr:_line
|
||||
- (BOOL)appendLine:(NSString *)_line forAttribute:(NSString *)_attr;
|
||||
|
||||
@end /* IcalResponse */
|
||||
|
||||
#endif /* __SkyDaemon_skyaptd_IcalResponse_H__ */
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "IcalResponse.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@implementation IcalResponse
|
||||
|
||||
- (void)_initContent {
|
||||
[self appendLine:@"BEGIN:VCALENDAR"];
|
||||
[self appendLine:@"VERSION:2.0"];
|
||||
[self appendLine:@"PRODID:-//skyrix42/scheduler/skyaptd v.1.0//"];
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
if ((self = [super init])) {
|
||||
self->content = [[NSMutableString alloc] initWithCapacity:0xFFFF];
|
||||
self->isFinished = NO;
|
||||
[self _initContent];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (id)initWithCapacity:(unsigned)_capacity {
|
||||
if ((self = [super init])) {
|
||||
self->content = [[NSMutableString alloc] initWithCapacity:_capacity];
|
||||
self->isFinished = NO;
|
||||
[self _initContent];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self->content release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)appendLine:(NSString *)_line {
|
||||
if (self->isFinished) {
|
||||
NSLog(@"WARNING[%s]: already finished!", __PRETTY_FUNCTION__);
|
||||
return NO;
|
||||
}
|
||||
// limit length to 75 chars
|
||||
while ([_line length] > 75) {
|
||||
[self appendLine:[_line substringToIndex:75]];
|
||||
_line = [@" " stringByAppendingString:[_line substringFromIndex:75]];
|
||||
}
|
||||
|
||||
[self->content appendString:_line];
|
||||
[self->content appendString:@"\r\n"];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)appendLine:(NSString *)_line forAttribute:(NSString *)_attr {
|
||||
_line = [NSString stringWithFormat:@"%@:%@", _attr, _line];
|
||||
return [self appendLine:_line];
|
||||
}
|
||||
|
||||
|
||||
- (void)finish {
|
||||
if (self->isFinished) return;
|
||||
[self appendLine:@"END:VCALENDAR"];
|
||||
self->isFinished = YES;
|
||||
}
|
||||
|
||||
- (NSString *)asString {
|
||||
[self finish];
|
||||
return [[self->content copy] autorelease];
|
||||
}
|
||||
|
||||
@end /* IcalResponse */
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>NGiCal</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.OpenGroupware.SOPE.ical.NGiCal</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string></string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>4.5</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_H__
|
||||
#define __NGCards_H__
|
||||
|
||||
#import <NGCards/iCalAttachment.h>
|
||||
#import <NGCards/iCalObject.h>
|
||||
#import <NGCards/iCalEntityObject.h>
|
||||
#import <NGCards/iCalRepeatableEntityObject.h>
|
||||
#import <NGCards/iCalCalendar.h>
|
||||
#import <NGCards/iCalToDo.h>
|
||||
#import <NGCards/iCalJournal.h>
|
||||
#import <NGCards/iCalEvent.h>
|
||||
#import <NGCards/iCalFreeBusy.h>
|
||||
#import <NGCards/iCalPerson.h>
|
||||
#import <NGCards/iCalAlarm.h>
|
||||
#import <NGCards/iCalTrigger.h>
|
||||
|
||||
#import <NGCards/iCalEventChanges.h>
|
||||
|
||||
#import <NGCards/iCalRecurrenceRule.h>
|
||||
#import <NGCards/iCalRecurrenceCalculator.h>
|
||||
|
||||
#import <NGCards/NSCalendarDate+ICal.h>
|
||||
|
||||
#import <NGCards/NSArray+NGCards.h>
|
||||
#import <NGCards/NSCalendarDate+ICal.h>
|
||||
#import <NGCards/NSCalendarDate+NGCards.h>
|
||||
#import <NGCards/NSDictionary+NGCards.h>
|
||||
#import <NGCards/NSString+NGCards.h>
|
||||
|
||||
#endif /* __NGCards_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,313 @@
|
|||
{
|
||||
"http://www.ietf.org/internet-drafts/draft-ietf-calsch-many-xcal-01.txt" = {
|
||||
|
||||
// components
|
||||
|
||||
iCalendar = {
|
||||
class = NSMutableDictionary; // "ICalXRoot";
|
||||
tagKey = "tag";
|
||||
|
||||
ToManyRelationships = {
|
||||
"subcomponents" = ( vcalendar );
|
||||
};
|
||||
};
|
||||
|
||||
vcalendar = {
|
||||
class = iCalCalendar; // ICalVCalendar;
|
||||
|
||||
attributes = {
|
||||
prodid = prodId;
|
||||
version = version;
|
||||
calscale = calscale;
|
||||
method = method;
|
||||
};
|
||||
|
||||
ToManyRelationships = {
|
||||
events = ( vevent );
|
||||
todos = ( vtodo );
|
||||
journals = ( journals );
|
||||
freeBusys = ( vfreebusy );
|
||||
timezones = ( vtimezone );
|
||||
};
|
||||
};
|
||||
|
||||
vevent = {
|
||||
class = iCalEvent;
|
||||
|
||||
attributes = {
|
||||
};
|
||||
|
||||
ToManyRelationships = {
|
||||
"alarms" = ( valarm );
|
||||
"attendees" = ( attendee );
|
||||
"recurrenceRules" = ( rrule );
|
||||
"exceptionRules" = ( exrule );
|
||||
"exceptionDates" = ( exdate );
|
||||
};
|
||||
};
|
||||
|
||||
vtodo = {
|
||||
class = "iCalToDo";
|
||||
|
||||
attributes = {
|
||||
};
|
||||
|
||||
ToManyRelationships = {
|
||||
"alarms" = ( valarm );
|
||||
"attendees" = ( attendee );
|
||||
};
|
||||
};
|
||||
|
||||
valarm = {
|
||||
class = "iCalAlarm";
|
||||
|
||||
attributes = {
|
||||
rrule = recurrenceRule;
|
||||
};
|
||||
};
|
||||
|
||||
vfreebusy = {
|
||||
class = "iCalFreeBusy";
|
||||
|
||||
ToManyRelationships = {
|
||||
"entries" = ( freebusy );
|
||||
};
|
||||
};
|
||||
|
||||
vtimezone = {
|
||||
class = NSMutableDictionary;
|
||||
|
||||
attributes = {
|
||||
tzid = timeZoneID;
|
||||
"X-LIC-LOCATION" = location;
|
||||
daylight = daylightInfo;
|
||||
standard = standardInfo;
|
||||
};
|
||||
};
|
||||
daylight = {
|
||||
class = NSMutableDictionary;
|
||||
|
||||
attributes = {
|
||||
tzoffsetfrom = tzOffsetFrom;
|
||||
tzoffsetto = tzOffsetTo;
|
||||
tzname = tzName;
|
||||
dtstart = startDate;
|
||||
rrule = recurrenceRule;
|
||||
};
|
||||
};
|
||||
standard = {
|
||||
class = NSMutableDictionary;
|
||||
|
||||
attributes = {
|
||||
tzoffsetfrom = tzOffsetFrom;
|
||||
tzoffsetto = tzOffsetTo;
|
||||
tzname = tzName;
|
||||
dtstart = startDate;
|
||||
rrule = recurrenceRule;
|
||||
};
|
||||
};
|
||||
|
||||
// attributes
|
||||
|
||||
dtstamp = {
|
||||
class = iCalDateHolder;
|
||||
key = "timeStampAsDate";
|
||||
tagKey = "tag";
|
||||
contentKey = "string";
|
||||
};
|
||||
created = {
|
||||
class = iCalDateHolder;
|
||||
key = "created";
|
||||
tagKey = "tag";
|
||||
contentKey = "string";
|
||||
};
|
||||
"last-modified" = {
|
||||
class = iCalDateHolder;
|
||||
key = "lastModified";
|
||||
tagKey = "tag";
|
||||
contentKey = "string";
|
||||
};
|
||||
|
||||
dtstart = {
|
||||
class = iCalDateHolder;
|
||||
key = "startDate";
|
||||
attributes = {
|
||||
tzid = tzid;
|
||||
};
|
||||
tagKey = "tag";
|
||||
contentKey = "string";
|
||||
};
|
||||
dtend = {
|
||||
class = iCalDateHolder;
|
||||
key = "endDate";
|
||||
attributes = {
|
||||
tzid = tzid;
|
||||
};
|
||||
tagKey = "tag";
|
||||
contentKey = "string";
|
||||
};
|
||||
exdate = {
|
||||
class = iCalDateHolder;
|
||||
key = "recurrenceRuleExceptionDate";
|
||||
attributes = {
|
||||
tzid = tzid;
|
||||
};
|
||||
tagKey = "tag";
|
||||
contentKey = "string";
|
||||
};
|
||||
due = {
|
||||
class = iCalDateHolder;
|
||||
attributes = {
|
||||
tzid = tzid;
|
||||
};
|
||||
tagKey = "tag";
|
||||
contentKey = "string";
|
||||
};
|
||||
completed = {
|
||||
class = iCalDateHolder;
|
||||
attributes = {
|
||||
tzid = tzid;
|
||||
};
|
||||
tagKey = "tag";
|
||||
contentKey = "string";
|
||||
};
|
||||
|
||||
duration = {
|
||||
class = NSString;
|
||||
};
|
||||
|
||||
summary = { class = NSString; };
|
||||
description = { class = NSString; key = comment; };
|
||||
comment = { class = NSString; key = userComment; };
|
||||
uid = { class = NSString; };
|
||||
action = { class = NSString; };
|
||||
priority = { class = NSString; };
|
||||
status = { class = NSString; };
|
||||
transp = { class = NSString; key = transparency; };
|
||||
sequence = { class = NSString; };
|
||||
categories = { class = NSString; };
|
||||
class = { class = NSString; key = accessClass; };
|
||||
percent-complete = { class = NSString; key = "percentComplete"; };
|
||||
|
||||
attendee = {
|
||||
class = iCalPerson;
|
||||
attributes = {
|
||||
cn = cn;
|
||||
rsvp = rsvp;
|
||||
role = role;
|
||||
partstat = partStat;
|
||||
};
|
||||
contentKey = "email";
|
||||
};
|
||||
organizer = {
|
||||
class = iCalPerson;
|
||||
attributes = {
|
||||
cn = cn;
|
||||
};
|
||||
contentKey = "email";
|
||||
};
|
||||
|
||||
freebusy = {
|
||||
class = NSString;
|
||||
};
|
||||
url = {
|
||||
class = NSString;
|
||||
};
|
||||
|
||||
trigger = {
|
||||
class = iCalTrigger;
|
||||
attributes = {
|
||||
value = valueType;
|
||||
};
|
||||
contentKey = "value";
|
||||
};
|
||||
attach = {
|
||||
class = iCalAttachment;
|
||||
attributes = {
|
||||
value = valueType;
|
||||
};
|
||||
contentKey = "value";
|
||||
};
|
||||
|
||||
tzid = {
|
||||
class = NSString;
|
||||
};
|
||||
tzname = {
|
||||
class = NSString;
|
||||
};
|
||||
tzoffsetfrom = {
|
||||
class = NSString;
|
||||
};
|
||||
tzoffsetto = {
|
||||
class = NSString;
|
||||
};
|
||||
rrule = {
|
||||
class = iCalRecurrenceRule;
|
||||
/*
|
||||
attributes = {
|
||||
freq = rrFreq;
|
||||
until = rrUntil;
|
||||
count = rrCount;
|
||||
interval = rrInterval;
|
||||
bysecond = rrBySecondList;
|
||||
byminute = rrByMinuteList;
|
||||
byhour = rrByHourList;
|
||||
byday = rrByDayList;
|
||||
bymonthday = rrByMonthDayList;
|
||||
byyearday = rrByYearDayList;
|
||||
byweekno = rrByWeekNumberList;
|
||||
bymonth = rrByMonthList;
|
||||
bysetpos = rrBySetPosList;
|
||||
wkst = rrWeekStart;
|
||||
};
|
||||
*/
|
||||
contentKey = "rrule";
|
||||
key = "recurrenceRule";
|
||||
};
|
||||
location = {
|
||||
class = NSString;
|
||||
};
|
||||
|
||||
// extra tags
|
||||
|
||||
"X-LIC-LOCATION" = {
|
||||
class = NSString;
|
||||
};
|
||||
|
||||
"X-WR-TIMEZONE" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
"X-WR-CALNAME" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
"X-WR-RELCALID" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
|
||||
"X-MICROSOFT-CDO-TZID" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
"X-MICROSOFT-CDO-BUSYSTATUS" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
"X-MICROSOFT-CDO-INSTTYPE" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
"X-MICROSOFT-CDO-INTENDEDSTATUS" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
"X-MICROSOFT-CDO-ALLDAYEVENT" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
"X-MICROSOFT-CDO-IMPORTANCE" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
|
||||
"X-PILOTID" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
"X-PILOTSTAT" = {
|
||||
rejectWithContent = YES;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Copyright (C) 2005 Helge Hess
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGiCal_NGCardsSaxHandler_H__
|
||||
#define __NGiCal_NGCardsSaxHandler_H__
|
||||
|
||||
#include <SaxObjC/SaxDefaultHandler.h>
|
||||
|
||||
/*
|
||||
NGCardsSaxHandler
|
||||
|
||||
This SAX handler is supposed to create the NGiCal object model from SAX
|
||||
events.
|
||||
*/
|
||||
|
||||
@class NSString, NSMutableString, NSMutableArray;
|
||||
@class NSDictionary, NSMutableDictionary;
|
||||
|
||||
@class CardElement;
|
||||
@class CardGroup;
|
||||
|
||||
@interface NGCardsSaxHandler : SaxDefaultHandler
|
||||
{
|
||||
NSMutableArray *cards;
|
||||
CardElement *currentElement;
|
||||
CardGroup *currentCardGroup;
|
||||
|
||||
NSString *currentGroup;
|
||||
unichar *content;
|
||||
unsigned contentLength;
|
||||
|
||||
NSMutableDictionary *xtags;
|
||||
NSMutableDictionary *subvalues;
|
||||
NSMutableArray *types;
|
||||
NSMutableDictionary *args;
|
||||
NSMutableArray *tel;
|
||||
NSMutableArray *adr;
|
||||
NSMutableArray *email;
|
||||
NSMutableArray *label;
|
||||
NSMutableArray *url;
|
||||
NSMutableArray *fburl;
|
||||
NSMutableArray *caluri;
|
||||
|
||||
struct {
|
||||
int isInVCardSet:1;
|
||||
int isInVCard:1;
|
||||
int isInN:1;
|
||||
int isInAdr:1;
|
||||
int isInOrg:1;
|
||||
int isInGroup:1;
|
||||
int isInGeo:1;
|
||||
int collectContent:1;
|
||||
int reserved:24;
|
||||
} vcs;
|
||||
|
||||
Class topGroupClass;
|
||||
}
|
||||
|
||||
/* results */
|
||||
|
||||
- (NSArray *) cards;
|
||||
- (void)reset;
|
||||
|
||||
/* content */
|
||||
|
||||
- (void) startCollectingContent;
|
||||
- (NSArray *) finishCollectingContent;
|
||||
|
||||
- (void) startGroupElement: (NSString *) _localName;
|
||||
- (void) endGroupElement;
|
||||
|
||||
- (void) setTopElementClass: (Class) aGroupClass;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_NGCardsSaxHandler_H__ */
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
Copyright (C) 2005 Helge Hess
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import "NGCardsSaxHandler.h"
|
||||
#import "common.h"
|
||||
#import <string.h>
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
#ifndef XMLNS_VCARD_XML_03
|
||||
# define XMLNS_VCARD_XML_03 \
|
||||
@"http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-03.txt"
|
||||
#endif
|
||||
|
||||
@implementation NGCardsSaxHandler
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
topGroupClass = nil;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
if (content)
|
||||
free(content);
|
||||
[cards release];
|
||||
if (currentGroup)
|
||||
[currentGroup release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* results */
|
||||
|
||||
- (NSArray *) cards
|
||||
{
|
||||
return [[cards copy] autorelease];;
|
||||
}
|
||||
|
||||
/* state */
|
||||
|
||||
- (void)resetExceptResult
|
||||
{
|
||||
if (content)
|
||||
{
|
||||
free(content);
|
||||
content = NULL;
|
||||
}
|
||||
|
||||
vcs.isInVCardSet = 0;
|
||||
vcs.collectContent = 0;
|
||||
}
|
||||
|
||||
- (void) reset
|
||||
{
|
||||
[self resetExceptResult];
|
||||
[cards removeAllObjects];
|
||||
}
|
||||
|
||||
/* document events */
|
||||
|
||||
- (void) startDocument
|
||||
{
|
||||
if (!cards)
|
||||
cards = [[NSMutableArray alloc] initWithCapacity:16];
|
||||
[self reset];
|
||||
}
|
||||
|
||||
- (void) endDocument
|
||||
{
|
||||
[self resetExceptResult];
|
||||
}
|
||||
|
||||
/* common tags */
|
||||
|
||||
- (void) startValueTag: (NSString *) _tag
|
||||
attributes: (id<SaxAttributes>) _attrs
|
||||
{
|
||||
/* a tag with types and attributes */
|
||||
unsigned i, count;
|
||||
|
||||
[types removeAllObjects];
|
||||
[args removeAllObjects];
|
||||
|
||||
for (i = 0, count = [_attrs count]; i < count; i++) {
|
||||
NSString *n, *v;
|
||||
|
||||
n = [_attrs nameAtIndex:i];
|
||||
v = [_attrs valueAtIndex:i];
|
||||
|
||||
if ([n hasSuffix:@".type"] || [n isEqualToString:@"TYPE"]) {
|
||||
/*
|
||||
Note: types cannot be separated by comma! Its indeed always a space,eg
|
||||
"work pref voice"
|
||||
If you find commas, usually the vCard is broken.
|
||||
*/
|
||||
NSEnumerator *e;
|
||||
NSString *k;
|
||||
|
||||
e = [[v componentsSeparatedByString:@" "] objectEnumerator];
|
||||
while ((k = [e nextObject]) != nil) {
|
||||
k = [k uppercaseString];
|
||||
if ([types containsObject:k]) continue;
|
||||
[types addObject:k];
|
||||
}
|
||||
}
|
||||
else
|
||||
[args setObject:v forKey:n];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)endValueTag
|
||||
{
|
||||
[types removeAllObjects];
|
||||
[args removeAllObjects];
|
||||
}
|
||||
|
||||
/* handle elements */
|
||||
|
||||
- (void) startGroup: (NSString *)_name
|
||||
{
|
||||
vcs.isInGroup = 1;
|
||||
ASSIGNCOPY(currentGroup, _name);
|
||||
}
|
||||
|
||||
- (void) endGroup
|
||||
{
|
||||
vcs.isInGroup = 0;
|
||||
[currentGroup release];
|
||||
currentGroup = nil;
|
||||
}
|
||||
|
||||
- (void)startVCardSet
|
||||
{
|
||||
currentCardGroup = nil;
|
||||
currentGroup = nil;
|
||||
vcs.isInVCardSet = 1;
|
||||
}
|
||||
|
||||
- (void)endVCardSet
|
||||
{
|
||||
vcs.isInVCardSet = 0;
|
||||
}
|
||||
|
||||
/* element events */
|
||||
|
||||
- (void) startElement:(NSString *)_localName
|
||||
namespace:(NSString *)_ns
|
||||
rawName:(NSString *)_rawName
|
||||
attributes:(id<SaxAttributes>)_attrs
|
||||
{
|
||||
unsigned int count, max;
|
||||
Class elementClass;
|
||||
|
||||
// NSLog (@"startElement localName: '%@'", _localName);
|
||||
|
||||
if ([_localName isEqualToString: @"vCardSet"])
|
||||
[self startVCardSet];
|
||||
else if ([_localName isEqualToString: @"group"])
|
||||
[self startGroup: [_attrs valueAtIndex: 0]];
|
||||
else if ([_localName isEqualToString: @"container"])
|
||||
[self startGroupElement: [_attrs valueAtIndex: 0]];
|
||||
else
|
||||
{
|
||||
if (currentCardGroup)
|
||||
elementClass
|
||||
= [currentCardGroup classForTag: [_localName uppercaseString]];
|
||||
else
|
||||
elementClass = topGroupClass;
|
||||
|
||||
if (!elementClass)
|
||||
elementClass = [CardElement class];
|
||||
|
||||
currentElement = [elementClass elementWithTag: _localName];
|
||||
[currentElement setTag: _localName];
|
||||
if (currentGroup)
|
||||
[currentElement setGroup: currentGroup];
|
||||
|
||||
max = [_attrs count];
|
||||
for (count = 0; count < max; count++)
|
||||
[currentElement addAttribute: [_attrs nameAtIndex: count]
|
||||
value: [_attrs valueAtIndex: count]];
|
||||
|
||||
[currentCardGroup addChild: currentElement];
|
||||
[self startCollectingContent];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) endElement: (NSString *)_localName
|
||||
namespace: (NSString *)_ns
|
||||
rawName: (NSString *)_rawName
|
||||
{
|
||||
// NSLog (@"endElement localName: '%@'", _localName);
|
||||
if ([_localName isEqualToString: @"vCardSet"])
|
||||
[self endVCardSet];
|
||||
else if ([_localName isEqualToString: @"group"])
|
||||
[self endGroup];
|
||||
else if ([_localName isEqualToString: @"container"])
|
||||
[self endGroupElement];
|
||||
else
|
||||
[currentElement addValues: [self finishCollectingContent]];
|
||||
}
|
||||
|
||||
/* content */
|
||||
|
||||
- (void) startCollectingContent
|
||||
{
|
||||
if (content) {
|
||||
free(content);
|
||||
content = NULL;
|
||||
}
|
||||
vcs.collectContent = 1;
|
||||
}
|
||||
|
||||
- (NSArray *) finishCollectingContent
|
||||
{
|
||||
NSArray *contentValues;
|
||||
NSString *s;
|
||||
|
||||
vcs.collectContent = 0;
|
||||
|
||||
if (content && contentLength)
|
||||
{
|
||||
s = [NSString stringWithCharacters: content
|
||||
length: contentLength];
|
||||
free (content);
|
||||
content = NULL;
|
||||
// NSLog (@"content: '%@'", s);
|
||||
contentValues = [s componentsSeparatedByString: @";"];
|
||||
}
|
||||
else
|
||||
contentValues = nil;
|
||||
|
||||
return contentValues;
|
||||
}
|
||||
|
||||
- (void) characters:(unichar *)_chars
|
||||
length:(int)_len
|
||||
{
|
||||
if (_len && _chars)
|
||||
{
|
||||
if (!content)
|
||||
{
|
||||
/* first content */
|
||||
contentLength = _len;
|
||||
content = calloc (_len + 1, sizeof(unichar));
|
||||
memcpy (content, _chars, (_len * sizeof(unichar)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* increase content */
|
||||
content =
|
||||
realloc (content, (contentLength + _len+2) * sizeof(unichar));
|
||||
memcpy (&(content[contentLength]), _chars,
|
||||
(_len * sizeof(unichar)));
|
||||
contentLength += _len;
|
||||
}
|
||||
content[contentLength] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) startGroupElement: (NSString *) _localName
|
||||
{
|
||||
CardGroup *newGroup;
|
||||
Class groupClass;
|
||||
|
||||
// NSLog (@"startGroupElement localName: '%@'", _localName);
|
||||
|
||||
if (currentCardGroup)
|
||||
{
|
||||
groupClass
|
||||
= [currentCardGroup classForTag: [_localName uppercaseString]];
|
||||
if (!groupClass)
|
||||
groupClass = [CardGroup class];
|
||||
|
||||
newGroup = [groupClass groupWithTag: _localName];
|
||||
[currentCardGroup addChild: newGroup];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (topGroupClass)
|
||||
groupClass = topGroupClass;
|
||||
else
|
||||
groupClass = [CardGroup class];
|
||||
|
||||
newGroup = [groupClass groupWithTag: _localName];
|
||||
[cards addObject: newGroup];
|
||||
}
|
||||
|
||||
currentCardGroup = newGroup;
|
||||
}
|
||||
|
||||
- (void) endGroupElement
|
||||
{
|
||||
// NSLog (@"endGroupElement localName: '%@'", _localName);
|
||||
|
||||
if (currentCardGroup)
|
||||
currentCardGroup = [currentCardGroup parent];
|
||||
}
|
||||
|
||||
- (void) setTopElementClass: (Class) aGroupClass
|
||||
{
|
||||
topGroupClass = aGroupClass;
|
||||
}
|
||||
|
||||
@end /* NGCardsSaxHandler */
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
Copyright (C) 2005 Helge Hess
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGiCal_NGVCard_H__
|
||||
#define __NGiCal_NGVCard_H__
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
/*
|
||||
NGVCard
|
||||
|
||||
Represents a vCard object.
|
||||
|
||||
XML DTD in Dawson-03 Draft:
|
||||
<!ELEMENT vCard (%prop.man;, (%prop.opt;)*)>
|
||||
|
||||
<!ATTLIST vCard
|
||||
%attr.lang;
|
||||
xmlns CDATA #FIXED
|
||||
'http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-02.txt'
|
||||
xmlns:vcf CDATA #FIXED
|
||||
'http://www.ietf.org/internet-drafts/draft-dawson-vcard-xml-dtd-02.txt'
|
||||
version CDATA #REQUIRED
|
||||
rev CDATA #IMPLIED
|
||||
uid CDATA #IMPLIED
|
||||
prodid CDATA #IMPLIED
|
||||
class (PUBLIC | PRIVATE | CONFIDENTIAL) "PUBLIC"
|
||||
value NOTATION (VCARD) #IMPLIED>
|
||||
<!-- version - Must be "3.0" if document conforms to this spec -->
|
||||
<!-- rev - ISO 8601 formatted date or date/time string -->
|
||||
<!-- uid - UID associated with the object described by the vCard -->
|
||||
<!-- prodid - ISO 9070 FPI for product that generated vCard -->
|
||||
<!-- class - Security classification for vCard information -->
|
||||
|
||||
Mandatory elements:
|
||||
n
|
||||
fn
|
||||
*/
|
||||
|
||||
@class NSArray;
|
||||
@class NSDictionary;
|
||||
@class NSString;
|
||||
|
||||
@interface NGVCard : CardGroup
|
||||
|
||||
+ (id) cardWithUid: (NSString *) _uid;
|
||||
- (id) initWithUid: (NSString *) _uid;
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setVersion: (NSString *) _version;
|
||||
- (NSString *) version;
|
||||
|
||||
- (void) setUid: (NSString *) _uid;
|
||||
- (NSString *) uid;
|
||||
|
||||
- (void) setPreferred: (CardElement *) aChild;
|
||||
|
||||
- (void) setVClass: (NSString *) _s;
|
||||
- (NSString *) vClass;
|
||||
- (void) setVName: (NSString *) _s;
|
||||
- (NSString *) vName;
|
||||
- (void) setProdID: (NSString *) _s;
|
||||
- (NSString *) prodID;
|
||||
- (void) setProfile: (NSString *) _s;
|
||||
- (NSString *) profile;
|
||||
- (void) setSource: (NSString *) _s;
|
||||
- (NSString *) source;
|
||||
|
||||
- (void) setFn: (NSString *) _fn;
|
||||
- (NSString *) fn;
|
||||
- (void) setNickname: (NSString *) aValue;
|
||||
- (NSString *) nickname;
|
||||
|
||||
- (void) setRole: (NSString *) _s;
|
||||
- (NSString *) role;
|
||||
- (void) setTitle: (NSString *) _title;
|
||||
- (NSString *) title;
|
||||
- (void) setBday: (NSString *) _bday;
|
||||
- (NSString *) bday;
|
||||
- (void) setNote: (NSString *) _note;
|
||||
- (NSString *) note;
|
||||
- (void) setTz: (NSString *) _tz;
|
||||
- (NSString *) tz;
|
||||
|
||||
- (void) addTel: (NSString *) phoneNumber
|
||||
types: (NSArray *) types;
|
||||
- (void) addEmail: (NSString *) emailAddress
|
||||
types: (NSArray *) types;
|
||||
|
||||
- (void) setNWithFamily: (NSString *) family
|
||||
given: (NSString *) given
|
||||
additional: (NSString *) additional
|
||||
prefixes: (NSString *) prefixes
|
||||
suffixes: (NSString *) suffixes;
|
||||
- (NSArray *) n;
|
||||
|
||||
- (void) setOrg: (NSString *) anOrg
|
||||
units: (NSArray *) someUnits;
|
||||
- (NSArray *) org;
|
||||
|
||||
// - (void) setN: (NGVCardName *) _v;
|
||||
// - (NGVCardName *) n;
|
||||
// - (void) setOrg: (NGVCardOrg *) _v;
|
||||
// - (NGVCardOrg *) org;
|
||||
|
||||
// - (void) setCategories: (id) _v;
|
||||
// - (NGVCardStrArrayValue *) categories;
|
||||
|
||||
// - (void) setTel: (NSArray *) _tel;
|
||||
// - (NSArray *) tel;
|
||||
// - (void) setAdr: (NSArray *) _adr;
|
||||
// - (NSArray *) adr;
|
||||
// - (void) setEmail: (NSArray *) _array;
|
||||
// - (NSArray *) email;
|
||||
// - (void) setLabel: (NSArray *) _array;
|
||||
// - (NSArray *) label;
|
||||
// - (void) setUrl: (NSArray *) _url;
|
||||
// - (NSArray *) url;
|
||||
|
||||
// - (void) setFreeBusyURL: (NSArray *) _v;
|
||||
// - (NSArray *) freeBusyURL;
|
||||
// - (void) setCalURI: (NSArray *) _calURI;
|
||||
// - (NSArray *) calURI;
|
||||
|
||||
// - (void) setX: (NSDictionary *) _dict;
|
||||
// - (NSDictionary *) x;
|
||||
|
||||
/* convenience */
|
||||
|
||||
- (NSString *) preferredEMail;
|
||||
- (NSString *) preferredTel;
|
||||
- (CardElement *) preferredAdr;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_NGVCard_H__ */
|
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
Copyright (C) 2005 Helge Hess
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSEnumerator.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "NSArray+NGCards.h"
|
||||
|
||||
#import "NGVCard.h"
|
||||
|
||||
@implementation NGVCard
|
||||
|
||||
+ (id) parseSingleFromSource: (id) source
|
||||
{
|
||||
NGVCard *newCard;
|
||||
|
||||
newCard = [super parseSingleFromSource: source];
|
||||
[newCard setVersion: @"3.0"];
|
||||
|
||||
return newCard;
|
||||
}
|
||||
|
||||
+ (id) cardWithUid: (NSString *) _uid
|
||||
{
|
||||
NGVCard *newCard;
|
||||
|
||||
newCard = [[self alloc] initWithUid: _uid];
|
||||
[newCard autorelease];
|
||||
|
||||
return newCard;
|
||||
}
|
||||
|
||||
- (id) initWithUid: (NSString *) _uid
|
||||
{
|
||||
if ((self = [self init]))
|
||||
{
|
||||
[self setTag: @"vcard"];
|
||||
[self setUid: _uid];
|
||||
[self setVersion: @"3.0"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/* class mapping */
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
tagClass = Nil;
|
||||
if ([classTag isEqualToString: @"PRODID"]
|
||||
|| [classTag isEqualToString: @"PRODID"]
|
||||
|| [classTag isEqualToString: @"PROFILE"]
|
||||
|| [classTag isEqualToString: @"UID"]
|
||||
|| [classTag isEqualToString: @"CLASS"]
|
||||
|| [classTag isEqualToString: @"N"]
|
||||
|| [classTag isEqualToString: @"FN"]
|
||||
|| [classTag isEqualToString: @"ORG"]
|
||||
|| [classTag isEqualToString: @"ADR"]
|
||||
|| [classTag isEqualToString: @"TEL"]
|
||||
|| [classTag isEqualToString: @"TZ"]
|
||||
|| [classTag isEqualToString: @"URL"]
|
||||
|| [classTag isEqualToString: @"LABEL"]
|
||||
|| [classTag isEqualToString: @"EMAIL"]
|
||||
|| [classTag isEqualToString: @"NICKNAME"]
|
||||
|| [classTag isEqualToString: @"NOTE"]
|
||||
|| [classTag isEqualToString: @"BDAY"]
|
||||
|| [classTag isEqualToString: @"TITLE"]
|
||||
|| [classTag isEqualToString: @"VERSION"])
|
||||
tagClass = [CardElement class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
- (void) setPreferred: (CardElement *) aChild
|
||||
{
|
||||
NSEnumerator *elements;
|
||||
CardElement *element;
|
||||
|
||||
if (![aChild hasAttribute: @"type" havingValue: @"pref"])
|
||||
{
|
||||
elements = [[children cardElementsWithTag: tag] objectEnumerator];
|
||||
element = [elements nextObject];
|
||||
while (element)
|
||||
{
|
||||
[element removeValue: @"pref" fromAttribute: @"type"];
|
||||
element = [elements nextObject];
|
||||
}
|
||||
[aChild addAttribute: @"type" value: @"pref"];
|
||||
}
|
||||
}
|
||||
|
||||
/* helpers */
|
||||
- (NSArray *) childrenWithType: (NSString *) aType
|
||||
{
|
||||
return [self childrenWithAttribute: @"type" havingValue: aType];
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setVersion: (NSString *) _version
|
||||
{
|
||||
[[self uniqueChildWithTag: @"version"] setValue: 0 to: _version];
|
||||
}
|
||||
|
||||
- (NSString *) version
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"version"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setUid: (NSString *) _uid
|
||||
{
|
||||
[[self uniqueChildWithTag: @"uid"] setValue: 0 to: _uid];
|
||||
}
|
||||
|
||||
- (NSString *) uid
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"uid"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setVClass: (NSString *) _class
|
||||
{
|
||||
[[self uniqueChildWithTag: @"class"] setValue: 0 to: _class];
|
||||
}
|
||||
|
||||
- (NSString *) vClass
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"class"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setVName: (NSString *) _vname
|
||||
{
|
||||
[[self uniqueChildWithTag: @"vname"] setValue: 0 to: _vname];
|
||||
}
|
||||
|
||||
- (NSString *) vName
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"vname"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setProdID: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"prodid"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) prodID
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"prodid"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setProfile: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"profile"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) profile
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"profile"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setSource: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"source"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) source
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"source"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setFn: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"fn"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) fn
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"fn"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setRole: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"role"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) role
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"role"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setTitle: (NSString *) _title
|
||||
{
|
||||
[[self uniqueChildWithTag: @"title"] setValue: 0 to: _title];
|
||||
}
|
||||
|
||||
- (NSString *) title
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"title"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setBday: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"bday"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) bday
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"bday"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setNote: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"note"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) note
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"note"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setTz: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"tz"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) tz
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"tz"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setNickname: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"nickname"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) nickname
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"nickname"] value: 0];
|
||||
}
|
||||
|
||||
- (void) addTel: (NSString *) phoneNumber
|
||||
types: (NSArray *) types
|
||||
{
|
||||
[self addChildWithTag: @"tel" types: types singleValue: phoneNumber];
|
||||
}
|
||||
|
||||
- (void) addEmail: (NSString *) emailAddress
|
||||
types: (NSArray *) types
|
||||
{
|
||||
[self addChildWithTag: @"email"
|
||||
types: types
|
||||
singleValue: emailAddress];
|
||||
}
|
||||
|
||||
- (void) setNWithFamily: (NSString *) family
|
||||
given: (NSString *) given
|
||||
additional: (NSString *) additional
|
||||
prefixes: (NSString *) prefixes
|
||||
suffixes: (NSString *) suffixes
|
||||
{
|
||||
CardElement *n;
|
||||
|
||||
n = [self uniqueChildWithTag: @"n"];
|
||||
if (family)
|
||||
[n setValue: 0 to: family];
|
||||
if (given)
|
||||
[n setValue: 1 to: given];
|
||||
if (additional)
|
||||
[n setValue: 2 to: additional];
|
||||
if (prefixes)
|
||||
[n setValue: 3 to: prefixes];
|
||||
if (suffixes)
|
||||
[n setValue: 4 to: suffixes];
|
||||
}
|
||||
|
||||
- (NSArray *) n
|
||||
{
|
||||
NSArray *elements, *n;
|
||||
|
||||
elements = [self childrenWithTag: @"n"];
|
||||
if ([elements count] > 0)
|
||||
n = [[elements objectAtIndex: 0] values];
|
||||
else
|
||||
n = nil;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
- (void) setOrg: (NSString *) anOrg
|
||||
units: (NSArray *) someUnits
|
||||
{
|
||||
CardElement *org;
|
||||
unsigned int count, max;
|
||||
|
||||
org = [self uniqueChildWithTag: @"org"];
|
||||
if (anOrg)
|
||||
[org setValue: 0 to: anOrg];
|
||||
if (someUnits)
|
||||
{
|
||||
max = [someUnits count];
|
||||
for (count = 0; count < max; count++)
|
||||
[org setValue: count + 1 to: [someUnits objectAtIndex: count]];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *) org
|
||||
{
|
||||
NSArray *elements, *org;
|
||||
|
||||
elements = [self childrenWithTag: @"org"];
|
||||
if ([elements count] > 0)
|
||||
org = [[elements objectAtIndex: 0] values];
|
||||
else
|
||||
org = nil;
|
||||
|
||||
return org;
|
||||
}
|
||||
|
||||
// - (void) setOrg: (NGVCardOrg *) _v
|
||||
// {
|
||||
// ASSIGNCOPY(self->org, _v);
|
||||
// }
|
||||
|
||||
// - (NGVCardOrg *)org {
|
||||
// return self->org;
|
||||
// }
|
||||
|
||||
// - (void)setNickname: (id) _v
|
||||
// {
|
||||
// if (![_v isKindOfClass:[NGVCardStrArrayValue class]] && [_v isNotNull])
|
||||
// _v = [[[NGVCardStrArrayValue alloc] initWithPropertyList:_v] autorelease];
|
||||
|
||||
// ASSIGNCOPY(self->nickname, _v);
|
||||
// }
|
||||
|
||||
// - (NGVCardStrArrayValue *) nickname
|
||||
// {
|
||||
// return self->nickname;
|
||||
// }
|
||||
|
||||
// - (void) setCategories: (id) _v
|
||||
// {
|
||||
// if (![_v isKindOfClass:[NGVCardStrArrayValue class]] && [_v isNotNull])
|
||||
// _v = [[[NGVCardStrArrayValue alloc] initWithPropertyList:_v] autorelease];
|
||||
|
||||
// ASSIGNCOPY(self->categories, _v);
|
||||
// }
|
||||
|
||||
// - (NGVCardStrArrayValue *) categories
|
||||
// {
|
||||
// return self->categories;
|
||||
// }
|
||||
|
||||
// - (void) setTel: (NSArray *) _tel
|
||||
// {
|
||||
// ASSIGNCOPY(self->tel, _tel);
|
||||
// }
|
||||
|
||||
// - (NSArray *) tel
|
||||
// {
|
||||
// return [self childrenWithTag: @"tel"];
|
||||
// }
|
||||
|
||||
// - (void) setAdr: (NSArray *) _adr
|
||||
// {
|
||||
// ASSIGNCOPY(self->adr, _adr);
|
||||
// }
|
||||
|
||||
// - (NSArray *) adr
|
||||
// {
|
||||
// return self->adr;
|
||||
// }
|
||||
|
||||
// - (void) setEmail: (NSArray *) _email
|
||||
// {
|
||||
// ASSIGNCOPY(self->email, _email);
|
||||
// }
|
||||
|
||||
// - (NSArray *) email
|
||||
// {
|
||||
// return [self childrenWithTag: @"email"];
|
||||
// }
|
||||
|
||||
// - (void) setLabel: (NSArray *) _label
|
||||
// {
|
||||
// ASSIGNCOPY(self->label, _label);
|
||||
// }
|
||||
|
||||
// - (NSArray *) label
|
||||
// {
|
||||
// return [self childrenWithTag: @"email"];
|
||||
// }
|
||||
|
||||
// - (void) setUrl: (NSArray *) _url
|
||||
// {
|
||||
// ASSIGNCOPY(self->url, _url);
|
||||
// }
|
||||
|
||||
// - (NSArray *) url
|
||||
// {
|
||||
// return self->url;
|
||||
// }
|
||||
|
||||
// - (void) setFreeBusyURL: (NSArray *) _v
|
||||
// {
|
||||
// ASSIGNCOPY(self->fburl, _v);
|
||||
// }
|
||||
|
||||
// - (NSArray *) freeBusyURL
|
||||
// {
|
||||
// return self->fburl;
|
||||
// }
|
||||
|
||||
// - (void) setCalURI: (NSArray *) _v
|
||||
// {
|
||||
// ASSIGNCOPY(self->caluri, _v);
|
||||
// }
|
||||
|
||||
// - (NSArray *) calURI
|
||||
// {
|
||||
// return self->caluri;
|
||||
// }
|
||||
|
||||
// - (void) setX: (NSDictionary *) _dict
|
||||
// {
|
||||
// ASSIGNCOPY(self->x, _dict);
|
||||
// }
|
||||
|
||||
// - (NSDictionary *) x
|
||||
// {
|
||||
// return self->x;
|
||||
// }
|
||||
|
||||
/* convenience */
|
||||
|
||||
- (CardElement *) _preferredElementWithTag: (NSString *) aTag
|
||||
{
|
||||
NSArray *elements, *prefElements;
|
||||
CardElement *element;
|
||||
|
||||
elements = [self childrenWithTag: aTag];
|
||||
if (elements && [elements count] > 0)
|
||||
{
|
||||
prefElements = [elements cardElementsWithAttribute: @"type"
|
||||
havingValue: @"pref"];
|
||||
if (prefElements && [prefElements count] > 0)
|
||||
element = [prefElements objectAtIndex: 0];
|
||||
else
|
||||
element = [elements objectAtIndex: 0];
|
||||
}
|
||||
else
|
||||
element = nil;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
- (NSString *) preferredEMail
|
||||
{
|
||||
return [[self _preferredElementWithTag: @"email"] value: 0];
|
||||
}
|
||||
|
||||
- (NSString *) preferredTel
|
||||
{
|
||||
return [[self _preferredElementWithTag: @"tel"] value: 0];
|
||||
}
|
||||
|
||||
- (CardElement *) preferredAdr
|
||||
{
|
||||
return [self _preferredElementWithTag: @"adr"];
|
||||
}
|
||||
|
||||
/* description */
|
||||
|
||||
- (void) appendAttributesToDescription: (NSMutableString *) _ms
|
||||
{
|
||||
if ([self uid]) [_ms appendFormat:@" uid='%@'", [self uid]];
|
||||
|
||||
// if ([[self tel] count] > 0) [_ms appendFormat:@" tel=%@", [self tel];
|
||||
// if ([[self adr] count])
|
||||
// [_ms appendFormat:@" adr=%@", [self adr]];
|
||||
// if ([[self email] count])
|
||||
// [_ms appendFormat:@" email=%@", [self email]];
|
||||
// if ([[self label] count])
|
||||
// [_ms appendFormat:@" label=%@", [self label]];
|
||||
// if ([[self x] count])
|
||||
// [_ms appendFormat:@" x=%@", [self x]];
|
||||
}
|
||||
|
||||
- (NSString *) description
|
||||
{
|
||||
NSMutableString *str = nil;
|
||||
|
||||
str = [NSMutableString stringWithCapacity:64];
|
||||
[str appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
|
||||
[self appendAttributesToDescription:str];
|
||||
[str appendString:@">"];
|
||||
return str;
|
||||
}
|
||||
|
||||
@end /* NGVCard */
|
|
@ -0,0 +1,42 @@
|
|||
/* NSArray+NGCards.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef NSARRAY_NGCARDS_H
|
||||
#define NSARRAY_NGCARDS_H
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
|
||||
@interface NSArray (NGCardsExtensions)
|
||||
|
||||
- (NSString *) valueForCaseInsensitiveString: (NSString *) aString;
|
||||
|
||||
- (BOOL) hasCaseInsensitiveString: (NSString *) aString;
|
||||
|
||||
- (NSArray *) cardElementsWithTag: (NSString *) aTag;
|
||||
- (NSArray *) cardElementsWithAttribute: (NSString *) anAttribute
|
||||
havingValue: (NSString *) aValue;
|
||||
|
||||
- (NSArray *) renderedForCards;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NSARRAY_NGCARDS_H */
|
|
@ -0,0 +1,133 @@
|
|||
/* NSArray+NGCards.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "CardElement.h"
|
||||
#import "NSString+NGCards.h"
|
||||
|
||||
#import "NSArray+NGCards.h"
|
||||
|
||||
@implementation NSArray (NGCardsExtensions)
|
||||
|
||||
- (NSString *) valueForCaseInsensitiveString: (NSString *) aString
|
||||
{
|
||||
NSString *currentString, *resultString, *cmpString;
|
||||
unsigned int count, max;
|
||||
BOOL found;
|
||||
|
||||
found = NO;
|
||||
|
||||
cmpString = [aString uppercaseString];
|
||||
max = [self count];
|
||||
count = 0;
|
||||
|
||||
currentString = nil;
|
||||
while (!found && count < max)
|
||||
{
|
||||
currentString = [self objectAtIndex: count];
|
||||
if ([[currentString uppercaseString] isEqualToString: cmpString])
|
||||
found = YES;
|
||||
else
|
||||
count++;
|
||||
}
|
||||
|
||||
if (found)
|
||||
resultString = currentString;
|
||||
else
|
||||
resultString = nil;
|
||||
|
||||
return resultString;
|
||||
}
|
||||
|
||||
- (BOOL) hasCaseInsensitiveString: (NSString *) aString
|
||||
{
|
||||
return ([self valueForCaseInsensitiveString: aString] != nil);
|
||||
}
|
||||
|
||||
- (NSArray *) cardElementsWithTag: (NSString *) aTag
|
||||
{
|
||||
NSMutableArray *matchingElements;
|
||||
NSEnumerator *allElements;
|
||||
CardElement *currentElement;
|
||||
NSString *cmpTag, *currentTag;
|
||||
|
||||
cmpTag = [aTag uppercaseString];
|
||||
|
||||
matchingElements = [NSMutableArray new];
|
||||
[matchingElements autorelease];
|
||||
|
||||
allElements = [self objectEnumerator];
|
||||
currentElement = [allElements nextObject];
|
||||
while (currentElement)
|
||||
{
|
||||
currentTag = [[currentElement tag] uppercaseString];
|
||||
if ([currentTag isEqualToString: cmpTag])
|
||||
[matchingElements addObject: currentElement];
|
||||
currentElement = [allElements nextObject];
|
||||
}
|
||||
|
||||
return matchingElements;
|
||||
}
|
||||
|
||||
- (NSArray *) cardElementsWithAttribute: (NSString *) anAttribute
|
||||
havingValue: (NSString *) aValue
|
||||
{
|
||||
NSMutableArray *matchingElements;
|
||||
NSEnumerator *allElements;
|
||||
CardElement *currentElement;
|
||||
|
||||
allElements = [self objectEnumerator];
|
||||
|
||||
matchingElements = [NSMutableArray new];
|
||||
[matchingElements autorelease];
|
||||
currentElement = [allElements nextObject];
|
||||
while (currentElement)
|
||||
{
|
||||
if ([currentElement hasAttribute: anAttribute
|
||||
havingValue: aValue])
|
||||
[matchingElements addObject: currentElement];
|
||||
currentElement = [allElements nextObject];
|
||||
}
|
||||
|
||||
return matchingElements;
|
||||
}
|
||||
|
||||
- (NSArray *) renderedForCards
|
||||
{
|
||||
NSMutableArray *purified;
|
||||
NSString *string;
|
||||
NSEnumerator *strings;
|
||||
|
||||
purified = [NSMutableArray arrayWithCapacity: [self count]];
|
||||
strings = [self objectEnumerator];
|
||||
string = [strings nextObject];
|
||||
while (string)
|
||||
{
|
||||
[purified addObject: [string escapedForCards]];
|
||||
string = [strings nextObject];
|
||||
}
|
||||
|
||||
return purified;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGiCal_NSCalendarDate_ICal_H__
|
||||
#define __NGiCal_NSCalendarDate_ICal_H__
|
||||
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
|
||||
@class NSTimeZone;
|
||||
|
||||
@interface NSCalendarDate(iCalRepresentation)
|
||||
|
||||
+ (id)calendarDateWithICalRepresentation:(NSString *)_iCalRep;
|
||||
|
||||
/* represention */
|
||||
|
||||
- (NSString *)icalStringWithTimeZone:(NSTimeZone *)_tz;
|
||||
- (NSString *)icalString;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSCalendarDate (iCalRecurrenceCalculatorExtensions)
|
||||
- (unsigned)yearsBetweenDate:(NSCalendarDate *)_date;
|
||||
- (unsigned)monthsBetweenDate:(NSCalendarDate *)_date;
|
||||
- (unsigned)daysBetweenDate:(NSCalendarDate *)_date;
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_NSCalendarDate_ICal_H__ */
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "NSCalendarDate+ICal.h"
|
||||
#include "iCalDateHolder.h"
|
||||
#include "common.h"
|
||||
|
||||
static NSTimeZone *gmt = nil;
|
||||
static inline void _setupGMT(void) {
|
||||
if (gmt == nil)
|
||||
gmt = [[NSTimeZone timeZoneWithAbbreviation:@"GMT"] retain];
|
||||
}
|
||||
|
||||
@interface iCalDateHolder (PrivateAPI)
|
||||
- (id)awakeAfterUsingSaxDecoder:(id)_decoder;
|
||||
@end
|
||||
|
||||
@implementation NSCalendarDate(iCalRepresentation)
|
||||
|
||||
/* represention */
|
||||
|
||||
static NSString *gmtcalfmt = @"%Y%m%dT%H%M%SZ";
|
||||
|
||||
+ (id)calendarDateWithICalRepresentation:(NSString *)_iCalRep {
|
||||
iCalDateHolder *dh;
|
||||
NSCalendarDate *date;
|
||||
|
||||
dh = [[iCalDateHolder alloc] init];
|
||||
[dh setString:_iCalRep];
|
||||
date = [dh awakeAfterUsingSaxDecoder:nil];
|
||||
[dh release];
|
||||
return date;
|
||||
}
|
||||
|
||||
- (NSString *)icalStringInGMT {
|
||||
NSTimeZone *oldtz;
|
||||
NSString *s;
|
||||
_setupGMT();
|
||||
|
||||
/* set GMT as timezone */
|
||||
oldtz = [[self timeZone] retain];
|
||||
if (oldtz == gmt) {
|
||||
[oldtz release];
|
||||
oldtz = nil;
|
||||
}
|
||||
else {
|
||||
[self setTimeZone:gmt];
|
||||
}
|
||||
|
||||
/* calc string */
|
||||
s = [self descriptionWithCalendarFormat:gmtcalfmt];
|
||||
|
||||
/* restore old timezone */
|
||||
if (oldtz) {
|
||||
[self setTimeZone:oldtz];
|
||||
[oldtz release];
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
- (NSString *)icalStringWithTimeZone:(NSTimeZone *)_tz {
|
||||
_setupGMT();
|
||||
|
||||
if (_tz == gmt || _tz == nil)
|
||||
return [self icalStringInGMT];
|
||||
else if ([_tz isEqual:gmt])
|
||||
return [self icalStringInGMT];
|
||||
else {
|
||||
/* not in GMT */
|
||||
NSLog(@"WARNING(%s): arbitary timezones not supported yet: %@",
|
||||
__PRETTY_FUNCTION__, _tz);
|
||||
return [self icalStringInGMT];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)icalString {
|
||||
_setupGMT();
|
||||
return [self icalStringWithTimeZone:gmt];
|
||||
}
|
||||
|
||||
@end /* NSDate(ICalValue) */
|
||||
|
||||
|
||||
#ifndef ABS
|
||||
#define ABS(a) ((a) < 0 ? -(a) : (a))
|
||||
#endif
|
||||
|
||||
@implementation NSCalendarDate (iCalRecurrenceCalculatorExtensions)
|
||||
|
||||
- (unsigned)yearsBetweenDate:(NSCalendarDate *)_date {
|
||||
return ABS([self yearOfCommonEra] - [_date yearOfCommonEra]);
|
||||
}
|
||||
|
||||
- (unsigned)monthsBetweenDate:(NSCalendarDate *)_date {
|
||||
NSCalendarDate *start, *end;
|
||||
NSComparisonResult order;
|
||||
int yDiff;
|
||||
|
||||
order = [self compare:_date];
|
||||
if (order == NSOrderedSame)
|
||||
return 0;
|
||||
else if (order == NSOrderedAscending) {
|
||||
start = self;
|
||||
end = _date;
|
||||
}
|
||||
else {
|
||||
start = _date;
|
||||
end = self;
|
||||
}
|
||||
yDiff = [end yearOfCommonEra] - [start yearOfCommonEra];
|
||||
if (yDiff > 0) {
|
||||
unsigned monthsRemaining, monthsToGo;
|
||||
|
||||
monthsRemaining = 12 - [start monthOfYear];
|
||||
monthsToGo = [end monthOfYear];
|
||||
yDiff -= 1;
|
||||
return monthsRemaining + monthsToGo + (12 * yDiff);
|
||||
}
|
||||
/* start and end in same year, calculate plain diff */
|
||||
return [end monthOfYear] - [start monthOfYear];
|
||||
}
|
||||
|
||||
- (unsigned)daysBetweenDate:(NSCalendarDate *)_date {
|
||||
return ABS([self julianNumber] - [_date julianNumber]);
|
||||
}
|
||||
@end /* NSCalendarDate (iCalRecurrenceCalculatorExtensions) */
|
|
@ -0,0 +1,38 @@
|
|||
/* NSDate+NGCards.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef NSDATE_NGCARDS_H
|
||||
#define NSDATE_NGCARDS_H
|
||||
|
||||
#import <Foundation/NSDate.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
|
||||
#import "CardElement.h"
|
||||
|
||||
@interface NSDate (NGCardsExtensions)
|
||||
|
||||
- (NSString *) iCalFormattedDateTimeString;
|
||||
- (NSString *) iCalFormattedDateString;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NSDATE_NGCARDS_H */
|
|
@ -0,0 +1,47 @@
|
|||
/* NSDate+NGCards.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "CardElement.h"
|
||||
|
||||
#import "NSCalendarDate+NGCards.h"
|
||||
#import "NSString+NGCards.h"
|
||||
|
||||
@implementation NSCalendarDate (NGCardsExtensions)
|
||||
|
||||
- (NSString *) iCalFormattedDateTimeString
|
||||
{
|
||||
return [NSString stringWithFormat: @"%.4d%.2d%.2dT%.2d%.2d%.2d",
|
||||
[self yearOfCommonEra], [self monthOfYear],
|
||||
[self dayOfMonth], [self hourOfDay],
|
||||
[self minuteOfHour], [self secondOfMinute]];
|
||||
}
|
||||
|
||||
- (NSString *) iCalFormattedDateString
|
||||
{
|
||||
return [NSString stringWithFormat: @"%.4d%.2d%.2d",
|
||||
[self yearOfCommonEra], [self monthOfYear],
|
||||
[self dayOfMonth]];
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,34 @@
|
|||
/* NSDictionary+NGCards.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef NSDICTIONARY_NGCARDS_H
|
||||
#define NSDICTIONARY_NGCARDS_H
|
||||
|
||||
#import <Foundation/NSDictionary.h>
|
||||
|
||||
@interface NSDictionary (NGCardsExtensions)
|
||||
|
||||
- (id) objectForCaseInsensitiveKey: (NSString *) aKey;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NSDICTIONARY_NGCARDS_H */
|
|
@ -0,0 +1,40 @@
|
|||
/* NSDictionary+NGCards.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import "NSArray+NGCards.h"
|
||||
|
||||
#import "NSDictionary+NGCards.h"
|
||||
|
||||
@implementation NSDictionary (NGCardsExtension)
|
||||
|
||||
- (id) objectForCaseInsensitiveKey: (NSString *) aKey
|
||||
{
|
||||
NSString *realKey;
|
||||
NSArray *keys;
|
||||
|
||||
keys = [self allKeys];
|
||||
realKey = [keys valueForCaseInsensitiveString: aKey];
|
||||
|
||||
return ((realKey) ? [self objectForKey: realKey] : nil);
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,45 @@
|
|||
/* NSString+NGCards.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef NSSTRING_NGCARDS_H
|
||||
#define NSSTRING_NGCARDS_H
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
@class NSCalendarDate;
|
||||
@class NSTimeZone;
|
||||
|
||||
@interface NSString (NGCardsExtensions)
|
||||
|
||||
- (NSString *) foldedForVersitCards;
|
||||
- (NSArray *) asCardAttributeValues;
|
||||
- (NSString *) escapedForCards;
|
||||
- (NSString *) unescapedFromCard;
|
||||
|
||||
- (NSTimeInterval) durationAsTimeInterval;
|
||||
- (NSCalendarDate *) asCalendarDate;
|
||||
|
||||
- (NSArray *) commaSeparatedValues;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* NSSTRING_NGCARDS_H */
|
|
@ -0,0 +1,272 @@
|
|||
/* NSString+NGCards.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSRange.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import <ctype.h>
|
||||
|
||||
#import "NSString+NGCards.h"
|
||||
|
||||
static NSString *commaSeparator = nil;
|
||||
|
||||
@implementation NSString (NGCardsExtensions)
|
||||
|
||||
- (void) _initCommaSeparator
|
||||
{
|
||||
commaSeparator = [NSMutableString stringWithFormat: @"%c", 255];
|
||||
[commaSeparator retain];
|
||||
}
|
||||
|
||||
- (NSString *) foldedForVersitCards
|
||||
{
|
||||
NSString *newString;
|
||||
NSMutableString *foldedString;
|
||||
unsigned int length;
|
||||
NSRange subStringRange;
|
||||
|
||||
length = [self length];
|
||||
if (length < 76)
|
||||
newString = self;
|
||||
else
|
||||
{
|
||||
foldedString = [NSMutableString new];
|
||||
[foldedString autorelease];
|
||||
|
||||
subStringRange = NSMakeRange (0, 75);
|
||||
[foldedString appendFormat: @"%@\r\n",
|
||||
[self substringWithRange: subStringRange]];
|
||||
subStringRange = NSMakeRange (75, 74);
|
||||
while ((length - subStringRange.location) > 74)
|
||||
{
|
||||
[foldedString appendFormat: @" %@\r\n",
|
||||
[self substringWithRange: subStringRange]];
|
||||
subStringRange.location += 74;
|
||||
}
|
||||
subStringRange.length = length - subStringRange.location;
|
||||
[foldedString appendFormat: @" %@",
|
||||
[self substringWithRange: subStringRange]];
|
||||
|
||||
newString = foldedString;
|
||||
}
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
- (NSArray *) asCardAttributeValues
|
||||
{
|
||||
NSMutableArray *values;
|
||||
NSEnumerator *rawValues;
|
||||
NSString *tmpString, *rawValue, *newString;
|
||||
|
||||
values = [NSMutableArray new];
|
||||
[values autorelease];
|
||||
|
||||
if (!commaSeparator)
|
||||
[self _initCommaSeparator];
|
||||
|
||||
tmpString = [self stringByReplacingString: @"\\,"
|
||||
withString: commaSeparator];
|
||||
rawValues = [[tmpString componentsSeparatedByString: @","]
|
||||
objectEnumerator];
|
||||
rawValue = [rawValues nextObject];
|
||||
while (rawValue)
|
||||
{
|
||||
newString = [rawValue stringByReplacingString: commaSeparator
|
||||
withString: @","];
|
||||
[values addObject: [newString stringByTrimmingSpaces]];
|
||||
rawValue = [rawValues nextObject];
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
- (NSString *) escapedForCards
|
||||
{
|
||||
NSString *string;
|
||||
|
||||
string = [self stringByReplacingString: @"\\"
|
||||
withString: @"\\\\"];
|
||||
string = [string stringByReplacingString: @","
|
||||
withString: @"\\,"];
|
||||
// string = [string stringByReplacingString: @":"
|
||||
// withString: @"\\:"];
|
||||
string = [string stringByReplacingString: @";"
|
||||
withString: @"\\;"];
|
||||
string = [string stringByReplacingString: @"\n"
|
||||
withString: @"\\n"];
|
||||
string = [string stringByReplacingString: @"\r"
|
||||
withString: @"\\r"];
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
- (NSString *) unescapedFromCard
|
||||
{
|
||||
NSString *string;
|
||||
|
||||
string = [self stringByReplacingString: @"\\,"
|
||||
withString: @","];
|
||||
string = [string stringByReplacingString: @"\\:"
|
||||
withString: @":"];
|
||||
string = [string stringByReplacingString: @"\\;"
|
||||
withString: @";"];
|
||||
string = [string stringByReplacingString: @"\\n"
|
||||
withString: @"\n"];
|
||||
string = [string stringByReplacingString: @"\\r"
|
||||
withString: @"\r"];
|
||||
string = [string stringByReplacingString: @"\\\\"
|
||||
withString: @"\\"];
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
- (NSTimeInterval) durationAsTimeInterval
|
||||
{
|
||||
/*
|
||||
eg: DURATION:PT1H
|
||||
P - "period"
|
||||
P2H30M - "2 hours 30 minutes"
|
||||
|
||||
dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
|
||||
|
||||
dur-date = dur-day [dur-time]
|
||||
dur-time = "T" (dur-hour / dur-minute / dur-second)
|
||||
dur-week = 1*DIGIT "W"
|
||||
dur-hour = 1*DIGIT "H" [dur-minute]
|
||||
dur-minute = 1*DIGIT "M" [dur-second]
|
||||
dur-second = 1*DIGIT "S"
|
||||
dur-day = 1*DIGIT "D"
|
||||
*/
|
||||
unsigned i, len;
|
||||
NSTimeInterval ti;
|
||||
BOOL isTime;
|
||||
int val;
|
||||
|
||||
if (![self hasPrefix:@"P"]) {
|
||||
NSLog(@"Cannot parse iCal duration value: '%@'", self);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
ti = 0.0;
|
||||
val = 0;
|
||||
for (i = 1, len = [self length], isTime = NO; i < len; i++) {
|
||||
unichar c;
|
||||
|
||||
c = [self characterAtIndex:i];
|
||||
if (c == 't' || c == 'T') {
|
||||
isTime = YES;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isdigit(c)) {
|
||||
val = (val * 10) + (c - 48);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'W': /* week */
|
||||
ti += (val * 7 * 24 * 60 * 60);
|
||||
break;
|
||||
case 'D': /* day */
|
||||
ti += (val * 24 * 60 * 60);
|
||||
break;
|
||||
case 'H': /* hour */
|
||||
ti += (val * 60 * 60);
|
||||
break;
|
||||
case 'M': /* min */
|
||||
ti += (val * 60);
|
||||
break;
|
||||
case 'S': /* sec */
|
||||
ti += val;
|
||||
break;
|
||||
default:
|
||||
[self logWithFormat: @"cannot process duration unit: '%c'", c];
|
||||
break;
|
||||
}
|
||||
val = 0;
|
||||
}
|
||||
return ti;
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) asCalendarDate
|
||||
{
|
||||
NSRange cursor;
|
||||
NSCalendarDate *date;
|
||||
NSTimeZone *utc;
|
||||
int year, month, day, hour, minute, second;
|
||||
|
||||
if ([self length] > 14)
|
||||
{
|
||||
cursor = NSMakeRange(0, 4);
|
||||
year = [[self substringWithRange: cursor] intValue];
|
||||
cursor.location += cursor.length;
|
||||
cursor.length = 2;
|
||||
month = [[self substringWithRange: cursor] intValue];
|
||||
cursor.location += cursor.length;
|
||||
day = [[self substringWithRange: cursor] intValue];
|
||||
|
||||
cursor.location += cursor.length + 1;
|
||||
hour = [[self substringWithRange: cursor] intValue];
|
||||
cursor.location += cursor.length;
|
||||
minute = [[self substringWithRange: cursor] intValue];
|
||||
cursor.location += cursor.length;
|
||||
second = [[self substringWithRange: cursor] intValue];
|
||||
|
||||
utc = [NSTimeZone timeZoneWithAbbreviation: @"GMT"];
|
||||
date = [NSCalendarDate dateWithYear: year month: month
|
||||
day: day hour: hour minute: minute
|
||||
second: second
|
||||
timeZone: utc];
|
||||
}
|
||||
else
|
||||
date = nil;
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
- (NSArray *) commaSeparatedValues
|
||||
{
|
||||
NSEnumerator *rawValues;
|
||||
NSMutableArray *values;
|
||||
NSString *currentValue, *newValue;
|
||||
|
||||
values = [NSMutableArray new];
|
||||
[values autorelease];
|
||||
|
||||
rawValues = [[self componentsSeparatedByString: @","] objectEnumerator];
|
||||
currentValue = [rawValues nextObject];
|
||||
while (currentValue)
|
||||
{
|
||||
newValue = [currentValue stringByTrimmingSpaces];
|
||||
if ([newValue length])
|
||||
[values addObject: newValue];
|
||||
currentValue = [rawValues nextObject];
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,19 @@
|
|||
TODO: improve text
|
||||
|
||||
Objective-C classes for representing iCalendar entities as objects. To
|
||||
actually parse iCalendar entities the sope-xml versitSaxDriver is used.
|
||||
Note that this library doesn't make any use of the now deprecated libical but
|
||||
rather relies on the SAX interface (SaxObjectDecoder is used).
|
||||
|
||||
Recurrences
|
||||
===========
|
||||
|
||||
Recurrences are modeled via iCalRecurrenceRules and an iCalRecurrenceCalculator
|
||||
which contains all the necessary logic according to RFC2445 to interpret
|
||||
iCalRecurrenceRules. The calculator needs a referrence date for the first
|
||||
instance of a recurrence which is usually provided by any of the repeatable
|
||||
entity objects (i.e. iCalEvent).
|
||||
|
||||
Please note that recurrences are work in progress and far from being
|
||||
complete/compliant with RFC2445. So far only the most simple cases are done
|
||||
properly.
|
|
@ -0,0 +1,8 @@
|
|||
# version file
|
||||
|
||||
MAJOR_VERSION=4
|
||||
MINOR_VERSION=5
|
||||
SUBMINOR_VERSION:=76
|
||||
|
||||
# v4.5.40 requires NGExtensions v4.5.145
|
||||
# v4.5.37 requires NGExtensions v4.5.140
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ICal_common_H__
|
||||
#define __ICal_common_H__
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <EOControl/EOControl.h>
|
||||
#include <NGExtensions/NGExtensions.h>
|
||||
|
||||
#define IS_EQUAL(a, b, sel) \
|
||||
_iCalSafeCompareObjects(a, b, @selector(sel))
|
||||
|
||||
static __inline__ BOOL _iCalSafeCompareObjects(id a, id b, SEL comparator) {
|
||||
id va = a;
|
||||
id vb = b;
|
||||
BOOL (*compm)(id, SEL, id);
|
||||
|
||||
if((va == nil && vb != nil) || (va != nil && vb == nil))
|
||||
return NO;
|
||||
else if(va == vb)
|
||||
return YES;
|
||||
compm = (BOOL (*)( id, SEL, id))[va methodForSelector:comparator];
|
||||
return compm(va, comparator, vb);
|
||||
}
|
||||
|
||||
#endif /* __ICal_common_H__ */
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalAlarm_H__
|
||||
#define __NGCards_iCalAlarm_H__
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
@class NSString;
|
||||
@class iCalTrigger;
|
||||
@class iCalAttachment;
|
||||
|
||||
@interface iCalAlarm : CardGroup
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (iCalTrigger *) trigger;
|
||||
- (iCalAttachment *) attach;
|
||||
- (NSString *) comment;
|
||||
- (NSString *) action;
|
||||
- (void) setRecurrenceRule: (NSString *) _recurrenceRule;
|
||||
- (NSString *) recurrenceRule;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalAlarm_H__ */
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import "iCalAttachment.h"
|
||||
#import "iCalRecurrenceRule.h"
|
||||
#import "iCalTrigger.h"
|
||||
|
||||
#import "iCalAlarm.h"
|
||||
#import "common.h"
|
||||
|
||||
@implementation iCalAlarm
|
||||
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
if ([classTag isEqualToString: @"TRIGGER"])
|
||||
tagClass = [iCalTrigger class];
|
||||
else if ([classTag isEqualToString: @"ATTACH"])
|
||||
tagClass = [iCalAttachment class];
|
||||
else if ([classTag isEqualToString: @"RRULE"])
|
||||
tagClass = [iCalRecurrenceRule class];
|
||||
else if ([classTag isEqualToString: @"ACTION"]
|
||||
|| [classTag isEqualToString: @"COMMENT"])
|
||||
tagClass = [CardElement class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setTrigger: (iCalTrigger *) _value
|
||||
{
|
||||
[self setUniqueChild: _value];
|
||||
}
|
||||
|
||||
- (iCalTrigger *) trigger
|
||||
{
|
||||
return (iCalTrigger *) [self uniqueChildWithTag: @"trigger"];
|
||||
}
|
||||
|
||||
- (void) setAttach: (iCalAttachment *) _value
|
||||
{
|
||||
[self setUniqueChild: _value];
|
||||
}
|
||||
|
||||
- (iCalAttachment *) attach
|
||||
{
|
||||
return (iCalAttachment *) [self uniqueChildWithTag: @"attach"];
|
||||
}
|
||||
|
||||
- (void) setComment: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"comment"] setValue: 0
|
||||
to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) comment
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"comment"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setAction: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"action"] setValue: 0
|
||||
to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) action
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"action"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setRecurrenceRule: (NSString *) _recurrenceRule
|
||||
{
|
||||
[[self uniqueChildWithTag: @"rrule"] setValue: 0
|
||||
to: _recurrenceRule];
|
||||
}
|
||||
|
||||
- (NSString *) recurrenceRule
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"rrule"] value: 0];
|
||||
}
|
||||
|
||||
@end /* iCalAlarm */
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGiCal_iCalAttachment_H__
|
||||
#define __NGiCal_iCalAttachment_H__
|
||||
|
||||
#import "CardElement.h"
|
||||
|
||||
@class NSString;
|
||||
|
||||
@interface iCalAttachment : CardElement
|
||||
|
||||
- (void) setValue: (NSString *) aValue;
|
||||
- (NSString *) value;
|
||||
|
||||
- (void) setValueType: (NSString *) aType;
|
||||
- (NSString *) valueType;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_iCalAttachment_H__ */
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import "iCalAttachment.h"
|
||||
#import "common.h"
|
||||
|
||||
@implementation iCalAttachment
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setValue: (NSString *) _value
|
||||
{
|
||||
[self setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) value
|
||||
{
|
||||
return [self value: 0];
|
||||
}
|
||||
|
||||
- (void) setValueType: (NSString *) _value
|
||||
{
|
||||
[self setValue: 0 ofAttribute: @"type" to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) valueType
|
||||
{
|
||||
return [self value: 0 ofAttribute: @"type"];
|
||||
}
|
||||
|
||||
@end /* iCalAttachment */
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalCalendar_H__
|
||||
#define __NGCards_iCalCalendar_H__
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
@class NSString;
|
||||
@class NSMutableArray;
|
||||
@class NSArray;
|
||||
@class NSEnumerator;
|
||||
@class NSMutableDictionary;
|
||||
|
||||
@class iCalEvent;
|
||||
@class iCalToDo;
|
||||
@class iCalJournal;
|
||||
@class iCalFreeBusy;
|
||||
@class iCalEntityObject;
|
||||
@class iCalTimeZone;
|
||||
|
||||
@interface iCalCalendar : CardGroup
|
||||
// {
|
||||
// NSString *version;
|
||||
// NSString *calscale;
|
||||
// NSString *prodId;
|
||||
// NSString *method;
|
||||
|
||||
// NSMutableArray *todos;
|
||||
// NSMutableArray *events;
|
||||
// NSMutableArray *journals;
|
||||
// NSMutableArray *freeBusys;
|
||||
// NSMutableDictionary *timezones;
|
||||
// }
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setMethod: (NSString *)_method;
|
||||
- (NSString *) method;
|
||||
|
||||
- (void) setCalscale: (NSString *) _calscale;
|
||||
- (NSString *) calscale;
|
||||
|
||||
- (void) setVersion: (NSString *) _version;
|
||||
- (NSString *) version;
|
||||
|
||||
- (void) setProdID: (NSString *) _prodid;
|
||||
- (NSString *) prodId;
|
||||
|
||||
- (void) setMethod: (NSString *) _method;
|
||||
- (NSString *) method;
|
||||
|
||||
- (NSArray *) events;
|
||||
- (NSArray *) todos;
|
||||
- (NSArray *) journals;
|
||||
- (NSArray *) freeBusys;
|
||||
|
||||
- (void) addTimeZone: (iCalTimeZone *) iTZ;
|
||||
- (iCalTimeZone *) timeZoneWithId: (NSString *) tzId;
|
||||
|
||||
/* collection */
|
||||
|
||||
- (NSArray *) allObjects;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalCalendar_H__ */
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "iCalEvent.h"
|
||||
#import "iCalToDo.h"
|
||||
#import "iCalJournal.h"
|
||||
#import "iCalFreeBusy.h"
|
||||
#import "iCalEntityObject.h"
|
||||
#import "iCalTimeZone.h"
|
||||
|
||||
#import "iCalCalendar.h"
|
||||
|
||||
@interface iCalCalendar (Privates)
|
||||
- (void) addToEvents: (iCalEvent *) _event;
|
||||
- (void) addToTimezones: (iCalTimeZone *) _tz;
|
||||
- (void) addToTodos: (iCalToDo *) _todo;
|
||||
- (void) addToJournals: (iCalJournal *) _obj;
|
||||
- (void) addToFreeBusys: (iCalFreeBusy *) _obj;
|
||||
@end
|
||||
|
||||
@implementation iCalCalendar
|
||||
|
||||
/* class mapping */
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
tagClass = Nil;
|
||||
if ([classTag isEqualToString: @"VEVENT"])
|
||||
tagClass = [iCalEvent class];
|
||||
else if ([classTag isEqualToString: @"VTODO"])
|
||||
tagClass = [iCalToDo class];
|
||||
else if ([classTag isEqualToString: @"VJOURNAL"])
|
||||
tagClass = [iCalJournal class];
|
||||
else if ([classTag isEqualToString: @"VFREEBUSY"])
|
||||
tagClass = [iCalFreeBusy class];
|
||||
else if ([classTag isEqualToString: @"VTIMEZONE"])
|
||||
tagClass = [iCalTimeZone class];
|
||||
else if ([classTag isEqualToString: @"METHOD"]
|
||||
|| [classTag isEqualToString: @"PRODID"]
|
||||
|| [classTag isEqualToString: @"VERSION"])
|
||||
tagClass = [CardElement class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setCalscale: (NSString *) _calscale
|
||||
{
|
||||
[[self uniqueChildWithTag: @"calscale"] setValue: 0 to: _calscale];
|
||||
}
|
||||
|
||||
- (NSString *) calscale
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"calscale"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setVersion: (NSString *) _version
|
||||
{
|
||||
[[self uniqueChildWithTag: @"version"] setValue: 0 to: _version];
|
||||
}
|
||||
|
||||
- (NSString *) version
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"version"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setProdID: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"prodid"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) prodId
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"prodid"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setMethod: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"method"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) method
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"method"] value: 0];
|
||||
}
|
||||
|
||||
- (void) addToEvents: (iCalEvent *) _event
|
||||
{
|
||||
[self addChild: _event];
|
||||
}
|
||||
|
||||
- (NSArray *) events
|
||||
{
|
||||
return [self childrenWithTag: @"vevent"];
|
||||
}
|
||||
|
||||
- (void) addToTimezones: (iCalTimeZone *) _tz
|
||||
{
|
||||
[self addChild: _tz];
|
||||
}
|
||||
|
||||
- (NSArray *) timezones
|
||||
{
|
||||
return [self childrenWithTag: @"vtimezone"];
|
||||
}
|
||||
|
||||
- (void) addToTodos: (iCalToDo *) _todo
|
||||
{
|
||||
[self addChild: _todo];
|
||||
}
|
||||
|
||||
- (NSArray *) todos
|
||||
{
|
||||
return [self childrenWithTag: @"vtodo"];
|
||||
}
|
||||
|
||||
- (void) addToJournals: (iCalJournal *) _todo
|
||||
{
|
||||
[self addChild: _todo];
|
||||
}
|
||||
|
||||
- (NSArray *) journals
|
||||
{
|
||||
return [self childrenWithTag: @"vjournal"];
|
||||
}
|
||||
|
||||
- (void) addToFreeBusys: (iCalFreeBusy *) _fb
|
||||
{
|
||||
[self addChild: _fb];
|
||||
}
|
||||
|
||||
- (NSArray *) freeBusys
|
||||
{
|
||||
return [self childrenWithTag: @"vfreebusy"];
|
||||
}
|
||||
|
||||
- (void) addTimeZone: (iCalTimeZone *) iTZ
|
||||
{
|
||||
iCalTimeZone *possibleTz;
|
||||
|
||||
possibleTz = [self timeZoneWithId: [iTZ tzId]];
|
||||
if (!possibleTz)
|
||||
[self addChild: iTZ];
|
||||
}
|
||||
|
||||
- (iCalTimeZone *) timeZoneWithId: (NSString *) tzId
|
||||
{
|
||||
NSArray *matchingTimeZones;
|
||||
iCalTimeZone *timeZone;
|
||||
|
||||
matchingTimeZones = [self childrenGroupWithTag: @"vtimezone"
|
||||
withChild: @"tzid"
|
||||
havingSimpleValue: tzId];
|
||||
if ([matchingTimeZones count])
|
||||
timeZone = [matchingTimeZones objectAtIndex: 0];
|
||||
else
|
||||
timeZone = nil;
|
||||
|
||||
return timeZone;
|
||||
}
|
||||
|
||||
/* collection */
|
||||
|
||||
- (NSArray *) allObjects
|
||||
{
|
||||
NSMutableArray *ma;
|
||||
|
||||
ma = [NSMutableArray new];
|
||||
[ma addObjectsFromArray: [self events]];
|
||||
[ma addObjectsFromArray: [self todos]];
|
||||
[ma addObjectsFromArray: [self journals]];
|
||||
[ma addObjectsFromArray: [self freeBusys]];
|
||||
|
||||
return ma;
|
||||
}
|
||||
|
||||
/* ical typing */
|
||||
|
||||
- (NSString *) entityName
|
||||
{
|
||||
return @"vcalendar";
|
||||
}
|
||||
|
||||
@end /* iCalCalendar */
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalRecurrenceCalculator.h"
|
||||
|
||||
@interface iCalDailyRecurrenceCalculator : iCalRecurrenceCalculator
|
||||
@end
|
||||
|
||||
#include <NGExtensions/NGCalendarDateRange.h>
|
||||
#include "iCalRecurrenceRule.h"
|
||||
#include "NSCalendarDate+ICal.h"
|
||||
#include "common.h"
|
||||
|
||||
@interface iCalRecurrenceCalculator(PrivateAPI)
|
||||
- (NSCalendarDate *)lastInstanceStartDate;
|
||||
@end
|
||||
|
||||
@implementation iCalDailyRecurrenceCalculator
|
||||
|
||||
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r{
|
||||
NSMutableArray *ranges;
|
||||
NSCalendarDate *firStart;
|
||||
long i, jnFirst, jnStart, jnEnd, startEndCount;
|
||||
unsigned interval;
|
||||
|
||||
firStart = [self->firstRange startDate];
|
||||
jnFirst = [firStart julianNumber];
|
||||
jnEnd = [[_r endDate] julianNumber];
|
||||
|
||||
if (jnFirst > jnEnd)
|
||||
return nil;
|
||||
|
||||
jnStart = [[_r startDate] julianNumber];
|
||||
interval = [self->rrule repeatInterval];
|
||||
|
||||
/* if rule is bound, check the bounds */
|
||||
if (![self->rrule isInfinite]) {
|
||||
NSCalendarDate *until;
|
||||
long jnRuleLast;
|
||||
|
||||
until = [self->rrule untilDate];
|
||||
if (until) {
|
||||
if ([until compare:[_r startDate]] == NSOrderedAscending)
|
||||
return nil;
|
||||
jnRuleLast = [until julianNumber];
|
||||
}
|
||||
else {
|
||||
jnRuleLast = (interval * [self->rrule repeatCount])
|
||||
+ jnFirst;
|
||||
if (jnRuleLast < jnStart)
|
||||
return nil;
|
||||
}
|
||||
/* jnStart < jnRuleLast < jnEnd ? */
|
||||
if (jnEnd > jnRuleLast)
|
||||
jnEnd = jnRuleLast;
|
||||
}
|
||||
|
||||
startEndCount = (jnEnd - jnStart) + 1;
|
||||
ranges = [NSMutableArray arrayWithCapacity:startEndCount];
|
||||
for (i = 0 ; i < startEndCount; i++) {
|
||||
long jnCurrent;
|
||||
|
||||
jnCurrent = jnStart + i;
|
||||
if (jnCurrent >= jnFirst) {
|
||||
long jnTest;
|
||||
|
||||
jnTest = jnCurrent - jnFirst;
|
||||
if ((jnTest % interval) == 0) {
|
||||
NSCalendarDate *start, *end;
|
||||
NGCalendarDateRange *r;
|
||||
|
||||
start = [NSCalendarDate dateForJulianNumber:jnCurrent];
|
||||
[start setTimeZone:[firStart timeZone]];
|
||||
start = [start hour: [firStart hourOfDay]
|
||||
minute:[firStart minuteOfHour]
|
||||
second:[firStart secondOfMinute]];
|
||||
end = [start addTimeInterval:[self->firstRange duration]];
|
||||
r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
|
||||
endDate:end];
|
||||
if ([_r containsDateRange:r])
|
||||
[ranges addObject:r];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
- (NSCalendarDate *)lastInstanceStartDate {
|
||||
if ([self->rrule repeatCount] > 0) {
|
||||
long jnFirst, jnRuleLast;
|
||||
NSCalendarDate *firStart, *until;
|
||||
|
||||
firStart = [self->firstRange startDate];
|
||||
jnFirst = [firStart julianNumber];
|
||||
jnRuleLast = ([self->rrule repeatInterval] *
|
||||
[self->rrule repeatCount]) +
|
||||
jnFirst;
|
||||
until = [NSCalendarDate dateForJulianNumber:jnRuleLast];
|
||||
until = [until hour: [firStart hourOfDay]
|
||||
minute:[firStart minuteOfHour]
|
||||
second:[firStart secondOfMinute]];
|
||||
return until;
|
||||
}
|
||||
return [super lastInstanceStartDate];
|
||||
}
|
||||
|
||||
@end /* iCalDailyRecurrenceCalculator */
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGiCal_iCalDataSource_H__
|
||||
#define __NGiCal_iCalDataSource_H__
|
||||
|
||||
#import <EOControl/EODataSource.h>
|
||||
|
||||
@class NSString, NSURL;
|
||||
@class EOFetchSpecification;
|
||||
|
||||
@interface iCalDataSource : EODataSource
|
||||
{
|
||||
EOFetchSpecification *fetchSpecification;
|
||||
NSURL *url;
|
||||
NSString *entityName;
|
||||
}
|
||||
|
||||
- (id)initWithURL:(NSURL *)_url entityName:(NSString *)_ename;
|
||||
- (id)initWithPath:(NSString *)_file entityName:(NSString *)_ename;
|
||||
- (id)initWithURL:(NSURL *)_url;
|
||||
- (id)initWithPath:(NSString *)_file;
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void)setFetchSpecification:(EOFetchSpecification *)_fspec;
|
||||
- (EOFetchSpecification *)fetchSpecification;
|
||||
|
||||
/* fetching */
|
||||
|
||||
- (NSArray *)fetchObjects;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_iCalDataSource_H__ */
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalDataSource.h"
|
||||
#include "iCalObject.h"
|
||||
#include "iCalCalendar.h"
|
||||
#include <SaxObjC/SaxObjC.h>
|
||||
#include "common.h"
|
||||
|
||||
@interface NSObject(suppressCapitalizedKeyWarning)
|
||||
+ (void)suppressCapitalizedKeyWarning;
|
||||
@end
|
||||
|
||||
@implementation iCalDataSource
|
||||
|
||||
// THREAD
|
||||
static id<NSObject,SaxXMLReader> parser = nil;
|
||||
static SaxObjectDecoder *sax = nil;
|
||||
|
||||
- (void)_setupGlobals {
|
||||
if (parser == nil ) {
|
||||
SaxXMLReaderFactory *factory =
|
||||
[SaxXMLReaderFactory standardXMLReaderFactory];
|
||||
parser = [[factory createXMLReaderForMimeType:@"text/calendar"] retain];
|
||||
if (parser == nil)
|
||||
[self logWithFormat:@"ERROR: found no SAX driver for 'text/calendar'!"];
|
||||
}
|
||||
if (sax == nil && parser != nil) {
|
||||
NSBundle *bundle;
|
||||
NSString *p;
|
||||
|
||||
#if COCOA_Foundation_LIBRARY
|
||||
/* otherwise we get warning on "X-WR-TIMEZONE" etc */
|
||||
[NSClassFromString(@"NSKeyBinding") suppressCapitalizedKeyWarning];
|
||||
#endif
|
||||
|
||||
bundle = [NSBundle bundleForClass:[self class]];
|
||||
if ((p = [bundle pathForResource:@"NGiCal" ofType:@"xmap"]))
|
||||
sax = [[SaxObjectDecoder alloc] initWithMappingAtPath:p];
|
||||
else
|
||||
sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGiCal"];
|
||||
|
||||
[parser setContentHandler:sax];
|
||||
[parser setErrorHandler:sax];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (id)initWithURL:(NSURL *)_url entityName:(NSString *)_ename {
|
||||
[self _setupGlobals];
|
||||
if ((self = [super init])) {
|
||||
self->url = [_url copy];
|
||||
self->entityName = [_ename copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (id)initWithPath:(NSString *)_path entityName:(NSString *)_ename {
|
||||
NSURL *lurl;
|
||||
|
||||
lurl = [[[NSURL alloc] initFileURLWithPath:_path] autorelease];
|
||||
return [self initWithURL:lurl entityName:_ename];
|
||||
}
|
||||
|
||||
- (id)initWithURL:(NSURL *)_url {
|
||||
return [self initWithURL:_url entityName:nil];
|
||||
}
|
||||
- (id)initWithPath:(NSString *)_path {
|
||||
return [self initWithPath:_path entityName:nil];
|
||||
}
|
||||
- (id)init {
|
||||
return [self initWithURL:nil];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self->fetchSpecification release];
|
||||
[self->url release];
|
||||
[self->entityName release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void)setFetchSpecification:(EOFetchSpecification *)_fspec {
|
||||
if ([self->fetchSpecification isEqual:_fspec])
|
||||
return;
|
||||
|
||||
ASSIGNCOPY(self->fetchSpecification, _fspec);
|
||||
|
||||
[self postDataSourceChangedNotification];
|
||||
}
|
||||
- (EOFetchSpecification *)fetchSpecification {
|
||||
return self->fetchSpecification;
|
||||
}
|
||||
|
||||
/* fetching */
|
||||
|
||||
- (id)_parseCalendar {
|
||||
id cal;
|
||||
|
||||
if (parser == nil) {
|
||||
[self logWithFormat:@"ERROR: missing iCalendar parser!"];
|
||||
return nil;
|
||||
}
|
||||
if (sax == nil) {
|
||||
[self logWithFormat:@"ERROR: missing SAX handler!"];
|
||||
return nil;
|
||||
}
|
||||
|
||||
[parser parseFromSource:self->url];
|
||||
cal = [sax rootObject];
|
||||
|
||||
return cal;
|
||||
}
|
||||
|
||||
- (NSArray *)objectsForEntityNamed:(NSString *)ename inCalendar:(id)_cal {
|
||||
if ([ename isEqualToString:@"vevent"])
|
||||
return [_cal events];
|
||||
if ([ename isEqualToString:@"vtodo"])
|
||||
return [_cal todos];
|
||||
if ([ename isEqualToString:@"vjournal"])
|
||||
return [_cal journals];
|
||||
if ([ename isEqualToString:@"vfreebusy"])
|
||||
return [_cal freeBusys];
|
||||
|
||||
[self logWithFormat:@"unknown calendar entity '%@'", ename];
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray *)objectsFromCalendar:(id)_cal {
|
||||
NSString *ename;
|
||||
|
||||
ename = [self->fetchSpecification entityName];
|
||||
if ([ename length] == 0)
|
||||
ename = self->entityName;
|
||||
|
||||
if ([ename length] == 0)
|
||||
return [_cal allObjects];
|
||||
|
||||
if ([_cal isKindOfClass:[NSDictionary class]]) {
|
||||
/*
|
||||
This happens with Mozilla Calendar which posts one vcalendar
|
||||
entry (with method 'PUBLISH') per event.
|
||||
*/
|
||||
NSMutableArray *ma;
|
||||
NSArray *calendars;
|
||||
unsigned i, count;
|
||||
|
||||
if (![[(NSDictionary *)_cal objectForKey:@"tag"]
|
||||
isEqualToString:@"iCalendar"]) {
|
||||
[self logWithFormat:
|
||||
@"ERROR: calendar (entity=%@) passed in as a dictionary: %@",
|
||||
_cal];
|
||||
}
|
||||
|
||||
if ((calendars=[(NSDictionary *)_cal objectForKey:@"subcomponents"])==nil)
|
||||
return nil;
|
||||
|
||||
count = [calendars count];
|
||||
ma = [NSMutableArray arrayWithCapacity:(count + 1)];
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
NSArray *objects;
|
||||
|
||||
objects = [self objectsForEntityNamed:ename
|
||||
inCalendar:[calendars objectAtIndex:i]];
|
||||
if ([objects count] == 0)
|
||||
continue;
|
||||
|
||||
[ma addObjectsFromArray:objects];
|
||||
}
|
||||
return ma;
|
||||
}
|
||||
|
||||
return [self objectsForEntityNamed:ename inCalendar:_cal];
|
||||
}
|
||||
|
||||
- (NSArray *)fetchObjects {
|
||||
NSAutoreleasePool *pool;
|
||||
NSArray *result;
|
||||
id calendar;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if ((calendar = [self _parseCalendar]) == nil)
|
||||
return nil;
|
||||
|
||||
if (self->fetchSpecification == nil) {
|
||||
result = [[self objectsFromCalendar:calendar] shallowCopy];
|
||||
}
|
||||
else {
|
||||
NSMutableArray *ma;
|
||||
NSEnumerator *e;
|
||||
EOQualifier *q;
|
||||
NSArray *sort;
|
||||
NSArray *objects;
|
||||
iCalObject *object;
|
||||
|
||||
/* get objects */
|
||||
|
||||
objects = [self objectsFromCalendar:calendar];
|
||||
|
||||
/* first filter using qualifier */
|
||||
|
||||
ma = [NSMutableArray arrayWithCapacity:[objects count]];
|
||||
q = [self->fetchSpecification qualifier];
|
||||
e = [objects objectEnumerator];
|
||||
while ((object = [e nextObject])) {
|
||||
if (q) {
|
||||
if (![(id<EOQualifierEvaluation>)q evaluateWithObject:object])
|
||||
continue;
|
||||
}
|
||||
|
||||
[ma addObject:object];
|
||||
}
|
||||
|
||||
/* now sort */
|
||||
|
||||
if ((sort = [self->fetchSpecification sortOrderings]))
|
||||
[ma sortUsingKeyOrderArray:sort];
|
||||
|
||||
result = [ma shallowCopy];
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return [result autorelease];
|
||||
}
|
||||
|
||||
@end /* iCalDataSource */
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGiCal_iCalDateHolder_H__
|
||||
#define __NGiCal_iCalDateHolder_H__
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
@class NSString, NSTimeZone;
|
||||
|
||||
@interface iCalDateHolder : NSObject
|
||||
{
|
||||
NSString *tzid;
|
||||
NSString *string;
|
||||
NSString *tag;
|
||||
}
|
||||
|
||||
- (void)setString:(NSString *)_value;
|
||||
- (NSString *)string;
|
||||
|
||||
- (void)setTag:(NSString *)_value;
|
||||
- (NSString *)tag;
|
||||
|
||||
- (void)setTzid:(NSString *)_value;
|
||||
- (NSString *)tzid;
|
||||
|
||||
- (NSTimeZone *)timeZone;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_iCalDateHolder_H__ */
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalDateHolder.h"
|
||||
#include "iCalObject.h"
|
||||
#include "common.h"
|
||||
|
||||
@interface NSTimeZone(iCalTimeZone)
|
||||
|
||||
+ (NSTimeZone *)timeZoneWithICalId:(NSString *)_tz;
|
||||
|
||||
@end
|
||||
|
||||
@implementation iCalDateHolder
|
||||
|
||||
static NSTimeZone *gmt = nil;
|
||||
|
||||
+ (void)initialize {
|
||||
if (gmt == nil)
|
||||
gmt = [[NSTimeZone timeZoneWithName:@"GMT"] retain];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self->tzid release];
|
||||
[self->string release];
|
||||
[self->tag release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void)setString:(NSString *)_value {
|
||||
ASSIGNCOPY(self->string, _value);
|
||||
}
|
||||
- (NSString *)string {
|
||||
return self->string;
|
||||
}
|
||||
|
||||
- (void)setTag:(NSString *)_value {
|
||||
ASSIGNCOPY(self->tag, _value);
|
||||
}
|
||||
- (NSString *)tag {
|
||||
return self->tag;
|
||||
}
|
||||
|
||||
- (void)setTzid:(NSString *)_value {
|
||||
ASSIGNCOPY(self->tzid, _value);
|
||||
}
|
||||
- (NSString *)tzid {
|
||||
return self->tzid;
|
||||
}
|
||||
|
||||
/* mapping to Foundation */
|
||||
|
||||
- (NSTimeZone *)timeZone {
|
||||
// TODO: lookup tzid in iCalCalendar !
|
||||
NSString *s;
|
||||
|
||||
s = [self tzid];
|
||||
|
||||
/* a hack */
|
||||
if ([s hasPrefix:@"/softwarestudio.org"]) {
|
||||
NSRange r;
|
||||
|
||||
r = [s rangeOfString:@"Europe/"];
|
||||
if (r.length > 0)
|
||||
s = [s substringFromIndex:r.location];
|
||||
}
|
||||
return [NSTimeZone timeZoneWithICalId:s];
|
||||
}
|
||||
|
||||
/* decoding */
|
||||
|
||||
- (id)awakeAfterUsingSaxDecoder:(id)_decoder {
|
||||
NSCalendarDate *date = nil;
|
||||
NSString *s;
|
||||
NSTimeZone *tz;
|
||||
|
||||
s = self->string;
|
||||
if ([s length] < 5) {
|
||||
[self logWithFormat:@"tag %@: got an weird date string '%@' ?!",
|
||||
self->tag, s];
|
||||
return s;
|
||||
}
|
||||
|
||||
/* calculate timezone */
|
||||
|
||||
if ([self->string hasSuffix:@"Z"]) {
|
||||
/* zulu time, eg 20021009T094500Z */
|
||||
tz = gmt;
|
||||
s = [s substringToIndex:([s length] - 1)];
|
||||
}
|
||||
else
|
||||
tz = [self timeZone];
|
||||
|
||||
/*
|
||||
012345678901234
|
||||
20021009T094500 - 15 chars
|
||||
20021009T0945 - 13 chars
|
||||
991009T0945 - 11 chars
|
||||
|
||||
20031111 - 8 chars
|
||||
*/
|
||||
if ([s rangeOfString:@"T"].length == 0 && [s length] == 8) {
|
||||
/* hm, maybe a date without a time? like an allday event! */
|
||||
int year, month, day;
|
||||
char buf[16];
|
||||
[s getCString:&(buf[0])];
|
||||
|
||||
buf[9] = '\0';
|
||||
day = atoi(&(buf[6])); buf[6] = '\0';
|
||||
month = atoi(&(buf[4])); buf[4] = '\0';
|
||||
year = atoi(&(buf[0]));
|
||||
|
||||
date = [NSCalendarDate dateWithYear:year month:month day:day
|
||||
hour:0 minute:0 second:0
|
||||
timeZone:tz];
|
||||
}
|
||||
else if ([s length] == 15) {
|
||||
int year, month, day, hour, minute, second;
|
||||
char buf[24];
|
||||
[s getCString:&(buf[0])];
|
||||
|
||||
second = atoi(&(buf[13])); buf[13] = '\0';
|
||||
minute = atoi(&(buf[11])); buf[11] = '\0';
|
||||
hour = atoi(&(buf[9])); buf[9] = '\0';
|
||||
day = atoi(&(buf[6])); buf[6] = '\0';
|
||||
month = atoi(&(buf[4])); buf[4] = '\0';
|
||||
year = atoi(&(buf[0]));
|
||||
|
||||
date = [NSCalendarDate dateWithYear:year month:month day:day
|
||||
hour:hour minute:minute second:second
|
||||
timeZone:tz];
|
||||
}
|
||||
else
|
||||
NSLog(@"%s: unknown date format (%@) ???", __PRETTY_FUNCTION__, s);
|
||||
|
||||
if (date == nil)
|
||||
NSLog(@"couldn't convert string '%@' to date (format '%@') ..", s);
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
/* description */
|
||||
|
||||
- (void)appendAttributesToDescription:(NSMutableString *)ms {
|
||||
if (self->tag) [ms appendFormat:@" %@", self->tag];
|
||||
if (self->string) [ms appendFormat:@" '%@'", self->string];
|
||||
if (self->tzid) [ms appendFormat:@" tz=%@", self->tzid];
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
NSMutableString *ms;
|
||||
|
||||
ms = [NSMutableString stringWithCapacity:128];
|
||||
[ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
|
||||
[self appendAttributesToDescription:ms];
|
||||
[ms appendString:@">"];
|
||||
return ms;
|
||||
}
|
||||
|
||||
@end /* iCalDateHolder */
|
||||
|
||||
@implementation NSTimeZone(iCalTimeZone)
|
||||
|
||||
static NSMutableDictionary *idToTz = nil; // THREAD
|
||||
|
||||
+ (NSTimeZone *)timeZoneWithICalId:(NSString *)_tzid {
|
||||
static NSString *iCalDefaultTZ = nil;
|
||||
NSTimeZone *tz;
|
||||
|
||||
if (idToTz == nil)
|
||||
idToTz = [[NSMutableDictionary alloc] initWithCapacity:16];
|
||||
|
||||
if ([_tzid length] == 0) {
|
||||
|
||||
tz = [iCalObject iCalDefaultTimeZone];
|
||||
if (tz != nil) return tz;
|
||||
|
||||
if (iCalDefaultTZ == nil) {
|
||||
NSString *defTz;
|
||||
NSUserDefaults *ud;
|
||||
// TODO: take a default timeZone
|
||||
ud = [NSUserDefaults standardUserDefaults];
|
||||
defTz = [ud stringForKey:@"iCalTimeZoneName"];
|
||||
if ([defTz length] == 0)
|
||||
defTz = [ud stringForKey:@"TimeZoneName"];
|
||||
if ([defTz length] == 0)
|
||||
defTz = [ud stringForKey:@"TimeZone"];
|
||||
if ([defTz length] == 0)
|
||||
defTz = @"GMT";
|
||||
iCalDefaultTZ = [defTz retain];
|
||||
}
|
||||
|
||||
_tzid = iCalDefaultTZ;
|
||||
|
||||
}
|
||||
|
||||
if ([_tzid length] == 0)
|
||||
_tzid = @"GMT";
|
||||
|
||||
tz = [idToTz objectForKey:_tzid];
|
||||
if (tz == nil) tz = [NSTimeZone timeZoneWithName:_tzid];
|
||||
if (tz == nil) tz = [NSTimeZone timeZoneWithAbbreviation:_tzid];
|
||||
|
||||
if (tz == nil) {
|
||||
NSLog(@"couldn't map timezone id %@", _tzid);
|
||||
}
|
||||
|
||||
if (tz) [idToTz setObject:tz forKey:_tzid];
|
||||
return tz;
|
||||
}
|
||||
|
||||
@end /* NSTimeZone(iCalTimeZone) */
|
|
@ -0,0 +1,41 @@
|
|||
/* iCalDateTime.h - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ICALDATETIMEELEMENT_H
|
||||
#define ICALDATETIMEELEMENT_H
|
||||
|
||||
@class NSCalendarDate;
|
||||
@class iCalTimeZone;
|
||||
|
||||
#import "CardElement.h"
|
||||
|
||||
@interface iCalDateTime : CardElement
|
||||
|
||||
- (void) setTimeZone: (iCalTimeZone *) iTZ;
|
||||
- (iCalTimeZone *) timeZone;
|
||||
|
||||
- (void) setDateTime: (NSCalendarDate *) dateTime;
|
||||
- (NSCalendarDate *) dateTime;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* ICALDATETIMEELEMENT_H */
|
|
@ -0,0 +1,155 @@
|
|||
/* iCalDateTime.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
#import "NSCalendarDate+NGCards.h"
|
||||
#import "NSString+NGCards.h"
|
||||
|
||||
#import "iCalCalendar.h"
|
||||
#import "iCalTimeZone.h"
|
||||
|
||||
#import "iCalDateTime.h"
|
||||
|
||||
// static NSTimeZone *localTimeZone = nil;
|
||||
|
||||
@implementation iCalDateTime
|
||||
|
||||
// + (void) initialize
|
||||
// {
|
||||
// if (!localTimeZone)
|
||||
// {
|
||||
// localTimeZone = [NSTimeZone defaultTimeZone];
|
||||
// [localTimeZone retain];
|
||||
// }
|
||||
// }
|
||||
|
||||
// + (void) setLocalTimeZone: (NSTimeZone *) aTimeZone
|
||||
// {
|
||||
// [localTimeZone release];
|
||||
// localTimeZone = aTimeZone;
|
||||
// [localTimeZone retain];
|
||||
// }
|
||||
|
||||
- (void) setTimeZone: (iCalTimeZone *) iTZ
|
||||
{
|
||||
iCalCalendar *calendar;
|
||||
NSCalendarDate *dateTime;
|
||||
NSString *newTZId;
|
||||
|
||||
dateTime = [self dateTime];
|
||||
if (iTZ)
|
||||
{
|
||||
calendar
|
||||
= (iCalCalendar *) [self searchParentOfClass: [iCalCalendar class]];
|
||||
if (calendar)
|
||||
[calendar addTimeZone: iTZ];
|
||||
newTZId = [iTZ tzId];
|
||||
}
|
||||
[self setValue: 0 ofAttribute: @"tzid" to: newTZId];
|
||||
[self setDateTime: dateTime];
|
||||
}
|
||||
|
||||
- (iCalTimeZone *) timeZone
|
||||
{
|
||||
iCalCalendar *calendar;
|
||||
NSString *tzId;
|
||||
iCalTimeZone *timeZone;
|
||||
|
||||
tzId = [self value: 0 ofAttribute: @"tzid"];
|
||||
calendar
|
||||
= (iCalCalendar *) [self searchParentOfClass: [iCalCalendar class]];
|
||||
if ([tzId length] && calendar)
|
||||
timeZone = [calendar timeZoneWithId: tzId];
|
||||
else
|
||||
timeZone = nil;
|
||||
|
||||
return timeZone;
|
||||
}
|
||||
|
||||
/* TODO: should implement the case where the TZ would be implicitly local
|
||||
(no TZID and no UTC) */
|
||||
- (void) setDateTime: (NSCalendarDate *) dateTime
|
||||
{
|
||||
NSCalendarDate *tmpTime;
|
||||
NSTimeZone *utcTZ;
|
||||
NSString *timeString;
|
||||
iCalTimeZone *tz;
|
||||
|
||||
if (dateTime)
|
||||
{
|
||||
tz = [self timeZone];
|
||||
if (tz)
|
||||
timeString = [tz dateTimeStringForDate: dateTime];
|
||||
else
|
||||
{
|
||||
utcTZ = [NSTimeZone timeZoneWithName: @"GMT"];
|
||||
|
||||
tmpTime = [dateTime copy];
|
||||
[tmpTime setTimeZone: utcTZ];
|
||||
timeString = [NSString stringWithFormat: @"%@Z",
|
||||
[tmpTime iCalFormattedDateTimeString]];
|
||||
[tmpTime release];
|
||||
}
|
||||
}
|
||||
else
|
||||
timeString = @"";
|
||||
|
||||
[self setValue: 0 to: timeString];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) dateTime
|
||||
{
|
||||
iCalTimeZone *iTZ;
|
||||
NSString *date;
|
||||
NSCalendarDate *initialDate, *dateTime;
|
||||
NSTimeZone *tz;
|
||||
|
||||
date = [self value: 0];
|
||||
iTZ = [self timeZone];
|
||||
if (iTZ)
|
||||
dateTime = [iTZ dateForDateTimeString: date];
|
||||
else
|
||||
{
|
||||
initialDate = [date asCalendarDate];
|
||||
if (initialDate)
|
||||
{
|
||||
if ([date hasSuffix: @"Z"] || [date hasSuffix: @"z"])
|
||||
dateTime = initialDate;
|
||||
else
|
||||
{
|
||||
/* same TODO as above */
|
||||
tz = [NSTimeZone defaultTimeZone];
|
||||
dateTime = [initialDate addYear: 0 month: 0 day: 0
|
||||
hour: 0 minute: 0
|
||||
second: -[tz secondsFromGMT]];
|
||||
}
|
||||
}
|
||||
else
|
||||
dateTime = nil;
|
||||
}
|
||||
|
||||
return dateTime;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalEntityObject_H__
|
||||
#define __NGCards_iCalEntityObject_H__
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
/*
|
||||
iCalEntityObject
|
||||
|
||||
This is a common base class for tasks and appointments which share a lot of
|
||||
attributes.
|
||||
*/
|
||||
|
||||
@class NSCalendarDate, NSMutableArray, NSString, NSArray, NSNumber;
|
||||
@class iCalPerson;
|
||||
@class NSURL;
|
||||
|
||||
@interface iCalEntityObject : CardGroup
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setUid: (NSString *) _value;
|
||||
- (NSString *) uid;
|
||||
|
||||
- (void) setSummary: (NSString *) _value;
|
||||
- (NSString *) summary;
|
||||
|
||||
- (void) setLocation: (NSString *) _value;
|
||||
- (NSString *) location;
|
||||
|
||||
- (void) setComment: (NSString *) _value;
|
||||
- (NSString *) comment;
|
||||
|
||||
- (void) setAccessClass:(NSString *) _value;
|
||||
- (NSString *) accessClass;
|
||||
- (BOOL) isPublic;
|
||||
|
||||
- (void) setPriority: (NSString *) _value;
|
||||
- (NSString *) priority;
|
||||
|
||||
- (void) setCategories: (NSString *) _value;
|
||||
- (NSString *)categories;
|
||||
|
||||
- (void) setUserComment: (NSString *) _userComment;
|
||||
- (NSString *) userComment;
|
||||
|
||||
- (void) setTimeStampAsDate: (NSCalendarDate *)_date;
|
||||
- (NSCalendarDate *) timeStampAsDate;
|
||||
|
||||
- (void)setStartDate:(NSCalendarDate *)_date;
|
||||
- (NSCalendarDate *)startDate;
|
||||
- (BOOL) hasStartDate;
|
||||
|
||||
- (void)setLastModified:(NSCalendarDate *)_value;
|
||||
- (NSCalendarDate *)lastModified;
|
||||
|
||||
- (void)setCreated:(NSCalendarDate *)_value;
|
||||
- (NSCalendarDate *)created;
|
||||
|
||||
- (void)setSequence:(NSNumber *)_value; /* this is an int */
|
||||
- (NSNumber *)sequence;
|
||||
- (void)increaseSequence;
|
||||
|
||||
/* url can either be set as NSString or NSURL */
|
||||
- (void)setUrl:(id)_value;
|
||||
- (NSURL *)url;
|
||||
|
||||
- (void)setOrganizer:(iCalPerson *)_organizer;
|
||||
- (iCalPerson *)organizer;
|
||||
- (BOOL)isOrganizer:(id)_email;
|
||||
|
||||
- (void)setStatus:(NSString *)_value;
|
||||
- (NSString *)status;
|
||||
|
||||
- (void)removeAllAttendees;
|
||||
- (void)addToAttendees:(iCalPerson *)_person;
|
||||
- (NSArray *)attendees;
|
||||
- (void) setAttendees: (NSArray *) attendees;
|
||||
|
||||
/* categorize attendees into participants and resources */
|
||||
- (NSArray *)participants;
|
||||
- (NSArray *)resources;
|
||||
- (BOOL)isParticipant:(id)_email;
|
||||
- (iCalPerson *)findParticipantWithEmail:(id)_email;
|
||||
|
||||
- (void)removeAllAlarms;
|
||||
- (void)addToAlarms:(id)_alarm;
|
||||
- (NSArray *)alarms;
|
||||
- (BOOL)hasAlarms;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalEntityObject_H__ */
|
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import "NSCalendarDate+NGCards.h"
|
||||
#import "CardGroup+iCal.h"
|
||||
|
||||
#import "iCalAlarm.h"
|
||||
#import "iCalDateTime.h"
|
||||
#import "iCalEntityObject.h"
|
||||
#import "iCalPerson.h"
|
||||
#import "common.h"
|
||||
|
||||
@interface iCalEntityObject (PrivateAPI)
|
||||
- (NSArray *)_filteredAttendeesThinkingOfPersons:(BOOL)_persons;
|
||||
@end
|
||||
|
||||
@implementation iCalEntityObject
|
||||
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
if ([classTag isEqualToString: @"ATTENDEE"]
|
||||
|| [classTag isEqualToString: @"ORGANIZER"])
|
||||
tagClass = [iCalPerson class];
|
||||
else if ([classTag isEqualToString: @"VALARM"])
|
||||
tagClass = [iCalAlarm class];
|
||||
else if ([classTag isEqualToString: @"SUMMARY"]
|
||||
|| [classTag isEqualToString: @"UID"]
|
||||
|| [classTag isEqualToString: @"COMMENT"]
|
||||
|| [classTag isEqualToString: @"DESCRIPTION"]
|
||||
|| [classTag isEqualToString: @"CLASS"]
|
||||
|| [classTag isEqualToString: @"STATUS"]
|
||||
|| [classTag isEqualToString: @"SEQUENCE"]
|
||||
|| [classTag isEqualToString: @"URL"]
|
||||
|| [classTag isEqualToString: @"PRIORITY"]
|
||||
|| [classTag isEqualToString: @"CATEGORIES"]
|
||||
|| [classTag isEqualToString: @"LOCATION"])
|
||||
tagClass = [CardElement class];
|
||||
else if ([classTag isEqualToString: @"DTSTAMP"]
|
||||
|| [classTag isEqualToString: @"DTSTART"]
|
||||
|| [classTag isEqualToString: @"CREATED"]
|
||||
|| [classTag isEqualToString: @"LAST-MODIFIED"])
|
||||
tagClass = [iCalDateTime class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setUid: (NSString *) _uid
|
||||
{
|
||||
[[self uniqueChildWithTag: @"uid"] setValue: 0 to: _uid];
|
||||
}
|
||||
|
||||
- (NSString *) uid
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"uid"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setSummary: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"summary"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) summary
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"summary"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setLocation: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"location"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) location
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"location"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setComment: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"description"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) comment
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"description"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setAccessClass: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"class"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) accessClass
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"class"] value: 0];
|
||||
}
|
||||
|
||||
- (BOOL) isPublic
|
||||
{
|
||||
return [[[self accessClass] uppercaseString] isEqualToString: @"PUBLIC"];
|
||||
}
|
||||
|
||||
- (void) setPriority: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"priority"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) priority
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"priority"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setCategories: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"categories"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) categories
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"categories"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setUserComment: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"usercomment"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) userComment
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"usercomment"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setStatus: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"status"] setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) status
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"status"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setSequence: (NSNumber *)_value
|
||||
{
|
||||
NSString *sequence;
|
||||
|
||||
sequence = [NSString stringWithFormat: @"%@", _value];
|
||||
[[self uniqueChildWithTag: @"sequence"] setValue: 0
|
||||
to: sequence];;
|
||||
}
|
||||
|
||||
- (NSNumber *) sequence
|
||||
{
|
||||
NSString *sequence;
|
||||
|
||||
sequence = [[self uniqueChildWithTag: @"sequence"] value: 0];
|
||||
|
||||
return [NSNumber numberWithInt: [sequence intValue]];
|
||||
}
|
||||
|
||||
- (void) increaseSequence
|
||||
{
|
||||
int seq;
|
||||
|
||||
seq = [[self sequence] intValue];
|
||||
seq += 1;
|
||||
[self setSequence: [NSNumber numberWithInt: seq]];
|
||||
}
|
||||
|
||||
- (void) setCreated: (NSCalendarDate *) _value
|
||||
{
|
||||
[self setDate: _value forDateTimeValue: @"created"];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) created
|
||||
{
|
||||
return [self dateForDateTimeValue: @"created"];
|
||||
}
|
||||
|
||||
- (void) setLastModified: (NSCalendarDate *) _value
|
||||
{
|
||||
[self setDate: _value forDateTimeValue: @"last-modified"];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) lastModified
|
||||
{
|
||||
return [self dateForDateTimeValue: @"last-modified"];
|
||||
}
|
||||
|
||||
- (void) setTimeStampAsDate: (NSCalendarDate *) _value
|
||||
{
|
||||
[self setDate: _value forDateTimeValue: @"dtstamp"];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) timeStampAsDate
|
||||
{
|
||||
return [self dateForDateTimeValue: @"dtstamp"];
|
||||
}
|
||||
|
||||
- (void) setStartDate: (NSCalendarDate *) _value
|
||||
{
|
||||
[self setDate: _value forDateTimeValue: @"dtstart"];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) startDate
|
||||
{
|
||||
return [self dateForDateTimeValue: @"dtstart"];
|
||||
}
|
||||
|
||||
- (BOOL) hasStartDate
|
||||
{
|
||||
return ([[self childrenWithTag: @"dtstart"] count] > 0);
|
||||
}
|
||||
|
||||
- (void) setOrganizer: (iCalPerson *) _organizer
|
||||
{
|
||||
[_organizer setTag: @"organizer"];
|
||||
[self setUniqueChild: _organizer];
|
||||
}
|
||||
|
||||
- (iCalPerson *) organizer
|
||||
{
|
||||
return (iCalPerson *) [self uniqueChildWithTag: @"organizer"];
|
||||
}
|
||||
|
||||
- (void) removeAllAttendees
|
||||
{
|
||||
[children removeObjectsInArray: [self attendees]];
|
||||
}
|
||||
|
||||
- (void) addToAttendees: (iCalPerson *) _person
|
||||
{
|
||||
[_person setTag: @"attendee"];
|
||||
[self addChild: _person];
|
||||
}
|
||||
|
||||
- (void) setAttendees: (NSArray *) attendees
|
||||
{
|
||||
[self removeAllAttendees];
|
||||
[self addChildren: attendees];
|
||||
}
|
||||
|
||||
- (NSArray *) attendees
|
||||
{
|
||||
return [self childrenWithTag: @"attendee"];
|
||||
}
|
||||
|
||||
- (void) removeAllAlarms
|
||||
{
|
||||
[children removeObjectsInArray: [self alarms]];
|
||||
}
|
||||
|
||||
- (void) addToAlarms: (id) _alarm
|
||||
{
|
||||
if (_alarm)
|
||||
{
|
||||
[_alarm setTag: @"valarm"];
|
||||
[self addChild: _alarm];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) hasAlarms
|
||||
{
|
||||
return ([[self childrenWithTag: @"valarm"] count] > 0);
|
||||
}
|
||||
|
||||
- (NSArray *) alarms
|
||||
{
|
||||
return [self childrenWithTag: @"valarm"];
|
||||
}
|
||||
|
||||
- (void) setUrl: (id) _value
|
||||
{
|
||||
NSString *asString;
|
||||
|
||||
if ([_value isKindOfClass: [NSString class]])
|
||||
asString = _value;
|
||||
else if ([_value isKindOfClass: [NSURL class]])
|
||||
asString = [_value absoluteString];
|
||||
else
|
||||
asString = @"";
|
||||
|
||||
[[self uniqueChildWithTag: @"url"] setValue: 0 to: asString];
|
||||
}
|
||||
|
||||
- (NSURL *) url
|
||||
{
|
||||
NSString *stringUrl;
|
||||
|
||||
stringUrl = [[self uniqueChildWithTag: @"url"] value: 0];
|
||||
|
||||
return [NSURL URLWithString: stringUrl];
|
||||
}
|
||||
|
||||
/* stuff */
|
||||
|
||||
- (NSArray *) participants
|
||||
{
|
||||
return [self _filteredAttendeesThinkingOfPersons: YES];
|
||||
}
|
||||
|
||||
- (NSArray *) resources
|
||||
{
|
||||
return [self _filteredAttendeesThinkingOfPersons: NO];
|
||||
}
|
||||
|
||||
- (NSArray *) _filteredAttendeesThinkingOfPersons: (BOOL) _persons
|
||||
{
|
||||
NSArray *list;
|
||||
NSMutableArray *filtered;
|
||||
unsigned count, max;
|
||||
iCalPerson *person;
|
||||
NSString *role;
|
||||
|
||||
if (_persons)
|
||||
{
|
||||
list = [self attendees];
|
||||
max = [list count];
|
||||
filtered = [NSMutableArray arrayWithCapacity: max];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
person = (iCalPerson *) [list objectAtIndex: count];
|
||||
role = [[person role] uppercaseString];
|
||||
if (![role hasPrefix: @"NON-PART"])
|
||||
[filtered addObject: person];
|
||||
}
|
||||
|
||||
list = filtered;
|
||||
}
|
||||
else
|
||||
list = [self childrenWithTag: @"attendee"
|
||||
andAttribute: @"role"
|
||||
havingValue: @"non-part"];
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
- (BOOL) isOrganizer: (id)_email
|
||||
{
|
||||
_email = [_email lowercaseString];
|
||||
|
||||
return [[[[self organizer] rfc822Email] lowercaseString]
|
||||
isEqualToString:_email];
|
||||
}
|
||||
|
||||
- (BOOL) isParticipant: (id) _email
|
||||
{
|
||||
NSArray *partEmails;
|
||||
|
||||
_email = [_email lowercaseString];
|
||||
partEmails = [[self participants] valueForKey:@"rfc822Email"];
|
||||
partEmails = [partEmails valueForKey: @"lowercaseString"];
|
||||
return [partEmails containsObject:_email];
|
||||
}
|
||||
|
||||
- (iCalPerson *) findParticipantWithEmail: (id) _email
|
||||
{
|
||||
NSArray *ps;
|
||||
unsigned i, count;
|
||||
|
||||
_email = [_email lowercaseString];
|
||||
ps = [self participants];
|
||||
count = [ps count];
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
iCalPerson *p;
|
||||
|
||||
p = [ps objectAtIndex:i];
|
||||
if ([[[p rfc822Email] lowercaseString] isEqualToString:_email])
|
||||
return p;
|
||||
}
|
||||
|
||||
return nil; /* not found */
|
||||
}
|
||||
|
||||
@end /* iCalEntityObject */
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalEvent_H__
|
||||
#define __NGCards_iCalEvent_H__
|
||||
|
||||
#import "iCalRepeatableEntityObject.h"
|
||||
|
||||
/*
|
||||
iCalEvent
|
||||
|
||||
This class keeps the attributes of an iCalendar event record, that is,
|
||||
an appointment.
|
||||
*/
|
||||
|
||||
@class NSCalendarDate;
|
||||
@class NSDate;
|
||||
@class NSString;
|
||||
@class NSMutableArray;
|
||||
|
||||
@class NGCalendarDateRange;
|
||||
@class iCalEventChanges;
|
||||
|
||||
@interface iCalEvent : iCalRepeatableEntityObject
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setEndDate: (NSCalendarDate *) _date;
|
||||
- (NSCalendarDate *) endDate;
|
||||
- (BOOL) hasEndDate;
|
||||
|
||||
- (void) setDuration: (NSString *) _value;
|
||||
- (NSString *) duration;
|
||||
- (BOOL) hasDuration;
|
||||
- (NSTimeInterval) durationAsTimeInterval;
|
||||
|
||||
- (void) setTransparency: (NSString *) _transparency;
|
||||
- (NSString *) transparency;
|
||||
|
||||
/* convenience */
|
||||
|
||||
- (BOOL) isOpaque;
|
||||
- (BOOL) isAllDay;
|
||||
|
||||
- (BOOL) isWithinCalendarDateRange: (NGCalendarDateRange *) _range;
|
||||
- (NSArray *) recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *)_r;
|
||||
|
||||
- (NSCalendarDate *) lastPossibleRecurrenceStartDate;
|
||||
|
||||
/* calculating changes */
|
||||
|
||||
- (iCalEventChanges *) getChangesRelativeToEvent: (iCalEvent *) _event;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalEvent_H__ */
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <NGExtensions/NGCalendarDateRange.h>
|
||||
|
||||
#import "NSCalendarDate+NGCards.h"
|
||||
#import "CardGroup+iCal.h"
|
||||
#import "NSString+NGCards.h"
|
||||
|
||||
#import "iCalEventChanges.h"
|
||||
#import "iCalDateTime.h"
|
||||
|
||||
#import "iCalEvent.h"
|
||||
|
||||
@implementation iCalEvent
|
||||
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
if ([classTag isEqualToString: @"DURATION"]
|
||||
|| [classTag isEqualToString: @"TRANSP"])
|
||||
tagClass = [CardElement class];
|
||||
else if ([classTag isEqualToString: @"DTEND"])
|
||||
tagClass = [iCalDateTime class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setEndDate: (NSCalendarDate *)_date
|
||||
{
|
||||
[self setDate: _date forDateTimeValue: @"dtend"];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) endDate
|
||||
{
|
||||
return [self dateForDateTimeValue: @"dtend"];
|
||||
}
|
||||
|
||||
- (BOOL) hasEndDate
|
||||
{
|
||||
return ([[self childrenWithTag: @"dtend"] count] > 0);
|
||||
}
|
||||
|
||||
- (void) setDuration: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"duration"] setValue: 0
|
||||
to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) duration
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"duration"] value: 0];
|
||||
}
|
||||
|
||||
- (BOOL) hasDuration
|
||||
{
|
||||
return ([[self childrenWithTag: @"duration"] count] > 0);
|
||||
}
|
||||
|
||||
- (NSTimeInterval) durationAsTimeInterval
|
||||
{
|
||||
/*
|
||||
eg: DURATION:PT1H
|
||||
P - "period"
|
||||
P2H30M - "2 hours 30 minutes"
|
||||
|
||||
dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
|
||||
|
||||
dur-date = dur-day [dur-time]
|
||||
dur-time = "T" (dur-hour / dur-minute / dur-second)
|
||||
dur-week = 1*DIGIT "W"
|
||||
dur-hour = 1*DIGIT "H" [dur-minute]
|
||||
dur-minute = 1*DIGIT "M" [dur-second]
|
||||
dur-second = 1*DIGIT "S"
|
||||
dur-day = 1*DIGIT "D"
|
||||
*/
|
||||
NSTimeInterval interval;
|
||||
|
||||
if ([self hasDuration])
|
||||
interval = [[self duration] durationAsTimeInterval];
|
||||
else if ([self hasEndDate] && [self hasStartDate])
|
||||
/* calculate duration using enddate */
|
||||
interval = [[self endDate] timeIntervalSinceDate: [self startDate]];
|
||||
else
|
||||
interval = 0.0;
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
- (void) setTransparency: (NSString *) _transparency
|
||||
{
|
||||
[[self uniqueChildWithTag: @"transp"] setValue: 0
|
||||
to: _transparency];
|
||||
}
|
||||
|
||||
- (NSString *) transparency
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"transp"] value: 0];
|
||||
}
|
||||
|
||||
/* convenience */
|
||||
|
||||
- (BOOL) isOpaque
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [[self transparency] uppercaseString];
|
||||
|
||||
return (![s isEqualToString: @"TRANSPARENT"]);
|
||||
}
|
||||
|
||||
/* TODO: FIX THIS!
|
||||
The problem is, that startDate/endDate are inappropriately modelled here.
|
||||
We'd need to have a special iCalDate in order to fix all the mess.
|
||||
For the time being, we chose allday to mean 00:00 - 23:59 in startDate's
|
||||
timezone.
|
||||
*/
|
||||
- (BOOL) isAllDay
|
||||
{
|
||||
NSCalendarDate *ed, *startDate;
|
||||
BOOL allDay;
|
||||
|
||||
if ([self hasEndDate])
|
||||
{
|
||||
ed = [self endDate];
|
||||
startDate = [self startDate];
|
||||
[ed setTimeZone: [startDate timeZone]];
|
||||
allDay = (([startDate hourOfDay] == 0)
|
||||
&& ([startDate minuteOfHour] == 0)
|
||||
&& ([ed hourOfDay] == 23)
|
||||
&& ([ed minuteOfHour] == 59));
|
||||
}
|
||||
else
|
||||
allDay = NO;
|
||||
|
||||
return allDay;
|
||||
}
|
||||
|
||||
- (BOOL) isWithinCalendarDateRange: (NGCalendarDateRange *) _range
|
||||
{
|
||||
NGCalendarDateRange *r;
|
||||
NSCalendarDate *startDate, *endDate;
|
||||
NGCalendarDateRange *fir;
|
||||
|
||||
startDate = [self startDate];
|
||||
endDate = [self endDate];
|
||||
|
||||
if (![self isRecurrent])
|
||||
{
|
||||
if ([self hasStartDate] && [self hasEndDate])
|
||||
{
|
||||
r = [NGCalendarDateRange calendarDateRangeWithStartDate: startDate
|
||||
endDate: endDate];
|
||||
return [_range containsDateRange: r];
|
||||
}
|
||||
else
|
||||
return [_range containsDate: startDate];
|
||||
}
|
||||
else
|
||||
{
|
||||
fir = [NGCalendarDateRange calendarDateRangeWithStartDate:startDate
|
||||
endDate: endDate];
|
||||
|
||||
return [self isWithinCalendarDateRange: _range
|
||||
firstInstanceCalendarDateRange: fir];
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSArray *) recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *)_r
|
||||
{
|
||||
NGCalendarDateRange *fir;
|
||||
|
||||
if (![self isRecurrent])
|
||||
return nil;
|
||||
|
||||
fir = [NGCalendarDateRange calendarDateRangeWithStartDate: [self startDate]
|
||||
endDate: [self endDate]];
|
||||
return [self recurrenceRangesWithinCalendarDateRange:_r
|
||||
firstInstanceCalendarDateRange:fir];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) lastPossibleRecurrenceStartDate
|
||||
{
|
||||
NGCalendarDateRange *fir;
|
||||
|
||||
if (![self isRecurrent])
|
||||
return nil;
|
||||
|
||||
fir = [NGCalendarDateRange calendarDateRangeWithStartDate: [self startDate]
|
||||
endDate: [self endDate]];
|
||||
|
||||
return [self lastPossibleRecurrenceStartDateUsingFirstInstanceCalendarDateRange: fir];
|
||||
}
|
||||
|
||||
/* ical typing */
|
||||
|
||||
- (NSString *) entityName
|
||||
{
|
||||
return @"vevent";
|
||||
}
|
||||
|
||||
/* descriptions */
|
||||
|
||||
// - (NSString *) description {
|
||||
// NSMutableString *ms;
|
||||
|
||||
// ms = [NSMutableString stringWithCapacity:128];
|
||||
// [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
|
||||
|
||||
// if (uid) [ms appendFormat:@" uid=%@", uid];
|
||||
// if (startDate) [ms appendFormat:@" from=%@", startDate];
|
||||
// if (endDate) [ms appendFormat:@" to=%@", endDate];
|
||||
// if (summary) [ms appendFormat:@" summary=%@", summary];
|
||||
|
||||
// if (organizer)
|
||||
// [ms appendFormat:@" organizer=%@", organizer];
|
||||
// if (attendees)
|
||||
// [ms appendFormat:@" attendees=%@", attendees];
|
||||
|
||||
// if ([self hasAlarms])
|
||||
// [ms appendFormat:@" alarms=%@", alarms];
|
||||
|
||||
// [ms appendString:@">"];
|
||||
// return ms;
|
||||
// }
|
||||
|
||||
/* changes */
|
||||
|
||||
- (iCalEventChanges *) getChangesRelativeToEvent: (iCalEvent *) _event
|
||||
{
|
||||
return [iCalEventChanges changesFromEvent: _event
|
||||
toEvent: self];
|
||||
}
|
||||
|
||||
@end /* iCalEvent */
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
// Created by znek on 31.08.04.
|
||||
|
||||
#ifndef __NGiCal_iCalEventChanges_H_
|
||||
#define __NGiCal_iCalEventChanges_H_
|
||||
|
||||
#include <Foundation/NSObject.h>
|
||||
|
||||
@class iCalEvent, NSArray, NSMutableArray;
|
||||
|
||||
@interface iCalEventChanges : NSObject
|
||||
{
|
||||
NSMutableArray *insertedAttendees;
|
||||
NSMutableArray *deletedAttendees;
|
||||
NSMutableArray *updatedAttendees;
|
||||
NSMutableArray *insertedAlarms;
|
||||
NSMutableArray *deletedAlarms;
|
||||
NSMutableArray *updatedAlarms;
|
||||
NSMutableArray *updatedProperties;
|
||||
}
|
||||
|
||||
+ (id)changesFromEvent:(iCalEvent *)_old toEvent:(iCalEvent *)_to;
|
||||
- (id)initWithFromEvent:(iCalEvent *)_from toEvent:(iCalEvent *)_to;
|
||||
|
||||
- (BOOL)hasChanges;
|
||||
|
||||
- (BOOL)hasAttendeeChanges;
|
||||
- (NSArray *)insertedAttendees;
|
||||
- (NSArray *)deletedAttendees;
|
||||
- (NSArray *)updatedAttendees;
|
||||
|
||||
- (BOOL)hasAlarmChanges;
|
||||
- (NSArray *)insertedAlarms;
|
||||
- (NSArray *)deletedAlarms;
|
||||
- (NSArray *)updatedAlarms;
|
||||
|
||||
- (BOOL)hasPropertyChanges;
|
||||
- (NSArray *)updatedProperties;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_iCalEventChanges_H_ */
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "iCalEventChanges.h"
|
||||
#include "iCalEvent.h"
|
||||
#include "iCalPerson.h"
|
||||
#include "common.h"
|
||||
|
||||
@interface iCalEventChanges (PrivateAPI)
|
||||
- (void)_trackAttendeeChanges:(iCalEvent *)_from :(iCalEvent *)_to;
|
||||
- (void)_trackAlarmChanges:(iCalEvent *)_from :(iCalEvent *)_to;
|
||||
- (void)_trackPropertyChanges:(iCalEvent *)_from :(iCalEvent *)_to;
|
||||
@end
|
||||
|
||||
@implementation iCalEventChanges
|
||||
|
||||
+ (id)changesFromEvent:(iCalEvent *)_from toEvent:(iCalEvent *)_to {
|
||||
return [[[self alloc] initWithFromEvent:_from toEvent:_to] autorelease];
|
||||
}
|
||||
|
||||
- (id)initWithFromEvent:(iCalEvent *)_from toEvent:(iCalEvent *)_to {
|
||||
self = [super init];
|
||||
if(self) {
|
||||
self->insertedAttendees = [[NSMutableArray alloc] init];
|
||||
self->deletedAttendees = [[NSMutableArray alloc] init];
|
||||
self->updatedAttendees = [[NSMutableArray alloc] init];
|
||||
self->insertedAlarms = [[NSMutableArray alloc] init];
|
||||
self->deletedAlarms = [[NSMutableArray alloc] init];
|
||||
self->updatedAlarms = [[NSMutableArray alloc] init];
|
||||
self->updatedProperties = [[NSMutableArray alloc] init];
|
||||
[self _trackAttendeeChanges:_from :_to];
|
||||
[self _trackPropertyChanges:_from :_to];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self->insertedAttendees release];
|
||||
[self->deletedAttendees release];
|
||||
[self->updatedAttendees release];
|
||||
[self->insertedAlarms release];
|
||||
[self->deletedAlarms release];
|
||||
[self->updatedAlarms release];
|
||||
[self->updatedProperties release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)_trackAttendeeChanges:(iCalEvent *)_from :(iCalEvent *)_to {
|
||||
unsigned f, t, fcount, tcount;
|
||||
NSArray *fromAttendees, *toAttendees;
|
||||
|
||||
fromAttendees = [_from attendees];
|
||||
fcount = [fromAttendees count];
|
||||
toAttendees = [_to attendees];
|
||||
tcount = [toAttendees count];
|
||||
for(f = 0; f < fcount; f++) {
|
||||
iCalPerson *fp;
|
||||
BOOL found = NO;
|
||||
|
||||
fp = [fromAttendees objectAtIndex:f];
|
||||
|
||||
for(t = 0; t < tcount; t++) {
|
||||
iCalPerson *tp;
|
||||
|
||||
tp = [toAttendees objectAtIndex:t];
|
||||
if([fp hasSameEmailAddress:tp]) {
|
||||
found = YES;
|
||||
if(![fp isEqualToPerson:tp]) {
|
||||
[self->updatedAttendees addObject:tp];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
[self->deletedAttendees addObject:fp];
|
||||
}
|
||||
}
|
||||
for(t = 0; t < tcount; t++) {
|
||||
iCalPerson *tp;
|
||||
BOOL found = NO;
|
||||
|
||||
tp = [toAttendees objectAtIndex:t];
|
||||
for(f = 0; f < fcount; f++) {
|
||||
iCalPerson *fp;
|
||||
|
||||
fp = [fromAttendees objectAtIndex:f];
|
||||
if([tp hasSameEmailAddress:fp]) {
|
||||
found = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
[self->insertedAttendees addObject:tp];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_trackAlarmChanges:(iCalEvent *)_from :(iCalEvent *)_to {
|
||||
}
|
||||
|
||||
- (void)_trackPropertyChanges:(iCalEvent *)_from :(iCalEvent *)_to {
|
||||
if(!IS_EQUAL([_from startDate], [_to startDate], isEqualToDate:))
|
||||
[self->updatedProperties addObject:@"startDate"];
|
||||
if(!IS_EQUAL([_from endDate], [_to endDate], isEqualToDate:))
|
||||
[self->updatedProperties addObject:@"endDate"];
|
||||
if(!IS_EQUAL([_from created], [_to created], isEqualToDate:))
|
||||
[self->updatedProperties addObject:@"created"];
|
||||
if(!IS_EQUAL([_from lastModified], [_to lastModified], isEqualToDate:))
|
||||
[self->updatedProperties addObject:@"lastModified"];
|
||||
if(![_from durationAsTimeInterval] == [_to durationAsTimeInterval])
|
||||
[self->updatedProperties addObject:@"duration"];
|
||||
if(!IS_EQUAL([_from summary], [_to summary], isEqualToString:))
|
||||
[self->updatedProperties addObject:@"summary"];
|
||||
if(!IS_EQUAL([_from location], [_to location], isEqualToString:))
|
||||
[self->updatedProperties addObject:@"location"];
|
||||
if(!IS_EQUAL([_from comment], [_to comment], isEqualToString:))
|
||||
[self->updatedProperties addObject:@"comment"];
|
||||
if(!IS_EQUAL([_from priority], [_to priority], isEqualToString:))
|
||||
[self->updatedProperties addObject:@"priority"];
|
||||
if(!IS_EQUAL([_from status], [_to status], isEqualToString:))
|
||||
[self->updatedProperties addObject:@"status"];
|
||||
if(!IS_EQUAL([_from accessClass], [_to accessClass], isEqualToString:))
|
||||
[self->updatedProperties addObject:@"accessClass"];
|
||||
if(!IS_EQUAL([_from sequence], [_to sequence], isEqualToNumber:))
|
||||
[self->updatedProperties addObject:@"sequence"];
|
||||
if(!IS_EQUAL([_from organizer], [_to organizer], isEqual:))
|
||||
[self->updatedProperties addObject:@"organizer"];
|
||||
}
|
||||
|
||||
- (BOOL)hasChanges {
|
||||
return [self hasAttendeeChanges] ||
|
||||
[self hasAlarmChanges] ||
|
||||
[self hasPropertyChanges];
|
||||
}
|
||||
|
||||
- (BOOL)hasAttendeeChanges {
|
||||
return [[self insertedAttendees] count] > 0 ||
|
||||
[[self deletedAttendees] count] > 0 ||
|
||||
[[self updatedAttendees] count] > 0;
|
||||
}
|
||||
|
||||
- (BOOL)hasAlarmChanges {
|
||||
return [[self insertedAlarms] count] > 0 ||
|
||||
[[self deletedAlarms] count] > 0 ||
|
||||
[[self updatedAlarms] count] > 0;
|
||||
}
|
||||
|
||||
- (BOOL)hasPropertyChanges {
|
||||
return [[self updatedProperties] count] > 0;
|
||||
}
|
||||
|
||||
- (NSArray *)insertedAttendees {
|
||||
return self->insertedAttendees;
|
||||
}
|
||||
- (NSArray *)deletedAttendees {
|
||||
return self->deletedAttendees;
|
||||
}
|
||||
- (NSArray *)updatedAttendees {
|
||||
return self->updatedAttendees;
|
||||
}
|
||||
|
||||
- (NSArray *)insertedAlarms {
|
||||
return self->insertedAlarms;
|
||||
}
|
||||
- (NSArray *)deletedAlarms {
|
||||
return self->deletedAlarms;
|
||||
}
|
||||
- (NSArray *)updatedAlarms {
|
||||
return self->updatedAlarms;
|
||||
}
|
||||
|
||||
- (NSArray *)updatedProperties {
|
||||
return self->updatedProperties;
|
||||
}
|
||||
|
||||
/* descriptions */
|
||||
|
||||
- (NSString *)description {
|
||||
NSMutableString *ms;
|
||||
|
||||
ms = [NSMutableString stringWithCapacity:128];
|
||||
[ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
|
||||
|
||||
[ms appendFormat:@" updatedProperties=%@", self->updatedProperties];
|
||||
[ms appendFormat:@" insertedAttendees=%@", self->insertedAttendees];
|
||||
[ms appendFormat:@" deletedAttendees=%@", self->deletedAttendees];
|
||||
[ms appendFormat:@" updatedAttendees=%@", self->updatedAttendees];
|
||||
|
||||
[ms appendString:@">"];
|
||||
return ms;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalFreeBusy_H__
|
||||
#define __NGCards_iCalFreeBusy_H__
|
||||
|
||||
#import "iCalEntityObject.h"
|
||||
|
||||
@class NSString;
|
||||
@class NSCalendarDate;
|
||||
@class NSURL;
|
||||
@class iCalPerson;
|
||||
|
||||
typedef enum iCalFreeBusyType
|
||||
{
|
||||
iCalFBBusy,
|
||||
iCalFBFree,
|
||||
iCalFBBusyUnavailable,
|
||||
iCalFBBusyTentative
|
||||
} iCalFreeBusyType;
|
||||
|
||||
@interface iCalFreeBusy : iCalEntityObject
|
||||
|
||||
- (void) setEndDate: (NSCalendarDate *) _date;
|
||||
- (NSCalendarDate *) endDate;
|
||||
- (BOOL) hasEndDate;
|
||||
|
||||
- (void) addFreeBusyFrom: (NSCalendarDate *) start
|
||||
to: (NSCalendarDate *) end
|
||||
type: (iCalFreeBusyType) type;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalFreeBusy_H__ */
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSTimeZone.h>
|
||||
|
||||
#import "CardGroup+iCal.h"
|
||||
#import "iCalDateTime.h"
|
||||
#import "NSCalendarDate+NGCards.h"
|
||||
|
||||
#import "iCalFreeBusy.h"
|
||||
|
||||
@implementation iCalFreeBusy
|
||||
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
if ([classTag isEqualToString: @"DTEND"])
|
||||
tagClass = [iCalDateTime class];
|
||||
else if ([classTag isEqualToString: @"FREEBUSY"])
|
||||
tagClass = [CardElement class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
- (void) setEndDate: (NSCalendarDate *)_date
|
||||
{
|
||||
[self setDate: _date forDateTimeValue: @"dtend"];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) endDate
|
||||
{
|
||||
return [self dateForDateTimeValue: @"dtend"];
|
||||
}
|
||||
|
||||
- (BOOL) hasEndDate
|
||||
{
|
||||
return ([[self childrenWithTag: @"dtend"] count] > 0);
|
||||
}
|
||||
|
||||
- (NSString *) _freeBusyTypeString: (iCalFreeBusyType) type
|
||||
{
|
||||
NSString *typeString;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case iCalFBBusy:
|
||||
typeString = @"BUSY";
|
||||
break;
|
||||
case iCalFBFree:
|
||||
typeString = @"FREE";
|
||||
break;
|
||||
case iCalFBBusyUnavailable:
|
||||
typeString = @"BUSY-UNAVAILABLE";
|
||||
break;
|
||||
default:
|
||||
typeString = @"BUSY-TENTATIVE";
|
||||
}
|
||||
|
||||
return typeString;
|
||||
}
|
||||
|
||||
- (void) addFreeBusyFrom: (NSCalendarDate *) start
|
||||
to: (NSCalendarDate *) end
|
||||
type: (iCalFreeBusyType) type
|
||||
{
|
||||
CardElement *freeBusyElement;
|
||||
NSString *value;
|
||||
NSCalendarDate *utcStart, *utcEnd;
|
||||
NSTimeZone *uTZ;
|
||||
|
||||
uTZ = [NSTimeZone timeZoneWithAbbreviation: @"GMT"];
|
||||
utcStart = [start copy];
|
||||
utcEnd = [end copy];
|
||||
[utcStart setTimeZone: uTZ];
|
||||
[utcEnd setTimeZone: uTZ];
|
||||
|
||||
value = [NSString stringWithFormat: @"%@Z/%@Z",
|
||||
[utcStart iCalFormattedDateTimeString],
|
||||
[utcEnd iCalFormattedDateTimeString]];
|
||||
freeBusyElement = [CardElement simpleElementWithTag: @"freebusy"
|
||||
value: value];
|
||||
[freeBusyElement addAttribute: @"fbtype"
|
||||
value: [self _freeBusyTypeString: type]];
|
||||
[self addChild: freeBusyElement];
|
||||
|
||||
[utcStart release];
|
||||
[utcEnd release];
|
||||
}
|
||||
|
||||
/* ical typing */
|
||||
|
||||
- (NSString *) entityName
|
||||
{
|
||||
return @"vfreebusy";
|
||||
}
|
||||
|
||||
@end /* iCalFreeBusy */
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalJournal_H__
|
||||
#define __NGCards_iCalJournal_H__
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
@interface iCalJournal : CardGroup
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalJournal_H__ */
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalJournal.h"
|
||||
#include "common.h"
|
||||
|
||||
@implementation iCalJournal
|
||||
|
||||
/* ical typing */
|
||||
|
||||
- (NSString *) entityName
|
||||
{
|
||||
return @"vjournal";
|
||||
}
|
||||
|
||||
/* descriptions */
|
||||
|
||||
@end /* iCalJournal */
|
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalRecurrenceCalculator.h"
|
||||
|
||||
@interface iCalMonthlyRecurrenceCalculator : iCalRecurrenceCalculator
|
||||
@end
|
||||
|
||||
#include <NGExtensions/NGCalendarDateRange.h>
|
||||
#include "iCalRecurrenceRule.h"
|
||||
#include "NSCalendarDate+ICal.h"
|
||||
#include "common.h"
|
||||
#include <string.h>
|
||||
|
||||
@interface iCalRecurrenceCalculator(PrivateAPI)
|
||||
- (NSCalendarDate *)lastInstanceStartDate;
|
||||
@end
|
||||
|
||||
// #define HEAVY_DEBUG 1
|
||||
|
||||
@implementation iCalMonthlyRecurrenceCalculator
|
||||
|
||||
typedef BOOL NGMonthSet[12];
|
||||
typedef BOOL NGMonthDaySet[32]; // 0 is unused
|
||||
|
||||
static void NGMonthDaySet_clear(NGMonthDaySet *daySet) {
|
||||
register unsigned i;
|
||||
|
||||
for (i = 1; i <= 31; i++)
|
||||
(*daySet)[i] = NO;
|
||||
}
|
||||
|
||||
static void NGMonthDaySet_copyOrUnion(NGMonthDaySet *base, NGMonthDaySet *new,
|
||||
BOOL doCopy)
|
||||
{
|
||||
register unsigned i;
|
||||
|
||||
if (doCopy)
|
||||
memcpy(base, new, sizeof(NGMonthDaySet));
|
||||
else {
|
||||
for (i = 1; i <= 31; i++) {
|
||||
if (!(*new)[i])
|
||||
(*base)[i] = NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL NGMonthDaySet_fillWithByMonthDay(NGMonthDaySet *daySet,
|
||||
NSArray *byMonthDay)
|
||||
{
|
||||
/* list of days in the month */
|
||||
unsigned i, count;
|
||||
BOOL ok;
|
||||
|
||||
NGMonthDaySet_clear(daySet);
|
||||
|
||||
for (i = 0, count = [byMonthDay count], ok = YES; i < count; i++) {
|
||||
int dayInMonth; /* -31..-1 and 1..31 */
|
||||
|
||||
if ((dayInMonth = [[byMonthDay objectAtIndex:i] intValue]) == 0) {
|
||||
ok = NO;
|
||||
continue; /* invalid value */
|
||||
}
|
||||
if (dayInMonth > 31) {
|
||||
ok = NO;
|
||||
continue; /* error, value to large */
|
||||
}
|
||||
if (dayInMonth < -31) {
|
||||
ok = NO;
|
||||
continue; /* error, value to large */
|
||||
}
|
||||
|
||||
/* adjust negative days */
|
||||
|
||||
if (dayInMonth < 0) {
|
||||
/* eg: -1 == last day in month, 30 days => 30 */
|
||||
dayInMonth = 32 - dayInMonth /* because we count from 1 */;
|
||||
}
|
||||
|
||||
(*daySet)[dayInMonth] = YES;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static inline unsigned iCalDoWForNSDoW(int dow) {
|
||||
switch (dow) {
|
||||
case 0: return iCalWeekDaySunday;
|
||||
case 1: return iCalWeekDayMonday;
|
||||
case 2: return iCalWeekDayTuesday;
|
||||
case 3: return iCalWeekDayWednesday;
|
||||
case 4: return iCalWeekDayThursday;
|
||||
case 5: return iCalWeekDayFriday;
|
||||
case 6: return iCalWeekDaySaturday;
|
||||
case 7: return iCalWeekDaySunday;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if HEAVY_DEBUG
|
||||
static NSString *dowEN[8] = {
|
||||
@"SU", @"MO", @"TU", @"WE", @"TH", @"FR", @"SA", @"SU-"
|
||||
};
|
||||
#endif
|
||||
|
||||
static void NGMonthDaySet_fillWithByDayX(NGMonthDaySet *daySet,
|
||||
unsigned dayMask,
|
||||
unsigned firstDoWInMonth,
|
||||
unsigned numberOfDaysInMonth,
|
||||
int occurrence1)
|
||||
{
|
||||
// TODO: this is called 'X' because the API doesn't allow for full iCalendar
|
||||
// functionality. The daymask must be a list of occurence+dow
|
||||
register unsigned dayInMonth;
|
||||
register int dow; /* current day of the week */
|
||||
int occurrences[7] = { 0, 0, 0, 0, 0, 0, 0 } ;
|
||||
|
||||
NGMonthDaySet_clear(daySet);
|
||||
|
||||
if (occurrence1 >= 0) {
|
||||
for (dayInMonth = 1, dow = firstDoWInMonth; dayInMonth<=31; dayInMonth++) {
|
||||
// TODO: complete me
|
||||
|
||||
if (dayMask & iCalDoWForNSDoW(dow)) {
|
||||
if (occurrence1 == 0)
|
||||
(*daySet)[dayInMonth] = YES;
|
||||
else { /* occurrence1 > 0 */
|
||||
occurrences[dow] = occurrences[dow] + 1;
|
||||
|
||||
if (occurrences[dow] == occurrence1)
|
||||
(*daySet)[dayInMonth] = YES;
|
||||
}
|
||||
}
|
||||
|
||||
dow = (dow == 6 /* Sat */) ? 0 /* Sun */ : (dow + 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int lastDoWInMonthSet;
|
||||
|
||||
/* get the last dow in the set (not necessarily the month!) */
|
||||
for (dayInMonth = 1, dow = firstDoWInMonth;
|
||||
dayInMonth < numberOfDaysInMonth;dayInMonth++)
|
||||
dow = (dow == 6 /* Sat */) ? 0 /* Sun */ : (dow + 1);
|
||||
lastDoWInMonthSet = dow;
|
||||
|
||||
#if HEAVY_DEBUG
|
||||
NSLog(@"LAST DOW IN SET: %i / %@",
|
||||
lastDoWInMonthSet, dowEN[lastDoWInMonthSet]);
|
||||
#endif
|
||||
/* start at the end of the set */
|
||||
for (dayInMonth = numberOfDaysInMonth, dow = lastDoWInMonthSet;
|
||||
dayInMonth >= 1; dayInMonth--) {
|
||||
// TODO: complete me
|
||||
|
||||
#if HEAVY_DEBUG
|
||||
NSLog(@" CHECK day-of-month %02i, "
|
||||
@" dow=%i/%@ (first=%i/%@, last=%i/%@)",
|
||||
dayInMonth,
|
||||
dow, dowEN[dow],
|
||||
firstDoWInMonth, dowEN[firstDoWInMonth],
|
||||
lastDoWInMonthSet, dowEN[lastDoWInMonthSet]
|
||||
);
|
||||
#endif
|
||||
|
||||
if (dayMask & iCalDoWForNSDoW(dow)) {
|
||||
occurrences[dow] = occurrences[dow] + 1;
|
||||
#if HEAVY_DEBUG
|
||||
NSLog(@" MATCH %i/%@ count: %i occurences=%i",
|
||||
dow, dowEN[dow], occurrences[dow], occurrence1);
|
||||
#endif
|
||||
|
||||
if (occurrences[dow] == -occurrence1) {
|
||||
#if HEAVY_DEBUG
|
||||
NSLog(@" COUNT MATCH");
|
||||
#endif
|
||||
(*daySet)[dayInMonth] = YES;
|
||||
}
|
||||
}
|
||||
|
||||
dow = (dow == 0 /* Sun */) ? 6 /* Sat */ : (dow - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)_addInstanceWithStartDate:(NSCalendarDate *)_startDate
|
||||
limitDate:(NSCalendarDate *)_until
|
||||
limitRange:(NGCalendarDateRange *)_r
|
||||
toArray:(NSMutableArray *)_ranges
|
||||
{
|
||||
NGCalendarDateRange *r;
|
||||
NSCalendarDate *end;
|
||||
|
||||
/* check whether we are still in the limits */
|
||||
|
||||
// TODO: I think we should check in here whether we succeeded the
|
||||
// repeatCount. Currently we precalculate that info in the
|
||||
// -lastInstanceStartDate method.
|
||||
if (_until != nil) {
|
||||
/* Note: the 'until' in the rrule is inclusive as per spec */
|
||||
if ([_until compare:_startDate] == NSOrderedAscending)
|
||||
/* start after until */
|
||||
return NO; /* Note: we assume that the algorithm is sequential */
|
||||
}
|
||||
|
||||
/* create end date */
|
||||
|
||||
end = [_startDate addTimeInterval:[self->firstRange duration]];
|
||||
[end setTimeZone:[_startDate timeZone]];
|
||||
|
||||
/* create range and check whether its in the requested range */
|
||||
|
||||
r = [[NGCalendarDateRange alloc] initWithStartDate:_startDate endDate:end];
|
||||
if ([_r containsDateRange:r])
|
||||
[_ranges addObject:r];
|
||||
[r release]; r = nil;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r{
|
||||
/* main entry */
|
||||
// TODO: check whether this is OK for multiday-events!
|
||||
NSMutableArray *ranges;
|
||||
NSTimeZone *timeZone;
|
||||
NSCalendarDate *eventStartDate, *rStart, *rEnd, *until;
|
||||
int eventDayOfMonth;
|
||||
unsigned monthIdxInRange, numberOfMonthsInRange, interval;
|
||||
int diff;
|
||||
NGMonthSet byMonthList = { // TODO: fill from rrule, this is the default
|
||||
YES, YES, YES, YES, YES, YES,
|
||||
YES, YES, YES, YES, YES, YES
|
||||
};
|
||||
NSArray *byMonthDay = nil; // array of ints (-31..-1 and 1..31)
|
||||
NGMonthDaySet byMonthDaySet;
|
||||
|
||||
eventStartDate = [self->firstRange startDate];
|
||||
eventDayOfMonth = [eventStartDate dayOfMonth];
|
||||
timeZone = [eventStartDate timeZone];
|
||||
rStart = [_r startDate];
|
||||
rEnd = [_r endDate];
|
||||
interval = [self->rrule repeatInterval];
|
||||
until = [self lastInstanceStartDate]; // TODO: maybe replace
|
||||
byMonthDay = [self->rrule byMonthDay];
|
||||
|
||||
|
||||
/* check whether the range to be processed is beyond the 'until' date */
|
||||
|
||||
if (until != nil) {
|
||||
if ([until compare:rStart] == NSOrderedAscending) /* until before start */
|
||||
return nil;
|
||||
if ([until compare:rEnd] == NSOrderedDescending) /* end before until */
|
||||
rEnd = until; // TODO: why is that? end is _before_ until?
|
||||
}
|
||||
|
||||
|
||||
/* precalculate month days (same for all instances) */
|
||||
|
||||
if (byMonthDay != nil)
|
||||
NGMonthDaySet_fillWithByMonthDay(&byMonthDaySet, byMonthDay);
|
||||
|
||||
|
||||
// TODO: I think the 'diff' is to skip recurrence which are before the
|
||||
// requested range. Not sure whether this is actually possible, eg
|
||||
// the repeatCount must be processed from the start.
|
||||
diff = [eventStartDate monthsBetweenDate:rStart];
|
||||
if ((diff != 0) && [rStart compare:eventStartDate] == NSOrderedAscending)
|
||||
diff = -diff;
|
||||
|
||||
numberOfMonthsInRange = [rStart monthsBetweenDate:rEnd] + 1;
|
||||
ranges = [NSMutableArray arrayWithCapacity:numberOfMonthsInRange];
|
||||
|
||||
/*
|
||||
Note: we do not add 'eventStartDate', this is intentional, the event date
|
||||
itself is _not_ necessarily part of the sequence, eg with monthly
|
||||
byday recurrences.
|
||||
*/
|
||||
|
||||
for (monthIdxInRange = 0; monthIdxInRange < numberOfMonthsInRange;
|
||||
monthIdxInRange++) {
|
||||
NSCalendarDate *cursor;
|
||||
unsigned numDaysInMonth;
|
||||
int monthIdxInRecurrence, dom;
|
||||
NGMonthDaySet monthDays;
|
||||
BOOL didByFill, doCont;
|
||||
|
||||
monthIdxInRecurrence = diff + monthIdxInRange;
|
||||
|
||||
if (monthIdxInRecurrence < 0)
|
||||
continue;
|
||||
|
||||
/* first check whether we are in the interval */
|
||||
|
||||
if ((monthIdxInRecurrence % interval) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
Then the sequence is:
|
||||
- check whether the month is in the BYMONTH list
|
||||
*/
|
||||
|
||||
cursor = [eventStartDate dateByAddingYears:0
|
||||
months:(diff + monthIdxInRange)
|
||||
days:0];
|
||||
[cursor setTimeZone:timeZone];
|
||||
numDaysInMonth = [cursor numberOfDaysInMonth];
|
||||
|
||||
|
||||
/* check whether we match the bymonth specification */
|
||||
|
||||
if (!byMonthList[[cursor monthOfYear] - 1])
|
||||
continue;
|
||||
|
||||
|
||||
/* check 'day level' byXYZ rules */
|
||||
|
||||
didByFill = NO;
|
||||
|
||||
if (byMonthDay != nil) { /* list of days in the month */
|
||||
NGMonthDaySet_copyOrUnion(&monthDays, &byMonthDaySet, !didByFill);
|
||||
didByFill = YES;
|
||||
}
|
||||
|
||||
if ([self->rrule byDayMask] != 0) { // TODO: replace the mask with an array
|
||||
NGMonthDaySet ruleset;
|
||||
unsigned firstDoWInMonth;
|
||||
|
||||
firstDoWInMonth = [[cursor firstDayOfMonth] dayOfWeek];
|
||||
|
||||
NGMonthDaySet_fillWithByDayX(&ruleset,
|
||||
[self->rrule byDayMask],
|
||||
firstDoWInMonth,
|
||||
[cursor numberOfDaysInMonth],
|
||||
[self->rrule byDayOccurence1]);
|
||||
NGMonthDaySet_copyOrUnion(&monthDays, &ruleset, !didByFill);
|
||||
didByFill = YES;
|
||||
}
|
||||
|
||||
if (!didByFill) {
|
||||
/* no rules applied, take the dayOfMonth of the startDate */
|
||||
NGMonthDaySet_clear(&monthDays);
|
||||
monthDays[eventDayOfMonth] = YES;
|
||||
}
|
||||
|
||||
// TODO: add processing of byhour/byminute/bysecond etc
|
||||
|
||||
for (dom = 1, doCont = YES; dom <= numDaysInMonth && doCont; dom++) {
|
||||
NSCalendarDate *start;
|
||||
|
||||
if (!monthDays[dom])
|
||||
continue;
|
||||
|
||||
if (eventDayOfMonth == dom)
|
||||
start = cursor;
|
||||
else {
|
||||
start = [cursor dateByAddingYears:0 months:0
|
||||
days:(dom - eventDayOfMonth)];
|
||||
}
|
||||
|
||||
doCont = [self _addInstanceWithStartDate:start
|
||||
limitDate:until
|
||||
limitRange:_r
|
||||
toArray:ranges];
|
||||
}
|
||||
if (!doCont) break; /* reached some limit */
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
- (NSCalendarDate *)lastInstanceStartDate {
|
||||
if ([self->rrule repeatCount] > 0) {
|
||||
NSCalendarDate *until;
|
||||
unsigned months, interval;
|
||||
|
||||
interval = [self->rrule repeatInterval];
|
||||
months = [self->rrule repeatCount] - 1 /* the first counts as one! */;
|
||||
|
||||
if (interval > 0)
|
||||
months *= interval;
|
||||
|
||||
until = [[self->firstRange startDate] dateByAddingYears:0
|
||||
months:months
|
||||
days:0];
|
||||
return until;
|
||||
}
|
||||
return [super lastInstanceStartDate];
|
||||
}
|
||||
|
||||
@end /* iCalMonthlyRecurrenceCalculator */
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* WAS: class being obsoleted !! */
|
||||
|
||||
#ifndef __NGiCal_iCalObject_H__
|
||||
#define __NGiCal_iCalObject_H__
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
#import <Foundation/NSDate.h>
|
||||
|
||||
/*
|
||||
iCalObject
|
||||
|
||||
A common base class for all iCal objects. Does some patches on key-value
|
||||
coding.
|
||||
*/
|
||||
|
||||
@class NSTimeZone;
|
||||
|
||||
@interface iCalObject : NSObject <NSCopying>
|
||||
{
|
||||
}
|
||||
|
||||
// what shall we take, if no timeZone is specified in dateValues
|
||||
+ (void)setICalDefaultTimeZone:(NSTimeZone *)_timeZone;
|
||||
+ (NSTimeZone *)iCalDefaultTimeZone;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
||||
#endif /* __NGiCal_iCalObject_H__ */
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalObject.h"
|
||||
#include "common.h"
|
||||
|
||||
@implementation iCalObject
|
||||
|
||||
+ (int)version {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// what shall we take, if no timeZone is specified in dateValues
|
||||
static NSTimeZone *defTZ = nil;
|
||||
+ (void)setICalDefaultTimeZone:(NSTimeZone *)_timeZone {
|
||||
ASSIGNCOPY(defTZ,_timeZone);
|
||||
}
|
||||
+ (NSTimeZone *)iCalDefaultTimeZone {
|
||||
return defTZ;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* NSCopying */
|
||||
|
||||
- (id)copyWithZone:(NSZone *)_zone {
|
||||
iCalObject *new;
|
||||
|
||||
new = [[[self class] allocWithZone:_zone] init];
|
||||
return new;
|
||||
}
|
||||
|
||||
/* KVC */
|
||||
|
||||
- (void)takeValue:(id)_value forXKey:(id)_key {
|
||||
/* extended keys are ignored by default */
|
||||
}
|
||||
|
||||
- (void)handleTakeValue:(id)_value forUnboundKey:(NSString *)_key {
|
||||
if ([_key hasPrefix:@"X-"]) {
|
||||
[self takeValue:_value forXKey:_key];
|
||||
}
|
||||
else {
|
||||
NSLog(@"0x%08x[%@]: ignoring attempt to set unbound key '%@'",
|
||||
self, NSStringFromClass([self class]), _key);
|
||||
}
|
||||
}
|
||||
|
||||
@end /* iCalObject */
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalPerson_H__
|
||||
#define __NGCards_iCalPerson_H__
|
||||
|
||||
#import "CardElement.h"
|
||||
|
||||
typedef enum {
|
||||
iCalPersonPartStatNeedsAction = 0, /* NEEDS-ACTION (DEFAULT) */
|
||||
iCalPersonPartStatAccepted = 1, /* ACCEPTED */
|
||||
iCalPersonPartStatDeclined = 2, /* DECLINED */
|
||||
/* up to here defined for VJOURNAL */
|
||||
iCalPersonPartStatTentative = 3, /* TENTATIVE */
|
||||
iCalPersonPartStatDelegated = 4, /* DELEGATED */
|
||||
/* up to here defined for VEVENT */
|
||||
iCalPersonPartStatCompleted = 5, /* COMPLETED */
|
||||
iCalPersonPartStatInProcess = 6, /* IN-PROCESS */
|
||||
/* up to there defined for VTODO */
|
||||
|
||||
/* these are also defined for VJOURNAL, VEVENT and VTODO */
|
||||
iCalPersonPartStatExperimental = 7, /* x-name */
|
||||
iCalPersonPartStatOther = 8 /* iana-token */
|
||||
} iCalPersonPartStat;
|
||||
|
||||
@interface iCalPerson : CardElement
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void)setCn:(NSString *)_s;
|
||||
- (NSString *)cn;
|
||||
- (NSString *)cnWithoutQuotes;
|
||||
|
||||
- (void)setEmail:(NSString *)_s;
|
||||
- (NSString *)email;
|
||||
- (NSString *)rfc822Email; /* email without 'mailto:' prefix */
|
||||
|
||||
- (void)setRsvp:(NSString *)_s;
|
||||
- (NSString *)rsvp;
|
||||
|
||||
// - (void)setXuid:(NSString *)_s;
|
||||
// - (NSString *)xuid;
|
||||
|
||||
- (void)setRole:(NSString *)_s;
|
||||
- (NSString *)role;
|
||||
|
||||
- (void)setPartStat:(NSString *)_s;
|
||||
- (NSString *)partStat;
|
||||
- (NSString *)partStatWithDefault;
|
||||
|
||||
- (void)setParticipationStatus:(iCalPersonPartStat)_status;
|
||||
- (iCalPersonPartStat)participationStatus;
|
||||
|
||||
- (BOOL)isEqualToPerson:(iCalPerson *)_other;
|
||||
- (BOOL)hasSameEmailAddress:(iCalPerson *)_other;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalPerson_H__ */
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalPerson.h"
|
||||
#include "common.h"
|
||||
|
||||
@implementation iCalPerson
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setCn: (NSString *) _s
|
||||
{
|
||||
[self setValue: 0 ofAttribute: @"cn" to: _s];
|
||||
}
|
||||
|
||||
- (NSString *) cn
|
||||
{
|
||||
return [self value: 0 ofAttribute: @"cn"];
|
||||
}
|
||||
|
||||
- (NSString *) cnWithoutQuotes
|
||||
{
|
||||
/* remove quotes around a CN */
|
||||
NSString *_cn;
|
||||
|
||||
_cn = [self cn];
|
||||
if ([_cn length] <= 2)
|
||||
return _cn;
|
||||
if ([_cn characterAtIndex:0] != '"')
|
||||
return _cn;
|
||||
if (![_cn hasSuffix:@"\""])
|
||||
return _cn;
|
||||
|
||||
return [_cn substringWithRange:NSMakeRange(1, [_cn length] - 2)];
|
||||
}
|
||||
|
||||
- (void) setEmail: (NSString *)_s
|
||||
{
|
||||
[self setValue: 0
|
||||
to: [NSString stringWithFormat: @"MAILTO:%@", _s]];
|
||||
}
|
||||
|
||||
- (NSString *) email
|
||||
{
|
||||
return [self value: 0];
|
||||
}
|
||||
|
||||
- (NSString *) rfc822Email
|
||||
{
|
||||
NSString *_email;
|
||||
unsigned idx;
|
||||
|
||||
_email = [self email];
|
||||
idx = NSMaxRange([_email rangeOfString:@":"]);
|
||||
|
||||
if ((idx > 0) && ([_email length] > idx))
|
||||
return [_email substringFromIndex:idx];
|
||||
|
||||
return _email;
|
||||
}
|
||||
|
||||
- (void) setRsvp: (NSString *) _s
|
||||
{
|
||||
[self setValue: 0 ofAttribute: @"rsvp" to: _s];
|
||||
}
|
||||
|
||||
- (NSString *) rsvp
|
||||
{
|
||||
return [self value: 0 ofAttribute: @"rsvp"];
|
||||
}
|
||||
|
||||
// - (void)setXuid:(NSString *)_s {
|
||||
// ASSIGNCOPY(self->xuid, _s);
|
||||
// }
|
||||
// - (NSString *)xuid {
|
||||
// return self->xuid;
|
||||
// }
|
||||
|
||||
- (void)setRole:(NSString *)_s
|
||||
{
|
||||
[self setValue: 0 ofAttribute: @"role" to: _s];
|
||||
}
|
||||
|
||||
- (NSString *) role
|
||||
{
|
||||
return [self value: 0 ofAttribute: @"role"];
|
||||
}
|
||||
|
||||
- (void)setPartStat:(NSString *)_s
|
||||
{
|
||||
[self setValue: 0 ofAttribute: @"partstat" to: _s];
|
||||
}
|
||||
|
||||
- (NSString *) partStat
|
||||
{
|
||||
return [self value: 0 ofAttribute: @"partstat"];
|
||||
}
|
||||
|
||||
- (NSString *) partStatWithDefault
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [self partStat];
|
||||
if ([s length] > 0)
|
||||
return s;
|
||||
|
||||
return @"NEEDS-ACTION";
|
||||
}
|
||||
|
||||
- (void) setParticipationStatus: (iCalPersonPartStat) _status
|
||||
{
|
||||
NSString *stat;
|
||||
|
||||
switch (_status) {
|
||||
case iCalPersonPartStatAccepted:
|
||||
stat = @"ACCEPTED";
|
||||
break;
|
||||
case iCalPersonPartStatDeclined:
|
||||
stat = @"DECLINED";
|
||||
break;
|
||||
case iCalPersonPartStatTentative:
|
||||
stat = @"TENTATIVE";
|
||||
break;
|
||||
case iCalPersonPartStatDelegated:
|
||||
stat = @"DELEGATED";
|
||||
break;
|
||||
case iCalPersonPartStatCompleted:
|
||||
stat = @"COMPLETED";
|
||||
break;
|
||||
case iCalPersonPartStatInProcess:
|
||||
stat = @"IN-PROCESS";
|
||||
break;
|
||||
case iCalPersonPartStatExperimental:
|
||||
case iCalPersonPartStatOther:
|
||||
// [NSException raise:NSInternalInconsistencyException
|
||||
// format:@"Attempt to set meaningless "
|
||||
// @"participationStatus (%d)!", _status];
|
||||
stat = nil; /* keep compiler happy */
|
||||
break;
|
||||
default:
|
||||
stat = @"NEEDS-ACTION";
|
||||
break;
|
||||
}
|
||||
if (stat)
|
||||
[self setPartStat:stat];
|
||||
}
|
||||
|
||||
- (iCalPersonPartStat)participationStatus {
|
||||
NSString *stat;
|
||||
|
||||
stat = [[self partStat] uppercaseString];
|
||||
if (![stat length] || [stat isEqualToString:@"NEEDS-ACTION"])
|
||||
return iCalPersonPartStatNeedsAction;
|
||||
else if ([stat isEqualToString:@"ACCEPTED"])
|
||||
return iCalPersonPartStatAccepted;
|
||||
else if ([stat isEqualToString:@"DECLINED"])
|
||||
return iCalPersonPartStatDeclined;
|
||||
else if ([stat isEqualToString:@"TENTATIVE"])
|
||||
return iCalPersonPartStatTentative;
|
||||
else if ([stat isEqualToString:@"DELEGATED"])
|
||||
return iCalPersonPartStatDelegated;
|
||||
else if ([stat isEqualToString:@"COMPLETED"])
|
||||
return iCalPersonPartStatCompleted;
|
||||
else if ([stat isEqualToString:@"IN-PROCESS"])
|
||||
return iCalPersonPartStatInProcess;
|
||||
else if ([stat hasPrefix:@"X-"])
|
||||
return iCalPersonPartStatExperimental;
|
||||
return iCalPersonPartStatOther;
|
||||
}
|
||||
|
||||
|
||||
/* comparison */
|
||||
|
||||
- (unsigned)hash {
|
||||
if([self email])
|
||||
return [[self email] hash];
|
||||
return [super hash];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)_other {
|
||||
if(_other == nil)
|
||||
return NO;
|
||||
if([_other class] != self->isa)
|
||||
return NO;
|
||||
if([_other hash] != [self hash])
|
||||
return NO;
|
||||
return [self isEqualToPerson:_other];
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToPerson:(iCalPerson *)_other {
|
||||
if(![self hasSameEmailAddress:_other])
|
||||
return NO;
|
||||
if(!IS_EQUAL([self cn], [_other cn], isEqualToString:))
|
||||
return NO;
|
||||
if(!IS_EQUAL([self rsvp], [_other rsvp], isEqualToString:))
|
||||
return NO;
|
||||
if(!IS_EQUAL([self partStat], [_other partStat], isEqualToString:))
|
||||
return NO;
|
||||
if(!IS_EQUAL([self role], [_other role], isEqualToString:))
|
||||
return NO;
|
||||
// if(!IS_EQUAL([self xuid], [_other xuid], isEqualToString:))
|
||||
// return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)hasSameEmailAddress:(iCalPerson *)_other {
|
||||
return IS_EQUAL([[self email] lowercaseString],
|
||||
[[_other email] lowercaseString],
|
||||
isEqualToString:);
|
||||
}
|
||||
|
||||
@end /* iCalPerson */
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGiCal_iCalRecurrenceCalculator_H_
|
||||
#define __NGiCal_iCalRecurrenceCalculator_H_
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
/*
|
||||
iCalRecurrenceCalculator
|
||||
|
||||
Provides an API for performing common calculations performed in conjunction
|
||||
with iCalRecurrenceRule objects.
|
||||
|
||||
TODO: rather move this functionality to iCalRecurrenceRule?
|
||||
*/
|
||||
|
||||
@class NSArray;
|
||||
@class iCalRecurrenceRule, NGCalendarDateRange;
|
||||
|
||||
@interface iCalRecurrenceCalculator : NSObject
|
||||
{
|
||||
NGCalendarDateRange *firstRange;
|
||||
iCalRecurrenceRule *rrule;
|
||||
}
|
||||
|
||||
+ (NSArray *)
|
||||
recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *) _r
|
||||
firstInstanceCalendarDateRange: (NGCalendarDateRange *) _fir
|
||||
recurrenceRules: (NSArray *) _rRules
|
||||
exceptionRules: (NSArray *) _exRules
|
||||
exceptionDates: (NSArray *) _exDates;
|
||||
|
||||
+ (id) recurrenceCalculatorForRecurrenceRule: (iCalRecurrenceRule *) _rrule
|
||||
withFirstInstanceCalendarDateRange: (NGCalendarDateRange *) _range;
|
||||
|
||||
- (id) initWithRecurrenceRule: (iCalRecurrenceRule *) _rrule
|
||||
firstInstanceCalendarDateRange: (NGCalendarDateRange *) _range;
|
||||
|
||||
- (NSArray *)
|
||||
recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *)_r;
|
||||
- (BOOL) doesRecurrWithinCalendarDateRange: (NGCalendarDateRange *) _range;
|
||||
|
||||
- (NGCalendarDateRange *) firstInstanceCalendarDateRange;
|
||||
- (NGCalendarDateRange *) lastInstanceCalendarDateRange; /* might be nil */
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_iCalRecurrenceCalculator_H_ */
|
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalRecurrenceCalculator.h"
|
||||
#include <NGExtensions/NGCalendarDateRange.h>
|
||||
#include "iCalRecurrenceRule.h"
|
||||
#include "NSCalendarDate+ICal.h"
|
||||
#include "common.h"
|
||||
|
||||
/* class cluster */
|
||||
|
||||
|
||||
/* Private */
|
||||
|
||||
@interface iCalRecurrenceCalculator (PrivateAPI)
|
||||
- (NSCalendarDate *)lastInstanceStartDate;
|
||||
|
||||
- (unsigned)offsetFromSundayForJulianNumber:(long)_jn;
|
||||
- (unsigned)offsetFromSundayForWeekDay:(iCalWeekDay)_weekDay;
|
||||
- (unsigned)offsetFromSundayForCurrentWeekStart;
|
||||
|
||||
- (iCalWeekDay)weekDayForJulianNumber:(long)_jn;
|
||||
@end
|
||||
|
||||
@implementation iCalRecurrenceCalculator
|
||||
|
||||
static Class NSCalendarDateClass = Nil;
|
||||
static Class iCalRecurrenceRuleClass = Nil;
|
||||
static Class dailyCalcClass = Nil;
|
||||
static Class weeklyCalcClass = Nil;
|
||||
static Class monthlyCalcClass = Nil;
|
||||
static Class yearlyCalcClass = Nil;
|
||||
|
||||
+ (void)initialize {
|
||||
static BOOL didInit = NO;
|
||||
|
||||
if (didInit) return;
|
||||
didInit = YES;
|
||||
|
||||
NSCalendarDateClass = [NSCalendarDate class];
|
||||
iCalRecurrenceRuleClass = [iCalRecurrenceRule class];
|
||||
|
||||
dailyCalcClass = NSClassFromString(@"iCalDailyRecurrenceCalculator");
|
||||
weeklyCalcClass = NSClassFromString(@"iCalWeeklyRecurrenceCalculator");
|
||||
monthlyCalcClass = NSClassFromString(@"iCalMonthlyRecurrenceCalculator");
|
||||
yearlyCalcClass = NSClassFromString(@"iCalYearlyRecurrenceCalculator");
|
||||
}
|
||||
|
||||
/* factory */
|
||||
|
||||
+ (id)recurrenceCalculatorForRecurrenceRule:(iCalRecurrenceRule *)_rrule
|
||||
withFirstInstanceCalendarDateRange:(NGCalendarDateRange *)_range
|
||||
{
|
||||
return [[[self alloc] initWithRecurrenceRule:_rrule
|
||||
firstInstanceCalendarDateRange:_range] autorelease];
|
||||
}
|
||||
|
||||
/* complex calculation convenience */
|
||||
|
||||
+ (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
|
||||
firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir
|
||||
recurrenceRules:(NSArray *)_rRules
|
||||
exceptionRules:(NSArray *)_exRules
|
||||
exceptionDates:(NSArray *)_exDates
|
||||
{
|
||||
id rule;
|
||||
iCalRecurrenceCalculator *calc;
|
||||
NSMutableArray *ranges;
|
||||
NSMutableArray *exDates;
|
||||
unsigned i, count, rCount;
|
||||
|
||||
ranges = [NSMutableArray arrayWithCapacity:64];
|
||||
|
||||
for (i = 0, count = [_rRules count]; i < count; i++) {
|
||||
NSArray *rs;
|
||||
|
||||
rule = [_rRules objectAtIndex:i];
|
||||
if (![rule isKindOfClass:iCalRecurrenceRuleClass])
|
||||
rule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation:rule];
|
||||
|
||||
calc = [self recurrenceCalculatorForRecurrenceRule:rule
|
||||
withFirstInstanceCalendarDateRange:_fir];
|
||||
rs = [calc recurrenceRangesWithinCalendarDateRange:_r];
|
||||
[ranges addObjectsFromArray:rs];
|
||||
}
|
||||
|
||||
if ([ranges count] == 0)
|
||||
return nil;
|
||||
|
||||
/* test if any exceptions do match */
|
||||
|
||||
for (i = 0, count = [_exRules count]; i < count; i++) {
|
||||
NSArray *rs;
|
||||
|
||||
rule = [_exRules objectAtIndex:i];
|
||||
if (![rule isKindOfClass:iCalRecurrenceRuleClass])
|
||||
rule = [iCalRecurrenceRule recurrenceRuleWithICalRepresentation:rule];
|
||||
|
||||
calc = [self recurrenceCalculatorForRecurrenceRule:rule
|
||||
withFirstInstanceCalendarDateRange:_fir];
|
||||
rs = [calc recurrenceRangesWithinCalendarDateRange:_r];
|
||||
[ranges removeObjectsInArray:rs];
|
||||
}
|
||||
|
||||
if (![ranges isNotEmpty])
|
||||
return nil;
|
||||
|
||||
/* exception dates */
|
||||
|
||||
if ((count = [_exDates count]) == 0)
|
||||
return ranges;
|
||||
|
||||
/* sort out exDates not within range */
|
||||
|
||||
exDates = [NSMutableArray arrayWithCapacity:count];
|
||||
for (i = 0; i < count; i++) {
|
||||
id exDate;
|
||||
|
||||
exDate = [_exDates objectAtIndex:i];
|
||||
if (![exDate isKindOfClass:NSCalendarDateClass])
|
||||
exDate = [NSCalendarDate calendarDateWithICalRepresentation:exDate];
|
||||
|
||||
if ([_r containsDate:exDate])
|
||||
[exDates addObject:exDate];
|
||||
}
|
||||
|
||||
/* remove matching exDates from ranges */
|
||||
|
||||
if ((count = [exDates count]) == 0)
|
||||
return ranges;
|
||||
|
||||
for (i = 0, rCount = [ranges count]; i < count; i++) {
|
||||
NSCalendarDate *exDate;
|
||||
NGCalendarDateRange *r;
|
||||
unsigned k;
|
||||
|
||||
exDate = [exDates objectAtIndex:i];
|
||||
for (k = 0; k < rCount; k++) {
|
||||
unsigned rIdx;
|
||||
|
||||
rIdx = (rCount - k) - 1;
|
||||
r = [ranges objectAtIndex:rIdx];
|
||||
if ([r containsDate:exDate]) {
|
||||
[ranges removeObjectAtIndex:rIdx];
|
||||
rCount--;
|
||||
break; /* this is safe because we know that ranges don't overlap */
|
||||
}
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
|
||||
/* init */
|
||||
|
||||
- (id)initWithRecurrenceRule:(iCalRecurrenceRule *)_rrule
|
||||
firstInstanceCalendarDateRange:(NGCalendarDateRange *)_range
|
||||
{
|
||||
iCalRecurrenceFrequency freq;
|
||||
Class calcClass = Nil;
|
||||
|
||||
freq = [_rrule frequency];
|
||||
if (freq == iCalRecurrenceFrequenceDaily)
|
||||
calcClass = dailyCalcClass;
|
||||
else if (freq == iCalRecurrenceFrequenceWeekly)
|
||||
calcClass = weeklyCalcClass;
|
||||
else if (freq == iCalRecurrenceFrequenceMonthly)
|
||||
calcClass = monthlyCalcClass;
|
||||
else if (freq == iCalRecurrenceFrequenceYearly)
|
||||
calcClass = yearlyCalcClass;
|
||||
else {
|
||||
[self errorWithFormat:@"unsupported rrule frequency: %@", _rrule];
|
||||
calcClass = Nil;
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
[self autorelease]; // TODO: why autorelease?
|
||||
if (calcClass == Nil)
|
||||
return nil;
|
||||
|
||||
if ((self = [[calcClass alloc] init]) != nil) {
|
||||
self->rrule = [_rrule retain];
|
||||
self->firstRange = [_range retain];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self->firstRange release];
|
||||
[self->rrule release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* helpers */
|
||||
|
||||
- (unsigned)offsetFromSundayForJulianNumber:(long)_jn {
|
||||
return (unsigned)((int)(_jn + 1.5)) % 7;
|
||||
}
|
||||
|
||||
- (unsigned)offsetFromSundayForWeekDay:(iCalWeekDay)_weekDay {
|
||||
unsigned offset;
|
||||
|
||||
switch (_weekDay) {
|
||||
case iCalWeekDaySunday: offset = 0; break;
|
||||
case iCalWeekDayMonday: offset = 1; break;
|
||||
case iCalWeekDayTuesday: offset = 2; break;
|
||||
case iCalWeekDayWednesday: offset = 3; break;
|
||||
case iCalWeekDayThursday: offset = 4; break;
|
||||
case iCalWeekDayFriday: offset = 5; break;
|
||||
case iCalWeekDaySaturday: offset = 6; break;
|
||||
default: offset = 0; break;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
- (unsigned)offsetFromSundayForCurrentWeekStart {
|
||||
return [self offsetFromSundayForWeekDay:[self->rrule weekStart]];
|
||||
}
|
||||
|
||||
- (iCalWeekDay)weekDayForJulianNumber:(long)_jn {
|
||||
unsigned day;
|
||||
iCalWeekDay weekDay;
|
||||
|
||||
day = [self offsetFromSundayForJulianNumber:_jn];
|
||||
switch (day) {
|
||||
case 0: weekDay = iCalWeekDaySunday; break;
|
||||
case 1: weekDay = iCalWeekDayMonday; break;
|
||||
case 2: weekDay = iCalWeekDayTuesday; break;
|
||||
case 3: weekDay = iCalWeekDayWednesday; break;
|
||||
case 4: weekDay = iCalWeekDayThursday; break;
|
||||
case 5: weekDay = iCalWeekDayFriday; break;
|
||||
case 6: weekDay = iCalWeekDaySaturday; break;
|
||||
default:
|
||||
[self errorWithFormat:@"got unexpected weekday: %d", day];
|
||||
weekDay = iCalWeekDaySunday;
|
||||
break; /* keep compiler happy */
|
||||
}
|
||||
return weekDay;
|
||||
}
|
||||
|
||||
/* calculation */
|
||||
|
||||
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r{
|
||||
return nil; /* subclass responsibility */
|
||||
}
|
||||
- (BOOL)doesRecurrWithinCalendarDateRange:(NGCalendarDateRange *)_range {
|
||||
NSArray *ranges;
|
||||
|
||||
ranges = [self recurrenceRangesWithinCalendarDateRange:_range];
|
||||
return (ranges == nil || [ranges count] == 0) ? NO : YES;
|
||||
}
|
||||
|
||||
- (NGCalendarDateRange *)firstInstanceCalendarDateRange {
|
||||
return self->firstRange;
|
||||
}
|
||||
|
||||
- (NGCalendarDateRange *)lastInstanceCalendarDateRange {
|
||||
NSCalendarDate *start, *end;
|
||||
|
||||
if ((start = [self lastInstanceStartDate]) == nil)
|
||||
return nil;
|
||||
|
||||
end = [start addTimeInterval:[self->firstRange duration]];
|
||||
return [NGCalendarDateRange calendarDateRangeWithStartDate:start
|
||||
endDate:end];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *)lastInstanceStartDate {
|
||||
NSCalendarDate *until;
|
||||
|
||||
/*
|
||||
NOTE: this is horribly inaccurate and doesn't even consider the use
|
||||
of repeatCount. It MUST be implemented by subclasses properly!
|
||||
However, it does the trick for SOGo 1.0 - that's why it's left here.
|
||||
*/
|
||||
if ((until = [self->rrule untilDate]) != nil)
|
||||
return until;
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end /* iCalRecurrenceCalculator */
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGiCal_iCalRecurrenceRule_H_
|
||||
#define __NGiCal_iCalRecurrenceRule_H_
|
||||
|
||||
#import "CardElement.h"
|
||||
|
||||
/*
|
||||
iCalRecurrenceRule
|
||||
|
||||
Encapsulates a (probably complex) recurrence rule by offering
|
||||
a high level API.
|
||||
|
||||
NOTE: as of now, only a very limited subset of RFC2445 is implemented.
|
||||
Please see the unit tests for what is covered.
|
||||
*/
|
||||
|
||||
// TODO: we could use string constants?
|
||||
typedef enum {
|
||||
iCalRecurrenceFrequenceSecondly = 1,
|
||||
iCalRecurrenceFrequenceMinutely = 2,
|
||||
iCalRecurrenceFrequenceHourly = 3,
|
||||
iCalRecurrenceFrequenceDaily = 4,
|
||||
iCalRecurrenceFrequenceWeekly = 5,
|
||||
iCalRecurrenceFrequenceMonthly = 6,
|
||||
iCalRecurrenceFrequenceYearly = 7,
|
||||
} iCalRecurrenceFrequency;
|
||||
|
||||
typedef enum {
|
||||
iCalWeekDayMonday = 1,
|
||||
iCalWeekDayTuesday = 2,
|
||||
iCalWeekDayWednesday = 4,
|
||||
iCalWeekDayThursday = 8,
|
||||
iCalWeekDayFriday = 16,
|
||||
iCalWeekDaySaturday = 32,
|
||||
iCalWeekDaySunday = 64,
|
||||
} iCalWeekDay;
|
||||
|
||||
@class NSString, NSCalendarDate, NGCalendarDateRange, NSArray;
|
||||
|
||||
@interface iCalRecurrenceRule : CardElement
|
||||
// {
|
||||
// iCalRecurrenceFrequency frequency;
|
||||
// int interval;
|
||||
// unsigned repeatCount;
|
||||
// NSCalendarDate *untilDate;
|
||||
// struct {
|
||||
// unsigned weekStart: 7;
|
||||
// unsigned mask: 7;
|
||||
// unsigned useOccurence:1;
|
||||
// unsigned reserved:1;
|
||||
// } byDay;
|
||||
// int byDayOccurence1;
|
||||
// NSArray *byMonthDay;
|
||||
|
||||
// NSString *rrule;
|
||||
// }
|
||||
|
||||
+ (id) recurrenceRuleWithICalRepresentation: (NSString *) _iCalRep;
|
||||
- (id) initWithString: (NSString *) _str;
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setFrequency: (iCalRecurrenceFrequency) _frequency;
|
||||
- (iCalRecurrenceFrequency) frequency;
|
||||
|
||||
- (void) setRepeatInterval: (int) _repeatInterval;
|
||||
- (int) repeatInterval;
|
||||
|
||||
- (void) setWeekStart: (iCalWeekDay) _weekStart;
|
||||
- (iCalWeekDay) weekStart;
|
||||
|
||||
- (void) setByDayMask: (unsigned int) _mask;
|
||||
- (unsigned int) byDayMask;
|
||||
- (int) byDayOccurence1;
|
||||
|
||||
- (NSArray *) byMonthDay;
|
||||
|
||||
/* count and untilDate are mutually exclusive */
|
||||
|
||||
- (void) setRepeatCount: (int) _repeatCount;
|
||||
- (int) repeatCount;
|
||||
|
||||
- (void) setUntilDate: (NSCalendarDate *) _untilDate;
|
||||
- (NSCalendarDate *) untilDate;
|
||||
|
||||
- (BOOL) isInfinite;
|
||||
|
||||
/* parse complete iCal RRULE */
|
||||
|
||||
- (void) setRrule: (NSString *) _rrule; // TODO: weird name? (better: RRule?)
|
||||
|
||||
// - (NSString *)iCalRepresentation;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGiCal_iCalRecurrenceRule_H_ */
|
|
@ -0,0 +1,631 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSException.h>
|
||||
#import <NGExtensions/NSString+Ext.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import <ctype.h>
|
||||
|
||||
#import "NSCalendarDate+NGCards.h"
|
||||
#import "NSString+NGCards.h"
|
||||
|
||||
#import "NSCalendarDate+ICal.h"
|
||||
|
||||
#import "iCalRecurrenceRule.h"
|
||||
|
||||
/*
|
||||
freq = rrFreq;
|
||||
until = rrUntil;
|
||||
count = rrCount;
|
||||
interval = rrInterval;
|
||||
bysecond = rrBySecondList;
|
||||
byminute = rrByMinuteList;
|
||||
byhour = rrByHourList;
|
||||
byday = rrByDayList;
|
||||
bymonthday = rrByMonthDayList;
|
||||
byyearday = rrByYearDayList;
|
||||
byweekno = rrByWeekNumberList;
|
||||
bymonth = rrByMonthList;
|
||||
bysetpos = rrBySetPosList;
|
||||
wkst = rrWeekStart;
|
||||
*/
|
||||
|
||||
// TODO: private API in the header file?!
|
||||
@interface iCalRecurrenceRule (PrivateAPI)
|
||||
|
||||
- (iCalWeekDay) weekDayFromICalRepresentation: (NSString *) _day;
|
||||
- (NSString *) iCalRepresentationForWeekDay: (iCalWeekDay) _waeekDay;
|
||||
- (NSString *) freq;
|
||||
- (NSString *) wkst;
|
||||
- (NSString *) byDayList;
|
||||
|
||||
// - (void)_parseRuleString:(NSString *)_rrule;
|
||||
|
||||
/* currently used by parser, should be removed (replace with an -init..) */
|
||||
- (void)setByday:(NSString *)_byDayList;
|
||||
|
||||
@end
|
||||
|
||||
@implementation iCalRecurrenceRule
|
||||
|
||||
+ (id) recurrenceRuleWithICalRepresentation: (NSString *) _iCalRep
|
||||
{
|
||||
return [self simpleElementWithTag: @"rrule" value: _iCalRep];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]) != nil)
|
||||
{
|
||||
[self setTag: @"rrule"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithString: (NSString *) _str
|
||||
{
|
||||
if ((self = [self init]))
|
||||
{
|
||||
[self setRrule: _str];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) setRrule: (NSString *) _rrule
|
||||
{
|
||||
NSEnumerator *newValues;
|
||||
NSString *newValue;
|
||||
|
||||
newValues = [[_rrule componentsSeparatedByString: @";"] objectEnumerator];
|
||||
newValue = [newValues nextObject];
|
||||
while (newValue)
|
||||
{
|
||||
[self addValue: newValue];
|
||||
newValue = [newValues nextObject];
|
||||
}
|
||||
}
|
||||
|
||||
- (iCalRecurrenceFrequency) valueForFrequency: (NSString *) value
|
||||
{
|
||||
NSString *frequency;
|
||||
iCalRecurrenceFrequency freq;
|
||||
|
||||
frequency = [value uppercaseString];
|
||||
if ([frequency isEqualToString:@"WEEKLY"])
|
||||
freq = iCalRecurrenceFrequenceWeekly;
|
||||
else if ([frequency isEqualToString:@"MONTHLY"])
|
||||
freq = iCalRecurrenceFrequenceMonthly;
|
||||
else if ([frequency isEqualToString:@"DAILY"])
|
||||
freq = iCalRecurrenceFrequenceDaily;
|
||||
else if ([frequency isEqualToString:@"YEARLY"])
|
||||
freq = iCalRecurrenceFrequenceYearly;
|
||||
else if ([frequency isEqualToString:@"HOURLY"])
|
||||
freq = iCalRecurrenceFrequenceHourly;
|
||||
else if ([frequency isEqualToString:@"MINUTELY"])
|
||||
freq = iCalRecurrenceFrequenceMinutely;
|
||||
else if ([frequency isEqualToString:@"SECONDLY"])
|
||||
freq = iCalRecurrenceFrequenceSecondly;
|
||||
else
|
||||
freq = NSNotFound;
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
- (NSString *) frequencyForValue: (iCalRecurrenceFrequency) freq
|
||||
{
|
||||
NSString *frequency;
|
||||
|
||||
switch (freq)
|
||||
{
|
||||
case iCalRecurrenceFrequenceWeekly:
|
||||
frequency = @"WEEKLY";
|
||||
break;
|
||||
case iCalRecurrenceFrequenceMonthly:
|
||||
frequency = @"MONTHLY";
|
||||
break;
|
||||
case iCalRecurrenceFrequenceDaily:
|
||||
frequency = @"DAILY";
|
||||
break;
|
||||
case iCalRecurrenceFrequenceYearly:
|
||||
frequency = @"YEARLY";
|
||||
break;
|
||||
case iCalRecurrenceFrequenceHourly:
|
||||
frequency = @"HOURLY";
|
||||
break;
|
||||
case iCalRecurrenceFrequenceMinutely:
|
||||
frequency = @"MINUTELY";
|
||||
break;
|
||||
case iCalRecurrenceFrequenceSecondly:
|
||||
frequency = @"SECONDLY";
|
||||
break;
|
||||
default:
|
||||
frequency = nil;
|
||||
}
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setFrequency: (iCalRecurrenceFrequency) _frequency
|
||||
{
|
||||
[self setNamedValue: @"freq" to: [self frequencyForValue: _frequency]];
|
||||
}
|
||||
|
||||
- (iCalRecurrenceFrequency) frequency
|
||||
{
|
||||
return [self valueForFrequency: [self namedValue: @"freq"]];
|
||||
}
|
||||
|
||||
- (void) setRepeatCount: (int) _repeatCount
|
||||
{
|
||||
[self setNamedValue: @"count"
|
||||
to: [NSString stringWithFormat: @"%d", _repeatCount]];
|
||||
}
|
||||
|
||||
- (int) repeatCount
|
||||
{
|
||||
return [[self namedValue: @"count"] intValue];
|
||||
}
|
||||
|
||||
- (void) setUntilDate: (NSCalendarDate *) _untilDate
|
||||
{
|
||||
[self setNamedValue: @"until"
|
||||
to: [_untilDate iCalFormattedDateTimeString]];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) untilDate
|
||||
{
|
||||
#warning handling of default timezone needs to be implemented
|
||||
return [[self namedValue: @"until"] asCalendarDate];
|
||||
}
|
||||
|
||||
- (void) setInterval: (NSString *) _interval
|
||||
{
|
||||
[self setNamedValue: @"interval" to: _interval];
|
||||
}
|
||||
|
||||
- (void) setCount: (NSString *) _count
|
||||
{
|
||||
[self setNamedValue: @"count" to: _count];
|
||||
}
|
||||
|
||||
- (void) setUntil: (NSString *) _until
|
||||
{
|
||||
[self setNamedValue: @"until" to: _until];
|
||||
}
|
||||
|
||||
- (void) setRepeatInterval: (int) _repeatInterval
|
||||
{
|
||||
[self setNamedValue: @"interval"
|
||||
to: [NSString stringWithFormat: @"%d", _repeatInterval]];
|
||||
}
|
||||
|
||||
- (int) repeatInterval
|
||||
{
|
||||
return [[self namedValue: @"interval"] intValue];
|
||||
}
|
||||
|
||||
- (void) setWkst: (NSString *) _weekStart
|
||||
{
|
||||
[self setNamedValue: @"wkst" to: _weekStart];
|
||||
}
|
||||
|
||||
- (NSString *) wkst
|
||||
{
|
||||
return [self namedValue: @"wkst"];
|
||||
}
|
||||
|
||||
- (void) setWeekStart: (iCalWeekDay) _weekStart
|
||||
{
|
||||
[self setWkst: [self iCalRepresentationForWeekDay: _weekStart]];
|
||||
}
|
||||
|
||||
- (iCalWeekDay) weekStart
|
||||
{
|
||||
return [self weekDayFromICalRepresentation: [self wkst]];
|
||||
}
|
||||
|
||||
- (void) setByDayMask: (unsigned) _mask
|
||||
{
|
||||
NSMutableArray *days;
|
||||
unsigned int count;
|
||||
unsigned char maskDays[] = { iCalWeekDayMonday, iCalWeekDayTuesday,
|
||||
iCalWeekDayWednesday, iCalWeekDayThursday,
|
||||
iCalWeekDayFriday, iCalWeekDaySaturday,
|
||||
iCalWeekDaySunday };
|
||||
days = [NSMutableArray arrayWithCapacity: 7];
|
||||
if (_mask)
|
||||
{
|
||||
for (count = 0; count < 7; count++)
|
||||
if (_mask & maskDays[count])
|
||||
[days addObject:
|
||||
[self iCalRepresentationForWeekDay: maskDays[count]]];
|
||||
}
|
||||
|
||||
[self setNamedValue: @"byday" to: [days componentsJoinedByString: @","]];
|
||||
}
|
||||
|
||||
- (unsigned int) byDayMask
|
||||
{
|
||||
NSArray *days;
|
||||
unsigned int mask, count, max;
|
||||
NSString *day;
|
||||
|
||||
mask = 0;
|
||||
|
||||
days = [[self namedValue: @"byday"] componentsSeparatedByString: @","];
|
||||
max = [days count];
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
day = [days objectAtIndex: count];
|
||||
day = [day substringFromIndex: [day length] - 2];
|
||||
mask |= [self weekDayFromICalRepresentation: day];
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
#warning this is fucked up
|
||||
- (int) byDayOccurence1
|
||||
{
|
||||
return 0;
|
||||
// return byDayOccurence1;
|
||||
}
|
||||
|
||||
- (NSArray *) byMonthDay
|
||||
{
|
||||
return [[self namedValue: @"bymonthday"] componentsSeparatedByString: @","];
|
||||
}
|
||||
|
||||
- (BOOL) isInfinite
|
||||
{
|
||||
return !([self repeatCount] || [self untilDate]);
|
||||
}
|
||||
|
||||
/* private */
|
||||
|
||||
- (iCalWeekDay) weekDayFromICalRepresentation: (NSString *) _day
|
||||
{
|
||||
if ([_day length] > 1) {
|
||||
/* be tolerant */
|
||||
unichar c0, c1;
|
||||
|
||||
c0 = [_day characterAtIndex:0];
|
||||
if (c0 == 'm' || c0 == 'M') return iCalWeekDayMonday;
|
||||
if (c0 == 'w' || c0 == 'W') return iCalWeekDayWednesday;
|
||||
if (c0 == 'f' || c0 == 'F') return iCalWeekDayFriday;
|
||||
|
||||
c1 = [_day characterAtIndex:1];
|
||||
if (c0 == 't' || c0 == 'T') {
|
||||
if (c1 == 'u' || c1 == 'U') return iCalWeekDayTuesday;
|
||||
if (c1 == 'h' || c1 == 'H') return iCalWeekDayThursday;
|
||||
}
|
||||
if (c0 == 's' || c0 == 'S') {
|
||||
if (c1 == 'a' || c1 == 'A') return iCalWeekDaySaturday;
|
||||
if (c1 == 'u' || c1 == 'U') return iCalWeekDaySunday;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: do not raise but rather return an error value?
|
||||
[NSException raise:NSGenericException
|
||||
format:@"Incorrect weekDay '%@' specified!", _day];
|
||||
return iCalWeekDayMonday; /* keep compiler happy */
|
||||
}
|
||||
|
||||
- (NSString *) iCalRepresentationForWeekDay: (iCalWeekDay) _weekDay
|
||||
{
|
||||
switch (_weekDay)
|
||||
{
|
||||
case iCalWeekDayMonday: return @"MO";
|
||||
case iCalWeekDayTuesday: return @"TU";
|
||||
case iCalWeekDayWednesday: return @"WE";
|
||||
case iCalWeekDayThursday: return @"TH";
|
||||
case iCalWeekDayFriday: return @"FR";
|
||||
case iCalWeekDaySaturday: return @"SA";
|
||||
case iCalWeekDaySunday: return @"SU";
|
||||
default: return @"MO"; // TODO: return error?
|
||||
}
|
||||
}
|
||||
|
||||
// - (iCalWeekDay) weekDayForiCalRepre: (NSString *) _weekDay
|
||||
// {
|
||||
// iCalWeekDay day;
|
||||
// NSString *weekDay;
|
||||
|
||||
// weekDay = [_weekDay uppercaseString];
|
||||
// if ([weekDay isEqualToString: @"TU"])
|
||||
// day = iCalWeekDayTuesday;
|
||||
// else if ([weekDay isEqualToString: @"WE"])
|
||||
// day = iCalWeekDayWednesday;
|
||||
// else if ([weekDay isEqualToString: @"TH"])
|
||||
// day = iCalWeekDayThursday;
|
||||
// else if ([weekDay isEqualToString: @"FR"])
|
||||
// day = iCalWeekDayFriday;
|
||||
// else if ([weekDay isEqualToString: @"SA"])
|
||||
// day = iCalWeekDaySaturday;
|
||||
// else if ([weekDay isEqualToString: @"SU"])
|
||||
// day = iCalWeekDaySunday;
|
||||
// else
|
||||
// day = iCalWeekDayMonday;
|
||||
|
||||
// return day;
|
||||
// }
|
||||
|
||||
// - (NSString *) wkst
|
||||
// {
|
||||
// return [self iCalRepresentationForWeekDay:byDay.weekStart];
|
||||
// }
|
||||
|
||||
/*
|
||||
TODO:
|
||||
Each BYDAY value can also be preceded by a positive (+n) or negative
|
||||
(-n) integer. If present, this indicates the nth occurrence of the
|
||||
specific day within the MONTHLY or YEARLY RRULE. For example, within
|
||||
a MONTHLY rule, +1MO (or simply 1MO) represents the first Monday
|
||||
within the month, whereas -1MO represents the last Monday of the
|
||||
month. If an integer modifier is not present, it means all days of
|
||||
this type within the specified frequency. For example, within a
|
||||
MONTHLY rule, MO represents all Mondays within the month.
|
||||
*/
|
||||
// - (NSString *) byDayList
|
||||
// {
|
||||
// NSMutableString *s;
|
||||
// unsigned dow, mask, day;
|
||||
// BOOL needsComma;
|
||||
|
||||
// s = [NSMutableString stringWithCapacity:20];
|
||||
// needsComma = NO;
|
||||
// mask = byDay.mask;
|
||||
// day = iCalWeekDayMonday;
|
||||
|
||||
// for (dow = 0 /* Sun */; dow < 7; dow++) {
|
||||
// if (mask & day) {
|
||||
// if (needsComma)
|
||||
// [s appendString:@","];
|
||||
|
||||
// if (byDay.useOccurence)
|
||||
// // Note: we only support one occurrence for all currently
|
||||
// [s appendFormat:@"%i", byDayOccurence1];
|
||||
|
||||
// [s appendString:[self iCalRepresentationForWeekDay:day]];
|
||||
// needsComma = YES;
|
||||
// }
|
||||
// day = (day << 1);
|
||||
// }
|
||||
|
||||
// return s;
|
||||
// }
|
||||
|
||||
/* parsing rrule */
|
||||
|
||||
// - (void) _parseRuleString: (NSString *) _rrule
|
||||
// {
|
||||
// // TODO: to be exact we would need a timezone to properly process the 'until'
|
||||
// // date
|
||||
// unsigned i, count;
|
||||
// NSString *pFrequency = nil;
|
||||
// NSString *pUntil = nil;
|
||||
// NSString *pCount = nil;
|
||||
// NSString *pByday = nil;
|
||||
// NSString *pBymday = nil;
|
||||
// NSString *pBysetpos = nil;
|
||||
// NSString *pInterval = nil;
|
||||
|
||||
// for (i = 0, count = [values count]; i < count; i++) {
|
||||
// NSString *prop, *key, *value;
|
||||
// NSRange r;
|
||||
// NSString **vHolder = NULL;
|
||||
|
||||
// prop = [values objectAtIndex:i];
|
||||
// r = [prop rangeOfString:@"="];
|
||||
// if (r.length > 0) {
|
||||
// key = [prop substringToIndex:r.location];
|
||||
// value = [prop substringFromIndex:NSMaxRange(r)];
|
||||
// }
|
||||
// else {
|
||||
// key = prop;
|
||||
// value = nil;
|
||||
// }
|
||||
|
||||
// key = [[key stringByTrimmingSpaces] lowercaseString];
|
||||
// if (![key isNotEmpty]) {
|
||||
// [self errorWithFormat:@"empty component in rrule: %@", _rrule];
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// vHolder = NULL;
|
||||
// switch ([key characterAtIndex:0]) {
|
||||
// case 'b':
|
||||
// if ([key isEqualToString:@"byday"]) { vHolder = &pByday; break; }
|
||||
// if ([key isEqualToString:@"bymonthday"]) { vHolder = &pBymday; break; }
|
||||
// if ([key isEqualToString:@"bysetpos"]) { vHolder = &pBysetpos; break; }
|
||||
// break;
|
||||
// case 'c':
|
||||
// if ([key isEqualToString:@"count"]) { vHolder = &pCount; break; }
|
||||
// break;
|
||||
// case 'f':
|
||||
// if ([key isEqualToString:@"freq"]) { vHolder = &pFrequency; break; }
|
||||
// break;
|
||||
// case 'i':
|
||||
// if ([key isEqualToString:@"interval"]) { vHolder = &pInterval; break; }
|
||||
// break;
|
||||
// case 'u':
|
||||
// if ([key isEqualToString:@"until"]) { vHolder = &pUntil; break; }
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
|
||||
// if (vHolder != NULL) {
|
||||
// if ([*vHolder isNotEmpty])
|
||||
// [self errorWithFormat:@"more than one '%@' in: %@", key, _rrule];
|
||||
// else
|
||||
// *vHolder = [value copy];
|
||||
// }
|
||||
// else {
|
||||
// // TODO: we should just parse known keys and put remainders into a
|
||||
// // separate dictionary
|
||||
// [self logWithFormat:@"TODO: add explicit support for key: %@", key];
|
||||
// [self takeValue:value forKey:key];
|
||||
// }
|
||||
// }
|
||||
|
||||
// /* parse and fill individual values */
|
||||
// // TODO: this method should be a class method and create a new rrule object
|
||||
|
||||
// if ([pFrequency isNotEmpty])
|
||||
// [self setNamedValue: @"FREQ" to: pFrequency];
|
||||
// else
|
||||
// [self errorWithFormat:@"rrule contains no frequency: '%@'", _rrule];
|
||||
// [pFrequency release]; pFrequency = nil;
|
||||
|
||||
// if (pInterval != nil)
|
||||
// interval = [pInterval intValue];
|
||||
// [pInterval release]; pInterval = nil;
|
||||
|
||||
// // TODO: we should parse byday in here
|
||||
// if (pByday != nil) [self setByday:pByday];
|
||||
// [pByday release]; pByday = nil;
|
||||
|
||||
// if (pBymday != nil) {
|
||||
// NSArray *t;
|
||||
|
||||
// t = [pBymday componentsSeparatedByString:@","];
|
||||
// ASSIGNCOPY(byMonthDay, t);
|
||||
// }
|
||||
// [pBymday release]; pBymday = nil;
|
||||
|
||||
// if (pBysetpos != nil)
|
||||
// // TODO: implement
|
||||
// [self errorWithFormat:@"rrule contains bysetpos, unsupported: %@", _rrule];
|
||||
// [pBysetpos release]; pBysetpos = nil;
|
||||
|
||||
// if (pUntil != nil) {
|
||||
// NSCalendarDate *pUntilDate;
|
||||
|
||||
// if (pCount != nil) {
|
||||
// [self errorWithFormat:@"rrule contains 'count' AND 'until': %@", _rrule];
|
||||
// [pCount release];
|
||||
// pCount = nil;
|
||||
// }
|
||||
|
||||
// /*
|
||||
// The spec says:
|
||||
// "If specified as a date-time value, then it MUST be specified in an
|
||||
// UTC time format."
|
||||
// TODO: we still need some object representing a 'timeless' date.
|
||||
// */
|
||||
// if (![pUntil hasSuffix:@"Z"] && [pUntil length] > 8) {
|
||||
// [self warnWithFormat:@"'until' date has no explicit UTC marker: '%@'",
|
||||
// _rrule];
|
||||
// }
|
||||
|
||||
// pUntilDate = [NSCalendarDate calendarDateWithICalRepresentation:pUntil];
|
||||
// if (pUntilDate != nil)
|
||||
// [self setUntilDate:pUntilDate];
|
||||
// else {
|
||||
// [self errorWithFormat:@"could not parse 'until' in rrule: %@",
|
||||
// _rrule];
|
||||
// }
|
||||
// }
|
||||
// [pUntil release]; pUntil = nil;
|
||||
|
||||
// if (pCount != nil)
|
||||
// [self setRepeatCount:[pCount intValue]];
|
||||
// [pCount release]; pCount = nil;
|
||||
// }
|
||||
|
||||
/* properties */
|
||||
|
||||
// - (void) setByday: (NSString *) _byDayList
|
||||
// {
|
||||
// // TODO: each day can have an associated occurence, eg:
|
||||
// // +1MO,+2TU,-9WE
|
||||
// // TODO: this should be moved to the parser
|
||||
// NSArray *days;
|
||||
// unsigned i, count;
|
||||
// NSString *iCalDay;
|
||||
// iCalWeekDay day;
|
||||
// unsigned len;
|
||||
// unichar c0;
|
||||
// int occurence;
|
||||
// int offset;
|
||||
|
||||
// /* reset mask */
|
||||
// byDay.mask = 0;
|
||||
// byDay.useOccurence = 0;
|
||||
// byDayOccurence1 = 0;
|
||||
|
||||
// days = [_byDayList componentsSeparatedByString:@","];
|
||||
// for (i = 0, count = [days count]; i < count; i++)
|
||||
// {
|
||||
// iCalDay = [days objectAtIndex:i]; // eg: MO or TU
|
||||
// if ((len = [iCalDay length]) == 0)
|
||||
// {
|
||||
// [self errorWithFormat:@"found an empty day in byday list: '%@'",
|
||||
// _byDayList];
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// c0 = [iCalDay characterAtIndex:0];
|
||||
// if (((c0 == '+' || c0 == '-') && len > 2) || (isdigit(c0) && len > 1)) {
|
||||
// occurence = [iCalDay intValue];
|
||||
|
||||
// offset = 1; /* skip occurence */
|
||||
// while (offset < len && isdigit([iCalDay characterAtIndex:offset]))
|
||||
// offset++;
|
||||
|
||||
// iCalDay = [iCalDay substringFromIndex:offset];
|
||||
|
||||
// if (byDay.useOccurence && (occurence != byDayOccurence1))
|
||||
// {
|
||||
// [self errorWithFormat:
|
||||
// @"we only supported one occurence (occ=%i,day=%@): '%@'",
|
||||
// occurence, iCalDay, _byDayList];
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// byDay.useOccurence = 1;
|
||||
// byDayOccurence1 = occurence;
|
||||
// }
|
||||
// else if (byDay.useOccurence)
|
||||
// [self errorWithFormat:
|
||||
// @"a byday occurence was specified on one day, but not on others"
|
||||
// @" (unsupported): '%@'", _byDayList];
|
||||
|
||||
// day = [self weekDayFromICalRepresentation:iCalDay];
|
||||
// byDay.mask |= day;
|
||||
// }
|
||||
// }
|
||||
|
||||
/* key/value coding */
|
||||
|
||||
- (void) handleTakeValue: (id) _value
|
||||
forUnboundKey: (NSString *)_key
|
||||
{
|
||||
[self warnWithFormat:@"Cannot handle unbound key: '%@'", _key];
|
||||
}
|
||||
|
||||
@end /* iCalRecurrenceRule */
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalRepeatableEntityObject_H_
|
||||
#define __NGCards_iCalRepeatableEntityObject_H_
|
||||
|
||||
#import "iCalEntityObject.h"
|
||||
|
||||
/*
|
||||
iCalRepeatableEntityObject
|
||||
|
||||
Specifies an iCal entity object which can bear a (possibly complex) set
|
||||
of recurrence rules and exceptions thereof. According to RFC 2445 these
|
||||
are VEVENT, VTODO and VJOURNAL.
|
||||
*/
|
||||
|
||||
@class NSMutableArray, NGCalendarDateRange;
|
||||
|
||||
@interface iCalRepeatableEntityObject : iCalEntityObject
|
||||
// {
|
||||
// NSMutableArray *rRules;
|
||||
// NSMutableArray *exRules;
|
||||
// NSMutableArray *exDates;
|
||||
// }
|
||||
|
||||
- (void)removeAllRecurrenceRules;
|
||||
- (void)addToRecurrenceRules:(id)_rrule;
|
||||
- (BOOL)hasRecurrenceRules;
|
||||
- (NSArray *)recurrenceRules;
|
||||
|
||||
- (void)removeAllExceptionRules;
|
||||
- (void)addToExceptionRules:(id)_rrule;
|
||||
- (BOOL)hasExceptionRules;
|
||||
- (NSArray *)exceptionRules;
|
||||
|
||||
- (void)removeAllExceptionDates;
|
||||
- (void)addToExceptionDates:(id)_date;
|
||||
- (BOOL)hasExceptionDates;
|
||||
- (NSArray *)exceptionDates;
|
||||
|
||||
- (BOOL)isRecurrent;
|
||||
- (BOOL)isWithinCalendarDateRange:(NGCalendarDateRange *)_range
|
||||
firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir;
|
||||
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r
|
||||
firstInstanceCalendarDateRange:(NGCalendarDateRange *)_fir;
|
||||
|
||||
/* this is the outmost bound possible, not necessarily the real last date */
|
||||
- (NSCalendarDate *)lastPossibleRecurrenceStartDateUsingFirstInstanceCalendarDateRange:(NGCalendarDateRange *)_r;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalRepeatableEntityObject_H_ */
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalRepeatableEntityObject.h"
|
||||
#include <NGExtensions/NGCalendarDateRange.h>
|
||||
#include "iCalRecurrenceRule.h"
|
||||
#include "iCalRecurrenceCalculator.h"
|
||||
#include "common.h"
|
||||
|
||||
@implementation iCalRepeatableEntityObject
|
||||
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
if ([classTag isEqualToString: @"RRULE"])
|
||||
tagClass = [iCalRecurrenceRule class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
/* Accessors */
|
||||
|
||||
- (void) removeAllRecurrenceRules
|
||||
{
|
||||
[children removeObjectsInArray: [self childrenWithTag: @"rrule"]];
|
||||
}
|
||||
|
||||
- (void) addToRecurrenceRules: (id) _rrule
|
||||
{
|
||||
[self addChild: _rrule];
|
||||
}
|
||||
|
||||
- (void) setRecurrenceRules: (NSArray *) _rrules
|
||||
{
|
||||
[children removeObjectsInArray: [self childrenWithTag: @"rrule"]];
|
||||
[self addChildren: _rrules];
|
||||
}
|
||||
|
||||
- (BOOL) hasRecurrenceRules
|
||||
{
|
||||
return ([[self childrenWithTag: @"rrule"] count] > 0);
|
||||
}
|
||||
|
||||
- (NSArray *) recurrenceRules
|
||||
{
|
||||
return [self childrenWithTag: @"rrule"];
|
||||
}
|
||||
|
||||
- (void) removeAllExceptionRules
|
||||
{
|
||||
[children removeObjectsInArray: [self childrenWithTag: @"exrule"]];
|
||||
}
|
||||
|
||||
- (void) addToExceptionRules: (id) _rrule
|
||||
{
|
||||
[self addChild: _rrule];
|
||||
}
|
||||
|
||||
- (void) setExceptionRules: (NSArray *) _rrules
|
||||
{
|
||||
[children removeObjectsInArray: [self childrenWithTag: @"exrule"]];
|
||||
[self addChildren: _rrules];
|
||||
}
|
||||
|
||||
- (BOOL) hasExceptionRules
|
||||
{
|
||||
return ([[self childrenWithTag: @"exrule"] count] > 0);
|
||||
}
|
||||
|
||||
- (NSArray *) exceptionRules
|
||||
{
|
||||
return [self childrenWithTag: @"exrule"];
|
||||
}
|
||||
|
||||
- (void) removeAllExceptionDates
|
||||
{
|
||||
[children removeObjectsInArray: [self childrenWithTag: @"exdate"]];
|
||||
}
|
||||
|
||||
- (void) addToExceptionDates: (id) _rdate
|
||||
{
|
||||
[self addChild: _rdate];
|
||||
}
|
||||
|
||||
- (void) setExceptionDates: (NSArray *) _rdates
|
||||
{
|
||||
[children removeObjectsInArray: [self childrenWithTag: @"exdate"]];
|
||||
[self addChildren: _rdates];
|
||||
}
|
||||
|
||||
- (BOOL) hasExceptionDates
|
||||
{
|
||||
return ([[self childrenWithTag: @"exdate"] count] > 0);
|
||||
}
|
||||
|
||||
- (NSArray *) exceptionDates
|
||||
{
|
||||
return [self childrenWithTag: @"exdate"];
|
||||
}
|
||||
|
||||
/* Convenience */
|
||||
|
||||
- (BOOL) isRecurrent
|
||||
{
|
||||
return [self hasRecurrenceRules];
|
||||
}
|
||||
|
||||
/* Matching */
|
||||
|
||||
- (BOOL) isWithinCalendarDateRange: (NGCalendarDateRange *) _range
|
||||
firstInstanceCalendarDateRange: (NGCalendarDateRange *) _fir
|
||||
{
|
||||
NSArray *ranges;
|
||||
|
||||
ranges = [self recurrenceRangesWithinCalendarDateRange:_range
|
||||
firstInstanceCalendarDateRange:_fir];
|
||||
return [ranges count] > 0;
|
||||
}
|
||||
|
||||
- (NSArray *) recurrenceRangesWithinCalendarDateRange: (NGCalendarDateRange *)_r
|
||||
firstInstanceCalendarDateRange: (NGCalendarDateRange *)_fir
|
||||
{
|
||||
return [iCalRecurrenceCalculator recurrenceRangesWithinCalendarDateRange: _r
|
||||
firstInstanceCalendarDateRange: _fir
|
||||
recurrenceRules: [self recurrenceRules]
|
||||
exceptionRules: [self exceptionRules]
|
||||
exceptionDates: [self exceptionDates]];
|
||||
}
|
||||
|
||||
|
||||
/* this is the outmost bound possible, not necessarily the real last date */
|
||||
- (NSCalendarDate *)
|
||||
lastPossibleRecurrenceStartDateUsingFirstInstanceCalendarDateRange: (NGCalendarDateRange *)_r
|
||||
{
|
||||
NSCalendarDate *date;
|
||||
NSEnumerator *rRules;
|
||||
iCalRecurrenceRule *rule;
|
||||
iCalRecurrenceCalculator *calc;
|
||||
NSCalendarDate *rdate;
|
||||
|
||||
date = nil;
|
||||
|
||||
rRules = [[self recurrenceRules] objectEnumerator];
|
||||
rule = [rRules nextObject];
|
||||
while (rule && ![rule isInfinite] & !date)
|
||||
{
|
||||
calc = [iCalRecurrenceCalculator
|
||||
recurrenceCalculatorForRecurrenceRule: rule
|
||||
withFirstInstanceCalendarDateRange: _r];
|
||||
rdate = [[calc lastInstanceCalendarDateRange] startDate];
|
||||
if (!date
|
||||
|| ([date compare: rdate] == NSOrderedAscending))
|
||||
date = rdate;
|
||||
else
|
||||
rule = [rRules nextObject];
|
||||
}
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,39 @@
|
|||
/* iCalTimeZone.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ICALTIMEZONE_H
|
||||
#define ICALTIMEZONE_H
|
||||
|
||||
@class NSString;
|
||||
@class NSCalendarDate;
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
@interface iCalTimeZone : CardGroup
|
||||
|
||||
- (NSString *) tzId;
|
||||
- (NSString *) dateTimeStringForDate: (NSCalendarDate *) date;
|
||||
- (NSCalendarDate *) dateForDateTimeString: (NSString *) string;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* ICALTIMEZONE_H */
|
|
@ -0,0 +1,132 @@
|
|||
/* iCalTimeZone.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
|
||||
#import "NSCalendarDate+NGCards.h"
|
||||
#import "NSString+NGCards.h"
|
||||
#import "iCalTimeZonePeriod.h"
|
||||
|
||||
#import "iCalTimeZone.h"
|
||||
|
||||
@implementation iCalTimeZone
|
||||
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
if ([classTag isEqualToString: @"STANDARD"]
|
||||
|| [classTag isEqualToString: @"DAYLIGHT"])
|
||||
tagClass = [iCalTimeZonePeriod class];
|
||||
else if ([classTag isEqualToString: @"TZID"])
|
||||
tagClass = [CardElement class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
- (void) setTzId: (NSString *) tzId
|
||||
{
|
||||
[[self uniqueChildWithTag: @"tzid"] setValue: 0 to: tzId];
|
||||
}
|
||||
|
||||
- (NSString *) tzId
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"tzid"] value: 0];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) _occurenceForPeriodNamed: (NSString *) pName
|
||||
forDate: (NSCalendarDate *) aDate
|
||||
{
|
||||
NSArray *periods;
|
||||
iCalTimeZonePeriod *period;
|
||||
NSCalendarDate *occurence;
|
||||
|
||||
periods = [self childrenWithTag: pName];
|
||||
if ([periods count])
|
||||
{
|
||||
period = (iCalTimeZonePeriod *) [periods objectAtIndex: 0];
|
||||
occurence = [period occurenceForDate: aDate];
|
||||
}
|
||||
else
|
||||
occurence = nil;
|
||||
|
||||
return occurence;
|
||||
}
|
||||
|
||||
- (iCalTimeZonePeriod *) periodForDate: (NSCalendarDate *) date
|
||||
{
|
||||
NSCalendarDate *daylightOccurence, *standardOccurence;
|
||||
iCalTimeZonePeriod *period;
|
||||
|
||||
/* FIXME, this could cause crashes when timezones are not properly
|
||||
specified, but let's say it won't happen often... */
|
||||
|
||||
daylightOccurence = [self _occurenceForPeriodNamed: @"daylight"
|
||||
forDate: date];
|
||||
standardOccurence = [self _occurenceForPeriodNamed: @"standard"
|
||||
forDate: date];
|
||||
if ([date earlierDate: daylightOccurence] == date
|
||||
|| [date earlierDate: standardOccurence] == standardOccurence)
|
||||
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"standard"];
|
||||
else
|
||||
period = (iCalTimeZonePeriod *) [self uniqueChildWithTag: @"daylight"];
|
||||
|
||||
NSLog (@"chosen period: '%@'", [period tag]);
|
||||
|
||||
return period;
|
||||
}
|
||||
|
||||
- (NSString *) dateTimeStringForDate: (NSCalendarDate *) date
|
||||
{
|
||||
NSCalendarDate *tmpDate;
|
||||
NSTimeZone *utc;
|
||||
|
||||
utc = [NSTimeZone timeZoneWithName: @"GMT"];
|
||||
tmpDate = [date copy];
|
||||
[tmpDate autorelease];
|
||||
[tmpDate setTimeZone: utc];
|
||||
tmpDate
|
||||
= [tmpDate addYear: 0 month: 0 day: 0
|
||||
hour: 0 minute: 0
|
||||
second: [[self periodForDate: date] secondsOffsetFromGMT]];
|
||||
|
||||
return [tmpDate iCalFormattedDateTimeString];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) dateForDateTimeString: (NSString *) string
|
||||
{
|
||||
NSCalendarDate *tmpDate;
|
||||
iCalTimeZonePeriod *period;
|
||||
|
||||
tmpDate = [string asCalendarDate];
|
||||
period = [self periodForDate: tmpDate];
|
||||
|
||||
return [tmpDate addYear: 0 month: 0 day: 0
|
||||
hour: 0 minute: 0
|
||||
second: -[period secondsOffsetFromGMT]];
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,35 @@
|
|||
/* iCalTimeZonePeriod.h - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef ICALTIMEZONEPERIOD_H
|
||||
#define ICALTIMEZONEPERIOD_H
|
||||
|
||||
#import "CardGroup.h"
|
||||
|
||||
@interface iCalTimeZonePeriod : CardGroup
|
||||
|
||||
- (NSCalendarDate *) occurenceForDate: (NSCalendarDate *) refDate;
|
||||
- (int) secondsOffsetFromGMT;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* ICALTIMEZONEPERIOD_H */
|
|
@ -0,0 +1,140 @@
|
|||
/* iCalTimeZonePeriod.m - this file is part of SOPE
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSCalendarDate.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "iCalDateTime.h"
|
||||
#import "iCalRecurrenceRule.h"
|
||||
#import "CardGroup+iCal.h"
|
||||
|
||||
#import "iCalTimeZonePeriod.h"
|
||||
|
||||
@implementation iCalTimeZonePeriod
|
||||
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
if ([classTag isEqualToString: @"RRULE"])
|
||||
tagClass = [iCalRecurrenceRule class];
|
||||
else if ([classTag isEqualToString: @"DTSTART"])
|
||||
tagClass = [iCalDateTime class];
|
||||
else if ([classTag isEqualToString: @"TZNAME"]
|
||||
|| [classTag isEqualToString: @"TZOFFSETFROM"]
|
||||
|| [classTag isEqualToString: @"TZOFFSETTO"])
|
||||
tagClass = [CardElement class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
- (int) _secondsOfOffset: (NSString *) offsetName
|
||||
{
|
||||
NSString *offsetTo;
|
||||
BOOL negative;
|
||||
NSRange cursor;
|
||||
unsigned int length;
|
||||
unsigned int seconds;
|
||||
|
||||
seconds = 0;
|
||||
|
||||
offsetTo = [[self uniqueChildWithTag: offsetName]
|
||||
value: 0];
|
||||
length = [offsetTo length];
|
||||
negative = [offsetTo hasPrefix: @"-"];
|
||||
if (negative)
|
||||
{
|
||||
length--;
|
||||
cursor = NSMakeRange(1, 2);
|
||||
}
|
||||
else if ([offsetTo hasPrefix: @"+"])
|
||||
{
|
||||
length--;
|
||||
cursor = NSMakeRange(1, 2);
|
||||
}
|
||||
else
|
||||
cursor = NSMakeRange(0, 2);
|
||||
|
||||
seconds = 3600 * [[offsetTo substringWithRange: cursor] intValue];
|
||||
cursor.location += 2;
|
||||
seconds += 60 * [[offsetTo substringWithRange: cursor] intValue];
|
||||
if (length == 6)
|
||||
{
|
||||
cursor.location += 2;
|
||||
seconds += [[offsetTo substringWithRange: cursor] intValue];
|
||||
}
|
||||
|
||||
return ((negative) ? -seconds : seconds);
|
||||
}
|
||||
|
||||
- (unsigned int) dayOfWeekFromRruleDay: (iCalWeekDay) day
|
||||
{
|
||||
unsigned int dayOfWeek;
|
||||
|
||||
dayOfWeek = 1;
|
||||
while (day >> dayOfWeek)
|
||||
dayOfWeek++;
|
||||
|
||||
return dayOfWeek;
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) occurenceForDate: (NSCalendarDate *) refDate;
|
||||
{
|
||||
NSCalendarDate *tmpDate;
|
||||
iCalRecurrenceRule *rrule;
|
||||
NSString *byDay;
|
||||
int dayOfWeek, dateDayOfWeek, offset, pos;
|
||||
|
||||
rrule = (iCalRecurrenceRule *) [self uniqueChildWithTag: @"rrule"];
|
||||
byDay = [rrule namedValue: @"byday"];
|
||||
dayOfWeek = [self dayOfWeekFromRruleDay: [rrule byDayMask]];
|
||||
pos = [[byDay substringToIndex: 2] intValue];
|
||||
if (!pos)
|
||||
pos = 1;
|
||||
|
||||
tmpDate = [NSCalendarDate
|
||||
dateWithYear: [refDate yearOfCommonEra]
|
||||
month: [[rrule namedValue: @"bymonth"] intValue]
|
||||
day: 1 hour: 0 minute: 0 second: 0
|
||||
timeZone: [NSTimeZone timeZoneWithName: @"GMT"]];
|
||||
tmpDate = [tmpDate addYear: 0 month: ((pos > 0) ? 0 : 1)
|
||||
day: 0 hour: 0 minute: 0
|
||||
second: -[self _secondsOfOffset: @"tzoffsetfrom"]];
|
||||
dateDayOfWeek = [tmpDate dayOfWeek];
|
||||
offset = (dayOfWeek - dateDayOfWeek);
|
||||
if (pos > 0 && offset < 0)
|
||||
offset += 7;
|
||||
offset += (pos * 7);
|
||||
tmpDate = [tmpDate addYear: 0 month: 0 day: offset
|
||||
hour: 0 minute: 0 second: 0];
|
||||
|
||||
return tmpDate;
|
||||
}
|
||||
|
||||
- (int) secondsOffsetFromGMT
|
||||
{
|
||||
return [self _secondsOfOffset: @"tzoffsetto"];
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalToDo_H__
|
||||
#define __NGCards_iCalToDo_H__
|
||||
|
||||
#import "iCalRepeatableEntityObject.h"
|
||||
|
||||
/*
|
||||
iCalToDo
|
||||
|
||||
This class keeps the attributes of an iCalendar todo record (a task).
|
||||
*/
|
||||
|
||||
@class NSCalendarDate;
|
||||
@class NSString;
|
||||
|
||||
@interface iCalToDo : iCalRepeatableEntityObject
|
||||
|
||||
- (void) setPercentComplete: (NSString *) _value;
|
||||
- (NSString *) percentComplete;
|
||||
|
||||
- (void) setDue: (NSCalendarDate *) _date;
|
||||
- (NSCalendarDate *) due;
|
||||
|
||||
- (void) setCompleted: (NSCalendarDate *) _date;
|
||||
- (NSCalendarDate *) completed;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalToDo_H__ */
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "NSCalendarDate+NGCards.h"
|
||||
#import "CardGroup+iCal.h"
|
||||
|
||||
#import "iCalDateTime.h"
|
||||
#import "iCalToDo.h"
|
||||
|
||||
@implementation iCalToDo
|
||||
|
||||
- (Class) classForTag: (NSString *) classTag
|
||||
{
|
||||
Class tagClass;
|
||||
|
||||
if ([classTag isEqualToString: @"DUE"]
|
||||
|| [classTag isEqualToString: @"COMPLETED"])
|
||||
tagClass = [iCalDateTime class];
|
||||
else if ([classTag isEqualToString: @"PERCENT-COMPLETE"])
|
||||
tagClass = [CardElement class];
|
||||
else
|
||||
tagClass = [super classForTag: classTag];
|
||||
|
||||
return tagClass;
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setPercentComplete: (NSString *) _value
|
||||
{
|
||||
[[self uniqueChildWithTag: @"percent-complete"] setValue: 0
|
||||
to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) percentComplete
|
||||
{
|
||||
return [[self uniqueChildWithTag: @"percent-complete"] value: 0];
|
||||
}
|
||||
|
||||
- (void) setDue: (NSCalendarDate *) _date
|
||||
{
|
||||
[self setDate: _date
|
||||
forDateTimeValue: @"due"];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) due
|
||||
{
|
||||
return [self dateForDateTimeValue: @"due"];
|
||||
// return [[self uniqueChildWithTag: @"percent-complete"] asCalendarDate];
|
||||
}
|
||||
|
||||
- (void) setCompleted: (NSCalendarDate *) _date
|
||||
{
|
||||
[self setStatus: @"COMPLETED"];
|
||||
[self setDate: _date forDateTimeValue: @"completed"];
|
||||
}
|
||||
|
||||
- (NSCalendarDate *) completed
|
||||
{
|
||||
return [self dateForDateTimeValue: @"completed"];
|
||||
}
|
||||
|
||||
/* ical typing */
|
||||
|
||||
- (NSString *) entityName
|
||||
{
|
||||
return @"vtodo";
|
||||
}
|
||||
|
||||
// /* descriptions */
|
||||
|
||||
// - (NSString *)description {
|
||||
// NSMutableString *ms;
|
||||
|
||||
// ms = [NSMutableString stringWithCapacity:128];
|
||||
// [ms appendFormat:@"<0x%p[%@]:", self, NSStringFromClass([self class])];
|
||||
|
||||
// if (uid) [ms appendFormat:@" uid=%@", uid];
|
||||
// if (startDate) [ms appendFormat:@" start=%@", startDate];
|
||||
// if (due) [ms appendFormat:@" due=%@", due];
|
||||
// if (priority) [ms appendFormat:@" pri=%@", priority];
|
||||
|
||||
// if (completed)
|
||||
// [ms appendFormat:@" completed=%@", completed];
|
||||
// if (percentComplete)
|
||||
// [ms appendFormat:@" complete=%@", percentComplete];
|
||||
// if (accessClass)
|
||||
// [ms appendFormat:@" class=%@", accessClass];
|
||||
|
||||
// if (summary)
|
||||
// [ms appendFormat:@" summary=%@", summary];
|
||||
|
||||
// [ms appendString:@">"];
|
||||
// return ms;
|
||||
// }
|
||||
|
||||
@end /* iCalToDo */
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __NGCards_iCalTrigger_H__
|
||||
#define __NGCards_iCalTrigger_H__
|
||||
|
||||
#import "CardElement.h"
|
||||
|
||||
@interface iCalTrigger : CardElement
|
||||
|
||||
- (void) setValue: (NSString *) aValue;
|
||||
- (NSString *) value;
|
||||
|
||||
- (void) setValueType: (NSString *) aType;
|
||||
- (NSString *) valueType;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* __NGCards_iCalTrigger_H__ */
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalTrigger.h"
|
||||
#include "common.h"
|
||||
|
||||
@implementation iCalTrigger
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void) setValue: (NSString *) _value
|
||||
{
|
||||
[self setValue: 0 to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) value
|
||||
{
|
||||
return [self value: 0];
|
||||
}
|
||||
|
||||
- (void) setValueType: (NSString *) _value
|
||||
{
|
||||
[self setValue: 0 ofAttribute: @"type" to: _value];
|
||||
}
|
||||
|
||||
- (NSString *) valueType
|
||||
{
|
||||
return [self value: 0 ofAttribute: @"type"];
|
||||
}
|
||||
|
||||
@end /* iCalTrigger */
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalRecurrenceCalculator.h"
|
||||
|
||||
@interface iCalWeeklyRecurrenceCalculator : iCalRecurrenceCalculator
|
||||
@end
|
||||
|
||||
#include <NGExtensions/NGCalendarDateRange.h>
|
||||
#include "iCalRecurrenceRule.h"
|
||||
#include "NSCalendarDate+ICal.h"
|
||||
#include "common.h"
|
||||
|
||||
@interface iCalRecurrenceCalculator (PrivateAPI)
|
||||
|
||||
- (NSCalendarDate *)lastInstanceStartDate;
|
||||
|
||||
- (unsigned)offsetFromSundayForJulianNumber:(long)_jn;
|
||||
- (unsigned)offsetFromSundayForWeekDay:(iCalWeekDay)_weekDay;
|
||||
- (unsigned)offsetFromSundayForCurrentWeekStart;
|
||||
|
||||
- (iCalWeekDay)weekDayForJulianNumber:(long)_jn;
|
||||
|
||||
@end
|
||||
|
||||
/*
|
||||
TODO: If BYDAY is specified, lastInstanceStartDate and recurrences will
|
||||
differ significantly!
|
||||
*/
|
||||
@implementation iCalWeeklyRecurrenceCalculator
|
||||
|
||||
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r {
|
||||
NSMutableArray *ranges;
|
||||
NSCalendarDate *firStart;
|
||||
long i, jnFirst, jnStart, jnEnd, startEndCount;
|
||||
unsigned interval, byDayMask;
|
||||
|
||||
firStart = [self->firstRange startDate];
|
||||
jnFirst = [firStart julianNumber];
|
||||
jnEnd = [[_r endDate] julianNumber];
|
||||
|
||||
if (jnFirst > jnEnd)
|
||||
return nil;
|
||||
|
||||
jnStart = [[_r startDate] julianNumber];
|
||||
interval = [self->rrule repeatInterval];
|
||||
|
||||
/* if rule is bound, check the bounds */
|
||||
if (![self->rrule isInfinite]) {
|
||||
NSCalendarDate *until;
|
||||
long jnRuleLast;
|
||||
|
||||
until = [self->rrule untilDate];
|
||||
if (until) {
|
||||
if ([until compare:[_r startDate]] == NSOrderedAscending)
|
||||
return nil;
|
||||
jnRuleLast = [until julianNumber];
|
||||
}
|
||||
else {
|
||||
jnRuleLast = (interval * [self->rrule repeatCount] * 7)
|
||||
+ jnFirst;
|
||||
if (jnRuleLast < jnStart)
|
||||
return nil;
|
||||
}
|
||||
/* jnStart < jnRuleLast < jnEnd ? */
|
||||
if (jnEnd > jnRuleLast)
|
||||
jnEnd = jnRuleLast;
|
||||
}
|
||||
|
||||
startEndCount = (jnEnd - jnStart) + 1;
|
||||
ranges = [NSMutableArray arrayWithCapacity:startEndCount];
|
||||
byDayMask = [self->rrule byDayMask];
|
||||
if (!byDayMask) {
|
||||
for (i = 0 ; i < startEndCount; i++) {
|
||||
long jnCurrent;
|
||||
|
||||
jnCurrent = jnStart + i;
|
||||
if (jnCurrent >= jnFirst) {
|
||||
long jnDiff;
|
||||
|
||||
jnDiff = jnCurrent - jnFirst; /* difference in days */
|
||||
if ((jnDiff % (interval * 7)) == 0) {
|
||||
NSCalendarDate *start, *end;
|
||||
NGCalendarDateRange *r;
|
||||
|
||||
start = [NSCalendarDate dateForJulianNumber:jnCurrent];
|
||||
[start setTimeZone:[firStart timeZone]];
|
||||
start = [start hour: [firStart hourOfDay]
|
||||
minute:[firStart minuteOfHour]
|
||||
second:[firStart secondOfMinute]];
|
||||
end = [start addTimeInterval:[self->firstRange duration]];
|
||||
r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
|
||||
endDate:end];
|
||||
if ([_r containsDateRange:r])
|
||||
[ranges addObject:r];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
long jnFirstWeekStart, weekStartOffset;
|
||||
|
||||
/* calculate jnFirst's week start - this depends on our setting of week
|
||||
start */
|
||||
weekStartOffset = [self offsetFromSundayForJulianNumber:jnFirst] -
|
||||
[self offsetFromSundayForCurrentWeekStart];
|
||||
|
||||
jnFirstWeekStart = jnFirst - weekStartOffset;
|
||||
|
||||
for (i = 0 ; i < startEndCount; i++) {
|
||||
long jnCurrent;
|
||||
|
||||
jnCurrent = jnStart + i;
|
||||
if (jnCurrent >= jnFirst) {
|
||||
long jnDiff;
|
||||
|
||||
/* we need to calculate a difference in weeks */
|
||||
jnDiff = (jnCurrent - jnFirstWeekStart) % 7;
|
||||
if ((jnDiff % interval) == 0) {
|
||||
BOOL isRecurrence = NO;
|
||||
|
||||
if (jnCurrent == jnFirst) {
|
||||
isRecurrence = YES;
|
||||
}
|
||||
else {
|
||||
iCalWeekDay weekDay;
|
||||
|
||||
weekDay = [self weekDayForJulianNumber:jnCurrent];
|
||||
isRecurrence = (weekDay & [self->rrule byDayMask]) ? YES : NO;
|
||||
}
|
||||
if (isRecurrence) {
|
||||
NSCalendarDate *start, *end;
|
||||
NGCalendarDateRange *r;
|
||||
|
||||
start = [NSCalendarDate dateForJulianNumber:jnCurrent];
|
||||
[start setTimeZone:[firStart timeZone]];
|
||||
start = [start hour: [firStart hourOfDay]
|
||||
minute:[firStart minuteOfHour]
|
||||
second:[firStart secondOfMinute]];
|
||||
end = [start addTimeInterval:[self->firstRange duration]];
|
||||
r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
|
||||
endDate:end];
|
||||
if ([_r containsDateRange:r])
|
||||
[ranges addObject:r];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
- (NSCalendarDate *)lastInstanceStartDate {
|
||||
if ([self->rrule repeatCount] > 0) {
|
||||
long jnFirst, jnRuleLast;
|
||||
NSCalendarDate *firStart, *until;
|
||||
|
||||
firStart = [self->firstRange startDate];
|
||||
jnFirst = [firStart julianNumber];
|
||||
jnRuleLast = ([self->rrule repeatInterval] *
|
||||
[self->rrule repeatCount] * 7) +
|
||||
jnFirst;
|
||||
until = [NSCalendarDate dateForJulianNumber:jnRuleLast];
|
||||
until = [until hour: [firStart hourOfDay]
|
||||
minute:[firStart minuteOfHour]
|
||||
second:[firStart secondOfMinute]];
|
||||
return until;
|
||||
}
|
||||
return [super lastInstanceStartDate];
|
||||
}
|
||||
|
||||
@end /* iCalWeeklyRecurrenceCalculator */
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "iCalRecurrenceCalculator.h"
|
||||
|
||||
@interface iCalYearlyRecurrenceCalculator : iCalRecurrenceCalculator
|
||||
@end
|
||||
|
||||
#include <NGExtensions/NGCalendarDateRange.h>
|
||||
#include "iCalRecurrenceRule.h"
|
||||
#include "NSCalendarDate+ICal.h"
|
||||
#include "common.h"
|
||||
|
||||
@interface iCalRecurrenceCalculator(PrivateAPI)
|
||||
- (NSCalendarDate *)lastInstanceStartDate;
|
||||
@end
|
||||
|
||||
@implementation iCalYearlyRecurrenceCalculator
|
||||
|
||||
- (NSArray *)recurrenceRangesWithinCalendarDateRange:(NGCalendarDateRange *)_r{
|
||||
NSMutableArray *ranges;
|
||||
NSCalendarDate *firStart, *rStart, *rEnd, *until;
|
||||
unsigned i, count, interval;
|
||||
int diff;
|
||||
|
||||
firStart = [self->firstRange startDate];
|
||||
rStart = [_r startDate];
|
||||
rEnd = [_r endDate];
|
||||
interval = [self->rrule repeatInterval];
|
||||
until = [self lastInstanceStartDate];
|
||||
|
||||
if (until) {
|
||||
if ([until compare:rStart] == NSOrderedAscending)
|
||||
return nil;
|
||||
if ([until compare:rEnd] == NSOrderedDescending)
|
||||
rEnd = until;
|
||||
}
|
||||
|
||||
diff = [firStart yearsBetweenDate:rStart];
|
||||
if ((diff != 0) && [rStart compare:firStart] == NSOrderedAscending)
|
||||
diff = -diff;
|
||||
|
||||
count = [rStart yearsBetweenDate:rEnd] + 1;
|
||||
ranges = [NSMutableArray arrayWithCapacity:count];
|
||||
for (i = 0 ; i < count; i++) {
|
||||
int test;
|
||||
|
||||
test = diff + i;
|
||||
if ((test >= 0) && (test % interval) == 0) {
|
||||
NSCalendarDate *start, *end;
|
||||
NGCalendarDateRange *r;
|
||||
|
||||
start = [firStart dateByAddingYears:diff + i
|
||||
months:0
|
||||
days:0];
|
||||
[start setTimeZone:[firStart timeZone]];
|
||||
end = [start addTimeInterval:[self->firstRange duration]];
|
||||
r = [NGCalendarDateRange calendarDateRangeWithStartDate:start
|
||||
endDate:end];
|
||||
if ([_r containsDateRange:r])
|
||||
[ranges addObject:r];
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
- (NSCalendarDate *)lastInstanceStartDate {
|
||||
if ([self->rrule repeatCount] > 0) {
|
||||
NSCalendarDate *until;
|
||||
unsigned years, interval;
|
||||
|
||||
interval = [self->rrule repeatInterval];
|
||||
years = [self->rrule repeatCount] * interval;
|
||||
until = [[self->firstRange startDate] dateByAddingYears:years
|
||||
months:0
|
||||
days:0];
|
||||
return until;
|
||||
}
|
||||
return [super lastInstanceStartDate];
|
||||
}
|
||||
|
||||
@end /* iCalYearlyRecurrenceCalculator */
|
|
@ -0,0 +1,482 @@
|
|||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
|
@ -0,0 +1,157 @@
|
|||
2005-09-19 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* ievalrrule.m: started tool to evaluate iCal rrules on the shell
|
||||
|
||||
2005-08-16 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* link tools against OSX frameworks if configured so
|
||||
|
||||
2005-05-06 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* renamed ical3.m to icalds.m, ical2.m to icalparsetest
|
||||
|
||||
2005-04-25 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* properly include config.make
|
||||
|
||||
* fixed some gcc 4.0 warnings
|
||||
|
||||
2004-09-26 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* GNUmakefile.preamble: fixed makefiles for SOPE inline compilation
|
||||
|
||||
2004-08-29 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* added hack to install the tools in FHS locations - the executables
|
||||
will be installed in FHS_INSTALL_ROOT if specified (eg make
|
||||
FHS_INSTALL_ROOT=/usr/local)
|
||||
|
||||
2004-08-17 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* subclassing.m: fixed a compiler warning
|
||||
|
||||
2004-07-09 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* bmlookup.m: major code cleanups, improved output
|
||||
|
||||
2004-06-27 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* ldap2dsml.m: fixed a compile warning
|
||||
|
||||
2004-06-21 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* common.h: fixed compatibility with gstep-base
|
||||
|
||||
2004-06-17 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* added 'testurl' to test NSURL for the Cocoa Foundation bug wrt the
|
||||
trailing suffix in -path
|
||||
|
||||
2004-05-09 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* subclassing.m: added support for Apple runtime
|
||||
|
||||
2004-04-12 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* ImapListTool, ImapTool.m, imapls.m: minor code cleanups
|
||||
|
||||
2004-01-19 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* ldapls.m: minor fixes (moved NSAutoreleasePool to correct place)
|
||||
|
||||
2004-01-11 Helge Hess <helge.hess@opengroupware.org>
|
||||
|
||||
* minor cleanups to log messages
|
||||
|
||||
2003-10-12 Helge Hess <helge@opengroupware.org>
|
||||
|
||||
* EOQualTool.m: fix: returned value in a void method
|
||||
|
||||
* GNUmakefile (TOOL_NAME): do not compile subclassing.m on
|
||||
MacOSX
|
||||
|
||||
* EncodingTool.m: fixed compilation on MacOSX
|
||||
|
||||
2003-05-15 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* added parserule for testing parsing of NGRule objects
|
||||
|
||||
2003-05-14 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* some gcc 3.3 warnings fixed
|
||||
|
||||
2003-04-03 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* GNUmakefile: added ldapchkpwd tool
|
||||
|
||||
* ldap2dsml.m: added autorelease-pool to main()
|
||||
|
||||
2003-04-01 GNUstep User <helge.hess@skyrix.com>
|
||||
|
||||
* ImapListTool.m: do not use NSFileIdentifier constant
|
||||
|
||||
* EncodingTool.m: removed some undeclared encodings when compiling for
|
||||
GNUstep Base
|
||||
|
||||
2003-02-12 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* added ical2.m, ical3.m - examples for NGiCal
|
||||
|
||||
2003-01-30 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* added httpu_notify, a small tool to send out HTTP-over-UDP
|
||||
NOTIFY notifications
|
||||
|
||||
2003-01-08 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* testsock.m: improved test code
|
||||
|
||||
2003-01-07 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* subclassing.m, ImapQuotaTool.m, imapquota.m: fixed compilation
|
||||
warnings
|
||||
|
||||
* moved in testsock.m from NGStreams
|
||||
|
||||
* changes for improved compilation on MacOSX, replaced RETAIN macros
|
||||
with methods
|
||||
|
||||
Fri Dec 27 10:54:40 2002 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* Mime2XmlTool.m: fixed a protocol warning
|
||||
|
||||
Mon Dec 23 15:36:01 2002 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* ImapListTool.m: pass correct filemanager as a parameter
|
||||
|
||||
2002-12-08 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* testdirenum.m: cleanups
|
||||
|
||||
Tue Dec 17 15:07:40 2002 <jan@skyrix.com>
|
||||
|
||||
* imapquota.m: add quota test
|
||||
|
||||
2002-11-21 Jan Reichmann <jr@skyrix.com>
|
||||
|
||||
* added Imap-Super class, improve imapls
|
||||
|
||||
2002-11-21 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* added ldapls, ldap2dsml as examples for NGLdap
|
||||
|
||||
2002-11-15 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* EOQualTool.m: added test for complex cast
|
||||
|
||||
2002-10-29 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* EOQualTool.m: added support for parsing SQL using the new EOSQLParser
|
||||
|
||||
2002-10-25 Helge Hess <helge.hess@skyrix.com>
|
||||
|
||||
* added eoqual tool for parsing EOQualifier's (useful for syntax
|
||||
checks)
|
||||
|
||||
* created ChangeLog
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# GNUstep makefile
|
||||
|
||||
-include ../../config.make
|
||||
include $(GNUSTEP_MAKEFILES)/common.make
|
||||
|
||||
TOOL_NAME = vcardtest versittest icalparsetest icalds vcf2xml vcfparsetest ievalrrule
|
||||
|
||||
ADDITIONAL_INCLUDE_DIRS += -I../NGCards
|
||||
|
||||
vcardtest_OBJC_FILES = unittest.m vcardtest.m CardElement.m CardGroup.m CardVersitRenderer.m NSArray+NGCards.m NSDictionary+NGCards.m
|
||||
versittest_OBJC_FILES = unittest.m versittest.m CardElement.m CardGroup.m CardVersitRenderer.m NSArray+NGCards.m NSDictionary+NGCards.m NSString+NGCards.m
|
||||
icalparsetest_OBJC_FILES = icalparsetest.m
|
||||
icalds_OBJC_FILES = icalds.m
|
||||
vcf2xml_OBJC_FILES = vcf2xml.m
|
||||
vcfparsetest_OBJC_FILES = vcfparsetest.m CardElement.m CardGroup.m CardVersitRenderer.m NSArray+NGCards.m NSDictionary+NGCards.m NSString+NGCards.m
|
||||
ievalrrule_OBJC_FILES = ievalrrule.m
|
||||
|
||||
-include GNUmakefile.preamble
|
||||
include $(GNUSTEP_MAKEFILES)/tool.make
|
||||
-include GNUmakefile.postamble
|
||||
-include fhs.make
|
||||
|
||||
CardElement.m: ../NGCards/CardElement.m
|
||||
ln -sf ../NGCards/CardElement.m ./
|
||||
|
||||
CardGroup.m: ../NGCards/CardGroup.m
|
||||
ln -sf ../NGCards/CardGroup.m ./
|
||||
|
||||
CardVersitRenderer.m: ../NGCards/CardVersitRenderer.m
|
||||
ln -sf ../NGCards/CardVersitRenderer.m ./
|
||||
|
||||
NSArray+NGCards.m: ../NGCards/NSArray+NGCards.m
|
||||
ln -sf ../NGCards/NSArray+NGCards.m ./
|
||||
|
||||
NSDictionary+NGCards.m: ../NGCards/NSDictionary+NGCards.m
|
||||
ln -sf ../NGCards/NSDictionary+NGCards.m ./
|
||||
|
||||
NSString+NGCards.m: ../NGCards/NSString+NGCards.m
|
||||
ln -sf ../NGCards/NSString+NGCards.m ./
|
||||
|
||||
|
||||
distclean clean::
|
||||
-rm -f CardElement.m CardGroup.m CardVersitRenderer.m NSArray+NGCards.m NSDictionary+NGCards.m NSString+NGCards.m
|
|
@ -0,0 +1,64 @@
|
|||
# compilation flags
|
||||
|
||||
SOPE_ROOT=../..
|
||||
SOPE_CORE="../../sope-core"
|
||||
SOPE_XML="../../sope-xml"
|
||||
|
||||
ADDITIONAL_INCLUDE_DIRS += \
|
||||
-I.. \
|
||||
-I$(SOPE_CORE)/NGStreams \
|
||||
-I$(SOPE_CORE)/NGExtensions \
|
||||
|
||||
|
||||
# PCH
|
||||
|
||||
icalparsetest_PCH_FILE = common.h
|
||||
icalds_PCH_FILE = common.h
|
||||
vcf2xml_PCH_FILE = common.h
|
||||
vcfparsetest_PCH_FILE = common.h
|
||||
ievalrrule_PCH_FILE = common.h
|
||||
|
||||
|
||||
# dependencies
|
||||
|
||||
ifneq ($(frameworks),yes)
|
||||
icalparsetest_TOOL_LIBS += -lNGCards
|
||||
icalds_TOOL_LIBS += -lNGCards
|
||||
vcfparsetest_TOOL_LIBS += -lNGCards
|
||||
ievalrrule_TOOL_LIBS += -lNGCards
|
||||
|
||||
ADDITIONAL_TOOL_LIBS += \
|
||||
-lNGStreams -lNGExtensions -lEOControl \
|
||||
-lDOM -lSaxObjC
|
||||
else
|
||||
icalparsetest_TOOL_LIBS += -framework NGCards
|
||||
icalds_TOOL_LIBS += -framework NGCards
|
||||
vcfparsetest_TOOL_LIBS += -framework NGCards
|
||||
ievalrrule_TOOL_LIBS += -framework NGCards
|
||||
|
||||
ADDITIONAL_TOOL_LIBS += \
|
||||
-framework NGStreams -framework NGExtensions -framework EOControl \
|
||||
-framework DOM -framework SaxObjC
|
||||
endif
|
||||
|
||||
|
||||
# library/framework search pathes
|
||||
|
||||
DEP_DIRS = \
|
||||
../NGCards/ \
|
||||
$(SOPE_ROOT)/sope-core/NGExtensions \
|
||||
$(SOPE_ROOT)/sope-core/NGStreams \
|
||||
$(SOPE_ROOT)/sope-core/EOControl \
|
||||
$(SOPE_ROOT)/sope-xml/DOM \
|
||||
$(SOPE_ROOT)/sope-xml/SaxObjC
|
||||
|
||||
ifneq ($(frameworks),yes)
|
||||
ADDITIONAL_LIB_DIRS += \
|
||||
$(foreach dir,$(DEP_DIRS),\
|
||||
-L$(GNUSTEP_BUILD_DIR)/$(dir)/$(GNUSTEP_OBJ_DIR_NAME))
|
||||
else
|
||||
ADDITIONAL_LIB_DIRS += \
|
||||
$(foreach dir,$(DEP_DIRS),-F$(GNUSTEP_BUILD_DIR)/$(dir))
|
||||
endif
|
||||
|
||||
SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
|
|
@ -0,0 +1,9 @@
|
|||
sope-ical/samples
|
||||
|
||||
This directory contains sample programs for the sope-ical libraries.
|
||||
|
||||
Tools
|
||||
=====
|
||||
|
||||
ical2 - uses SaxObjectDecoder with NGiCal.xmap
|
||||
ical3 - uses iCalDataSource to run queries on iCal files
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
# include <Foundation/exceptions/GeneralExceptions.h>
|
||||
#else
|
||||
# include <NGExtensions/NGObjectMacros.h>
|
||||
# include <NGExtensions/NSString+Ext.h>
|
||||
#endif
|
||||
|
||||
#include <NGExtensions/NGExtensions.h>
|
|
@ -0,0 +1,26 @@
|
|||
# postprocessing
|
||||
|
||||
# FHS support (this is a hack and is going to be done by gstep-make!)
|
||||
|
||||
ifneq ($(FHS_INSTALL_ROOT),)
|
||||
|
||||
FHS_INCLUDE_DIR=$(FHS_INSTALL_ROOT)/include/
|
||||
FHS_LIB_DIR=$(FHS_INSTALL_ROOT)/lib/
|
||||
FHS_BIN_DIR=$(FHS_INSTALL_ROOT)/bin/
|
||||
|
||||
fhs-bin-dirs ::
|
||||
$(MKDIRS) $(FHS_BIN_DIR)
|
||||
|
||||
NONFHS_BINDIR="$(GNUSTEP_TOOLS)/$(GNUSTEP_TARGET_LDIR)"
|
||||
|
||||
move-tools-to-fhs :: fhs-bin-dirs
|
||||
@echo "moving tools from $(NONFHS_BINDIR) to $(FHS_BIN_DIR) .."
|
||||
for i in $(TOOL_NAME); do \
|
||||
mv "$(NONFHS_BINDIR)/$${i}" $(FHS_BIN_DIR); \
|
||||
done
|
||||
|
||||
move-to-fhs :: move-tools-to-fhs
|
||||
|
||||
after-install :: move-to-fhs
|
||||
|
||||
endif
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@class EOQualifier, NSString, EOSortOrdering;
|
||||
|
||||
@interface iCal3Tool : NSObject
|
||||
{
|
||||
EOQualifier *qualifier;
|
||||
NSString *entityName;
|
||||
NSArray *sortOrderings;
|
||||
}
|
||||
|
||||
- (int)runWithArguments:(NSArray *)_args;
|
||||
|
||||
@end
|
||||
|
||||
#include <NGCards/iCalDataSource.h>
|
||||
#include <NGCards/iCalObject.h>
|
||||
#include <EOControl/EOQualifier.h>
|
||||
#include <EOControl/EOSortOrdering.h>
|
||||
#include "common.h"
|
||||
|
||||
@implementation iCal3Tool
|
||||
|
||||
- (id)init {
|
||||
if ((self = [super init])) {
|
||||
NSUserDefaults *ud;
|
||||
id tmp;
|
||||
|
||||
/* collect options */
|
||||
ud = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
self->entityName = [[ud stringForKey:@"entity"] copy];
|
||||
|
||||
if ((tmp = [ud objectForKey:@"qualifier"]) != nil) {
|
||||
self->qualifier = [[EOQualifier alloc] initWithPropertyList:tmp
|
||||
owner:nil];
|
||||
}
|
||||
|
||||
if ((tmp = [ud objectForKey:@"sort"]) != nil) {
|
||||
tmp = [[EOSortOrdering alloc] initWithPropertyList:tmp owner:nil];
|
||||
if (tmp != nil) {
|
||||
self->sortOrderings = [[NSArray alloc] initWithObjects:&tmp count:1];
|
||||
[tmp release]; tmp = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (void)dealloc {
|
||||
[self->sortOrderings release];
|
||||
[self->qualifier release];
|
||||
[self->entityName release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* run */
|
||||
|
||||
- (void)printObject:(id)_object {
|
||||
printf("object: %s\n", [[_object description] cString]);
|
||||
}
|
||||
|
||||
- (int)runWithArguments:(NSArray *)_args {
|
||||
NSEnumerator *args;
|
||||
NSString *arg;
|
||||
|
||||
/* begin processing */
|
||||
|
||||
args = [_args objectEnumerator];
|
||||
[args nextObject]; // process name ...
|
||||
|
||||
while ((arg = [args nextObject])) {
|
||||
NSAutoreleasePool *pool2;
|
||||
|
||||
if ([arg hasPrefix:@"-"]) { /* consume defaults */
|
||||
[args nextObject];
|
||||
continue;
|
||||
}
|
||||
|
||||
pool2 = [[NSAutoreleasePool alloc] init];
|
||||
{
|
||||
iCalDataSource *ds;
|
||||
EOFetchSpecification *fspec;
|
||||
NSArray *objs;
|
||||
iCalObject *obj;
|
||||
|
||||
/* setup fetch specification */
|
||||
|
||||
fspec = [[[EOFetchSpecification alloc] init] autorelease];
|
||||
[fspec setEntityName:self->entityName];
|
||||
[fspec setQualifier:self->qualifier];
|
||||
|
||||
/* setup datasource */
|
||||
|
||||
ds = [iCalDataSource alloc]; // keep gcc happy
|
||||
ds = [[ds initWithPath:arg] autorelease];
|
||||
[ds setFetchSpecification:fspec];
|
||||
|
||||
/* perform fetch */
|
||||
|
||||
if ((objs = [ds fetchObjects]) == nil) {
|
||||
/* fetch failed */
|
||||
|
||||
NSLog(@"fetch on ical file failed: %@", arg);
|
||||
}
|
||||
else {
|
||||
/* process results */
|
||||
NSEnumerator *e;
|
||||
|
||||
e = [objs objectEnumerator];
|
||||
while ((obj = [e nextObject])) {
|
||||
[self printObject:obj];
|
||||
}
|
||||
}
|
||||
}
|
||||
[pool2 release];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end /* iCal3Tool */
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
NSAutoreleasePool *pool;
|
||||
iCal3Tool *tool;
|
||||
int rc;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
|
||||
#endif
|
||||
|
||||
if ((tool = [[iCal3Tool alloc] init])) {
|
||||
NS_DURING
|
||||
rc = [tool runWithArguments:[[NSProcessInfo processInfo] arguments]];
|
||||
NS_HANDLER
|
||||
abort();
|
||||
NS_ENDHANDLER;
|
||||
|
||||
[tool release];
|
||||
}
|
||||
else
|
||||
rc = 1;
|
||||
|
||||
[pool release];
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
Copyright (C) 2000-2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <SaxObjC/SaxObjC.h>
|
||||
|
||||
@interface iCal2Tool : NSObject
|
||||
{
|
||||
id<NSObject,SaxXMLReader> parser;
|
||||
SaxObjectDecoder *sax;
|
||||
}
|
||||
|
||||
- (int)runWithArguments:(NSArray *)_args;
|
||||
|
||||
@end
|
||||
|
||||
@implementation iCal2Tool
|
||||
|
||||
- (id)init {
|
||||
if ((self = [super init])) {
|
||||
self->parser =
|
||||
[[[SaxXMLReaderFactory standardXMLReaderFactory]
|
||||
createXMLReaderForMimeType:@"text/calendar"]
|
||||
retain];
|
||||
if (self->parser == nil) {
|
||||
NSLog(@"%s: did not find a parser for text/calendar !",
|
||||
__PRETTY_FUNCTION__);
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* ensure that NGCards.xmap can be found ! (Library/SaxMappings) */
|
||||
self->sax = [[SaxObjectDecoder alloc] initWithMappingNamed:@"NGCards"];
|
||||
if (self->sax == nil) {
|
||||
NSLog(@"could not create the iCal SAX handler !");
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
[self->parser setContentHandler:self->sax];
|
||||
[self->parser setErrorHandler:self->sax];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (void)dealloc {
|
||||
[self->sax release];
|
||||
[self->parser release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* parsing */
|
||||
|
||||
- (id)parseFile:(NSString *)_path {
|
||||
if ([_path length] == 0) return nil;
|
||||
|
||||
_path = [@"file://" stringByAppendingString:_path];
|
||||
|
||||
[self->parser parseFromSystemId:_path];
|
||||
|
||||
return [self->sax rootObject];
|
||||
}
|
||||
|
||||
- (void)printParsedObject:(id)_object {
|
||||
NSLog(@"component: %@", _object);
|
||||
#if 0
|
||||
NSLog(@" subcomponents: %@", [_object subComponents]);
|
||||
|
||||
printf("%s", [[_object icalString] cString]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* run */
|
||||
|
||||
- (int)runWithArguments:(NSArray *)_args {
|
||||
NSEnumerator *args;
|
||||
NSString *arg;
|
||||
|
||||
args = [_args objectEnumerator];
|
||||
[args nextObject]; // process name ...
|
||||
|
||||
while ((arg = [args nextObject])) {
|
||||
NSAutoreleasePool *pool2;
|
||||
|
||||
if ([arg hasPrefix:@"-"]) { /* consume defaults */
|
||||
[args nextObject];
|
||||
continue;
|
||||
}
|
||||
|
||||
pool2 = [[NSAutoreleasePool alloc] init];
|
||||
{
|
||||
id component;
|
||||
|
||||
NS_DURING
|
||||
component = [self parseFile:arg];
|
||||
NS_HANDLER
|
||||
abort();
|
||||
NS_ENDHANDLER;
|
||||
|
||||
if (component == nil)
|
||||
NSLog(@"could not parse file: '%@'", arg);
|
||||
else
|
||||
[self printParsedObject:component];
|
||||
}
|
||||
[pool2 release];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end /* iCal2Tool */
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
NSAutoreleasePool *pool;
|
||||
iCal2Tool *tool;
|
||||
int rc;
|
||||
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
|
||||
#endif
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
if ((tool = [[iCal2Tool alloc] init])) {
|
||||
NS_DURING
|
||||
rc = [tool runWithArguments:[[NSProcessInfo processInfo] arguments]];
|
||||
NS_HANDLER
|
||||
abort();
|
||||
NS_ENDHANDLER;
|
||||
|
||||
[tool release];
|
||||
}
|
||||
else
|
||||
rc = 1;
|
||||
|
||||
[pool release];
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
Copyright (C) 2005 SKYRIX Software AG
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <NGCards/iCalRecurrenceRule.h>
|
||||
#include <NGCards/iCalRecurrenceCalculator.h>
|
||||
#include <NGExtensions/NGCalendarDateRange.h>
|
||||
#include "common.h"
|
||||
|
||||
static NSCalendarDate *dateForString(NSString *_s) {
|
||||
// copied from ogo-chkaptconflicts, maybe move to NGExtensions?
|
||||
static NSCalendarDate *now = nil;
|
||||
static NSCalendarDate *mon = nil;
|
||||
|
||||
if (now == nil) now = [[NSCalendarDate date] retain];
|
||||
if (mon == nil) mon = [[now mondayOfWeek] retain];
|
||||
_s = [_s lowercaseString];
|
||||
|
||||
if ([_s isEqualToString:@"now"]) return now;
|
||||
if ([_s isEqualToString:@"tomorrow"]) return [now tomorrow];
|
||||
if ([_s isEqualToString:@"yesterday"]) return [now yesterday];
|
||||
|
||||
if ([_s hasPrefix:@"mon"]) return mon;
|
||||
if ([_s hasPrefix:@"tue"]) return [mon dateByAddingYears:0 months:0 days:1];
|
||||
if ([_s hasPrefix:@"wed"]) return [mon dateByAddingYears:0 months:0 days:2];
|
||||
if ([_s hasPrefix:@"thu"]) return [mon dateByAddingYears:0 months:0 days:3];
|
||||
if ([_s hasPrefix:@"fri"]) return [mon dateByAddingYears:0 months:0 days:4];
|
||||
if ([_s hasPrefix:@"sat"]) return [mon dateByAddingYears:0 months:0 days:5];
|
||||
if ([_s hasPrefix:@"sun"]) return [mon dateByAddingYears:0 months:0 days:6];
|
||||
|
||||
switch ([_s length]) {
|
||||
case 6:
|
||||
return [NSCalendarDate dateWithString:_s calendarFormat:@"%Y%m"];
|
||||
case 8:
|
||||
return [NSCalendarDate dateWithString:_s calendarFormat:@"%Y%m%d"];
|
||||
case 10:
|
||||
return [NSCalendarDate dateWithString:_s calendarFormat:@"%Y%-m-%d"];
|
||||
case 13:
|
||||
return [NSCalendarDate dateWithString:_s calendarFormat:@"%Y%m%d %H%M"];
|
||||
case 14:
|
||||
return [NSCalendarDate dateWithString:_s calendarFormat:@"%Y%m%d %H:%M"];
|
||||
case 16:
|
||||
return [NSCalendarDate dateWithString:_s calendarFormat:@"%Y-%m-%d %H:%M"];
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
static int usage(NSArray *args) {
|
||||
fprintf(stderr,
|
||||
"usage: %s <rrule> <startdate> <enddate> <cycleend>\n"
|
||||
"\n"
|
||||
"sample:\n"
|
||||
" %s 'FREQ=MONTHLY;BYDAY=2TU' '20050901 14:00' '20050901 15:00' "
|
||||
"20060921\n",
|
||||
[[args objectAtIndex:0] cString],
|
||||
[[args objectAtIndex:0] cString]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void printInstances(NSArray *instances) {
|
||||
unsigned i, count;
|
||||
|
||||
if ((count = [instances count]) == 0) {
|
||||
printf("no reccurrences in given range\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
NGCalendarDateRange *instance;
|
||||
NSString *s;
|
||||
|
||||
instance = [instances objectAtIndex:i];
|
||||
|
||||
s = [[instance startDate] descriptionWithCalendarFormat:
|
||||
@"%a, %Y-%m-%d at %H:%M"];
|
||||
printf("%s - ", [s cString]);
|
||||
|
||||
s = [[instance endDate] descriptionWithCalendarFormat:
|
||||
[[instance startDate] isDateOnSameDay:
|
||||
[instance endDate]]
|
||||
? @"%H:%M"
|
||||
: @"%a, %Y-%m-%d at %H:%M"];
|
||||
printf("%s\n", [s cString]);
|
||||
}
|
||||
}
|
||||
|
||||
static int runIt(NSArray *args) {
|
||||
iCalRecurrenceCalculator *cpu;
|
||||
iCalRecurrenceRule *rrule;
|
||||
NGCalendarDateRange *startRange, *calcRange;
|
||||
NSCalendarDate *from, *to, *cycleTo;
|
||||
NSString *pattern;
|
||||
NSArray *instances;
|
||||
|
||||
if ([args count] < 5)
|
||||
return usage(args);
|
||||
|
||||
pattern = [args objectAtIndex:1];
|
||||
from = dateForString([args objectAtIndex:2]);
|
||||
to = dateForString([args objectAtIndex:3]);
|
||||
cycleTo = dateForString([args objectAtIndex:4]);
|
||||
|
||||
if (from == nil || to == nil || cycleTo == nil || ![pattern isNotEmpty])
|
||||
return usage(args);
|
||||
|
||||
startRange =
|
||||
[NGCalendarDateRange calendarDateRangeWithStartDate:from endDate:to];
|
||||
|
||||
calcRange =
|
||||
[NGCalendarDateRange calendarDateRangeWithStartDate:from endDate:cycleTo];
|
||||
|
||||
/* parse rrule */
|
||||
|
||||
if ((rrule = [[iCalRecurrenceRule alloc] initWithString:pattern]) == nil) {
|
||||
usage(args);
|
||||
fprintf(stderr, "error: could not parse reccurence rule: '%s'\n",
|
||||
[pattern cString]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
NSLog(@"from: %@ to: %@, cycle %@", from, to, cycleTo);
|
||||
NSLog(@"rrule: %@", rrule);
|
||||
|
||||
/* calculate */
|
||||
|
||||
cpu = [iCalRecurrenceCalculator
|
||||
recurrenceCalculatorForRecurrenceRule:rrule
|
||||
withFirstInstanceCalendarDateRange:startRange];
|
||||
|
||||
instances = [cpu recurrenceRangesWithinCalendarDateRange:calcRange];
|
||||
printInstances(instances);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
NSAutoreleasePool *pool;
|
||||
int rc;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
|
||||
#endif
|
||||
|
||||
rc = runIt([[NSProcessInfo processInfo] argumentsWithoutDefaults]);
|
||||
[pool release];
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/* unittest.h - this file is part of $PROJECT_NAME_HERE$
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef UNITTEST_H
|
||||
#define UNITTEST_H
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
|
||||
@interface unittest : NSObject
|
||||
|
||||
- (void) run;
|
||||
|
||||
@end
|
||||
|
||||
#define testEqual(x,y) \
|
||||
if ((x) != (y)) { \
|
||||
NSLog (@"%s: values not equal at line %d", \
|
||||
__PRETTY_FUNCTION__, __LINE__); \
|
||||
return NO; \
|
||||
}
|
||||
|
||||
#define testObjectsEqual(x,y) \
|
||||
if (![(x) isEqual: (y)]) { \
|
||||
NSLog (@"%s: objects not equal at line %d", \
|
||||
__PRETTY_FUNCTION__, __LINE__); \
|
||||
return NO; \
|
||||
}
|
||||
|
||||
#define testStringsEqual(x,y) \
|
||||
if (!([(x) isKindOfClass: [NSString class]] \
|
||||
&& [(y) isKindOfClass: [NSString class]] ) \
|
||||
|| ![(x) isEqualToString: (y)]) { \
|
||||
NSLog (@"%s: strings \"%@\" and \"%@\" not equal at" \
|
||||
@" line %d", __PRETTY_FUNCTION__, (x), (y), \
|
||||
__LINE__); \
|
||||
return NO; \
|
||||
}
|
||||
|
||||
#define testNotEqual(x,y) \
|
||||
if ((x) == (y)) { \
|
||||
NSLog (@"%s: values equal at line %d", \
|
||||
__PRETTY_FUNCTION__, __LINE__); \
|
||||
return NO; \
|
||||
}
|
||||
|
||||
#define testObjectsNotEqual(x,y) \
|
||||
if ([(x) isEqual: (y)]) { \
|
||||
NSLog (@"%s: objects not equal at line %d", \
|
||||
__PRETTY_FUNCTION__, __LINE__); \
|
||||
return NO; \
|
||||
}
|
||||
|
||||
#define testStringsNotEqual(x,y) \
|
||||
if (!([(x) isKindOfClass: [NSString class]] \
|
||||
&& [(y) isKindOfClass: [NSString class]]) \
|
||||
|| [(x) isEqualToString: (y)]) { \
|
||||
NSLog (@"%s: strings not equal at line %d", \
|
||||
__PRETTY_FUNCTION__, __LINE__); \
|
||||
return NO; \
|
||||
}
|
||||
|
||||
@interface unittest (OptionalMethods)
|
||||
|
||||
- (void) setUp;
|
||||
- (void) tearDown;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* UNITTEST_H */
|
|
@ -0,0 +1,98 @@
|
|||
/* unittest.m - this file is part of $PROJECT_NAME_HERE$
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "unittest.h"
|
||||
|
||||
@implementation unittest
|
||||
|
||||
- (NSArray *) _testMethods
|
||||
{
|
||||
Class testClass;
|
||||
MethodList *methodList;
|
||||
NSMutableArray *methods;
|
||||
NSString *methodName;
|
||||
unsigned int count, max;
|
||||
|
||||
testClass = [self class];
|
||||
|
||||
methods = [NSMutableArray new];
|
||||
[methods autorelease];
|
||||
|
||||
while (testClass)
|
||||
{
|
||||
methodList = testClass->methods;
|
||||
max = methodList->method_count;
|
||||
|
||||
for (count = 0; count < max; count++)
|
||||
{
|
||||
methodName
|
||||
= NSStringFromSelector (methodList->method_list[count].method_name);
|
||||
if ([methodName hasPrefix: @"test"])
|
||||
[methods addObject: methodName];
|
||||
}
|
||||
|
||||
testClass = testClass->super_class;
|
||||
}
|
||||
|
||||
return methods;
|
||||
}
|
||||
|
||||
- (void) run
|
||||
{
|
||||
NSEnumerator *methods;
|
||||
NSString *methodName;
|
||||
unsigned int count, successes, failures;
|
||||
BOOL success;
|
||||
|
||||
methods = [[self _testMethods] objectEnumerator];
|
||||
methodName = [methods nextObject];
|
||||
|
||||
count = 0;
|
||||
successes = 0;
|
||||
failures = 0;
|
||||
NSLog (@"-- start: %@", NSStringFromClass([self class]));
|
||||
while (methodName)
|
||||
{
|
||||
count++;
|
||||
if ([self respondsToSelector: @selector (setUp)])
|
||||
[self setUp];
|
||||
success
|
||||
= (BOOL) [self performSelector: NSSelectorFromString (methodName)];
|
||||
NSLog (@"%@ '%@'",
|
||||
((success) ? @"PASSED" : @"FAILED"), methodName);
|
||||
if ([self respondsToSelector: @selector (tearDown)])
|
||||
[self tearDown];
|
||||
if (success)
|
||||
successes++;
|
||||
else
|
||||
failures++;
|
||||
methodName = [methods nextObject];
|
||||
}
|
||||
|
||||
NSLog (@"-- end: %d methods, %d successes, %d failures",
|
||||
count, successes, failures);
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,369 @@
|
|||
/* vcardtest.m - this file is part of $PROJECT_NAME_HERE$
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "CardElement.h"
|
||||
#import "CardGroup.h"
|
||||
|
||||
#import "unittest.h"
|
||||
|
||||
@interface subtest: unittest
|
||||
{
|
||||
CardElement *element;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation subtest: unittest
|
||||
|
||||
- (void) setUp
|
||||
{
|
||||
element = [CardElement new];
|
||||
}
|
||||
|
||||
- (void) tearDown
|
||||
{
|
||||
[element release];
|
||||
}
|
||||
|
||||
- (BOOL) testSimpleElementWithTag_value
|
||||
{
|
||||
CardElement *testElement;
|
||||
NSArray *values;
|
||||
|
||||
testElement = [CardElement simpleElementWithTag: @"pouet"
|
||||
value: @"tutu"];
|
||||
testStringsEqual([testElement tag], @"pouet");
|
||||
|
||||
values = [testElement values];
|
||||
testNotEqual(values, nil);
|
||||
testEqual([values count], 1);
|
||||
testStringsEqual([values objectAtIndex: 0], @"tutu");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testSimpleElementWithTag_singleType_value
|
||||
{
|
||||
CardElement *testElement;
|
||||
NSArray *values, *keys;
|
||||
NSDictionary *attrs;
|
||||
|
||||
testElement = [CardElement simpleElementWithTag: @"pouet"
|
||||
singleType: @"coucou"
|
||||
value: @"tutu"];
|
||||
testStringsEqual([testElement tag], @"pouet");
|
||||
|
||||
values = [testElement values];
|
||||
testNotEqual(values, nil);
|
||||
testEqual([values count], 1);
|
||||
testStringsEqual([values objectAtIndex: 0], @"tutu");
|
||||
|
||||
attrs = [testElement attributes];
|
||||
keys = [attrs allKeys];
|
||||
testEqual([keys count], 1);
|
||||
testStringsEqual([[keys objectAtIndex: 0] uppercaseString], @"TYPE");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testElementWithTag_attributes_values
|
||||
{
|
||||
NSMutableDictionary *addedAttrs;
|
||||
NSMutableArray *addedValues;
|
||||
NSArray *rValues, *keys;
|
||||
NSDictionary *rAttrs;
|
||||
CardElement *testElement;
|
||||
|
||||
addedAttrs = [NSMutableDictionary new];
|
||||
[addedAttrs setObject: [NSMutableArray arrayWithObjects:
|
||||
@"value1", @"blabla", nil]
|
||||
forKey: @"key1"];
|
||||
[addedAttrs setObject: [NSMutableArray arrayWithObject: @"test2"]
|
||||
forKey: @"key2"];
|
||||
addedValues = [NSMutableArray new];
|
||||
[addedValues addObject: @"value1"];
|
||||
[addedValues addObject: @"pouetpouet2"];
|
||||
|
||||
testElement = [CardElement elementWithTag: @"pouet"
|
||||
attributes: addedAttrs
|
||||
values: addedValues];
|
||||
|
||||
|
||||
testStringsEqual([testElement tag], @"pouet");
|
||||
rValues = [testElement values];
|
||||
rAttrs = [testElement attributes];
|
||||
keys = [rAttrs allKeys];
|
||||
|
||||
testNotEqual(rValues, nil);
|
||||
testNotEqual(rAttrs, nil);
|
||||
testEqual([rValues count], 2);
|
||||
testEqual([keys count], 2);
|
||||
testNotEqual(addedValues, rValues);
|
||||
testNotEqual(addedAttrs, rAttrs);
|
||||
|
||||
testStringsEqual([rValues objectAtIndex: 0], @"value1");
|
||||
testStringsEqual([rValues objectAtIndex: 1], @"pouetpouet2");
|
||||
testNotEqual([rAttrs objectForKey: @"key1"], nil);
|
||||
testNotEqual([rAttrs objectForKey: @"key2"], nil);
|
||||
testEqual([[rAttrs objectForKey: @"key1"] count], 2);
|
||||
testEqual([[rAttrs objectForKey: @"key2"] count], 1);
|
||||
|
||||
testStringsEqual([[rAttrs objectForKey: @"key1"] objectAtIndex: 0],
|
||||
@"value1");
|
||||
testStringsEqual([[rAttrs objectForKey: @"key1"] objectAtIndex: 1],
|
||||
@"blabla");
|
||||
testStringsEqual([[rAttrs objectForKey: @"key2"] objectAtIndex: 0],
|
||||
@"test2");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testAddValue
|
||||
{
|
||||
NSArray *values;
|
||||
|
||||
values = [element values];
|
||||
testEqual([values count], 0);
|
||||
[element addValue: @"test"];
|
||||
testEqual([values count], 1);
|
||||
testStringsEqual([values objectAtIndex: 0], @"test");
|
||||
[element addValue: @"coucou"];
|
||||
testEqual([values count], 2);
|
||||
testStringsEqual([values objectAtIndex: 0], @"test");
|
||||
testStringsEqual([values objectAtIndex: 1], @"coucou");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testAddValues
|
||||
{
|
||||
NSArray *values;
|
||||
|
||||
values = [element values];
|
||||
[element addValue: @"cuicui"];
|
||||
testEqual([values count], 1);
|
||||
|
||||
[element addValues: [NSArray arrayWithObject: @"coucou"]];
|
||||
testEqual([values count], 2);
|
||||
|
||||
[element addValue: @"cuicui2"];
|
||||
testEqual([values count], 3);
|
||||
testStringsEqual([values objectAtIndex: 1], @"coucou");
|
||||
testStringsEqual([values objectAtIndex: 2], @"cuicui2");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testAddType
|
||||
{
|
||||
NSMutableDictionary *attrs;
|
||||
NSArray *types;
|
||||
|
||||
attrs = (NSMutableDictionary *) [element attributes];
|
||||
testEqual([attrs objectForKey: @"TYPE"], nil);
|
||||
[element addType: @"INTERNET"];
|
||||
types = [attrs objectForKey: @"type"];
|
||||
testNotEqual(types, nil);
|
||||
testEqual([types count], 1);
|
||||
testStringsEqual([types objectAtIndex: 0],
|
||||
@"INTERNET");
|
||||
|
||||
[element addType: @"pref"];
|
||||
testEqual([types count], 2);
|
||||
testStringsEqual([types objectAtIndex: 0],
|
||||
@"INTERNET");
|
||||
testStringsEqual([types objectAtIndex: 1],
|
||||
@"pref");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testAddAttribute_value
|
||||
{
|
||||
NSMutableDictionary *attrs;
|
||||
|
||||
attrs = (NSMutableDictionary *) [element attributes];
|
||||
testEqual([attrs objectForKey: @"attr1"], nil);
|
||||
[element addAttribute: @"attr1" value: @"value1"];
|
||||
testNotEqual([attrs objectForKey: @"attr1"], nil);
|
||||
testEqual([[attrs objectForKey: @"attr1"] count], 1);
|
||||
testStringsEqual([[attrs objectForKey: @"attr1"] objectAtIndex: 0],
|
||||
@"value1");
|
||||
|
||||
[element addAttribute: @"attr1" value: @"value2"];
|
||||
testEqual([[attrs objectForKey: @"attr1"] count], 2);
|
||||
testStringsEqual([[attrs objectForKey: @"attr1"] objectAtIndex: 0],
|
||||
@"value1");
|
||||
testStringsEqual([[attrs objectForKey: @"attr1"] objectAtIndex: 1],
|
||||
@"value2");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testAddAttributes
|
||||
{
|
||||
NSMutableDictionary *attrs, *addedAttrs;
|
||||
NSArray *keys;
|
||||
|
||||
attrs = (NSMutableDictionary *) [element attributes];
|
||||
keys = [attrs allKeys];
|
||||
testEqual([keys count], 0);
|
||||
|
||||
[attrs setObject: [NSMutableArray arrayWithObject: @"test1"]
|
||||
forKey: @"key1"];
|
||||
keys = [attrs allKeys];
|
||||
testEqual([keys count], 1);
|
||||
|
||||
addedAttrs = [NSMutableDictionary new];
|
||||
[addedAttrs setObject: [NSMutableArray arrayWithObject: @"test2"]
|
||||
forKey: @"key2"];
|
||||
[element addAttributes: addedAttrs];
|
||||
[addedAttrs release];
|
||||
keys = [attrs allKeys];
|
||||
testEqual([keys count], 2);
|
||||
testNotEqual([attrs objectForKey: @"key2"], nil);
|
||||
testStringsEqual([[attrs objectForKey: @"key2"] objectAtIndex: 0],
|
||||
@"test2");
|
||||
|
||||
testNotEqual([attrs objectForKey: @"key1"], nil);
|
||||
testStringsEqual([[attrs objectForKey: @"key1"] objectAtIndex: 0],
|
||||
@"test1");
|
||||
testEqual([[attrs objectForKey: @"key1"] count], 1);
|
||||
addedAttrs = [NSMutableDictionary new];
|
||||
[addedAttrs setObject: [NSMutableArray arrayWithObject: @"test3"]
|
||||
forKey: @"key1"];
|
||||
[element addAttributes: addedAttrs];
|
||||
[addedAttrs release];
|
||||
testStringsEqual([[attrs objectForKey: @"key1"] objectAtIndex: 1],
|
||||
@"test3");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testSetValue_To
|
||||
{
|
||||
NSArray *values;
|
||||
|
||||
values = [element values];
|
||||
testEqual([values count], 0);
|
||||
|
||||
[element setValue: 2 to: @"coucou"];
|
||||
testStringsEqual([values objectAtIndex: 0], @"");
|
||||
testStringsEqual([values objectAtIndex: 1], @"");
|
||||
testStringsEqual([values objectAtIndex: 2], @"coucou");
|
||||
|
||||
[element setValue: 0 to: @"cuicui"];
|
||||
testStringsEqual([values objectAtIndex: 0], @"cuicui");
|
||||
testStringsEqual([values objectAtIndex: 1], @"");
|
||||
testStringsEqual([values objectAtIndex: 2], @"coucou");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// BEGIN:VCALENDAR
|
||||
// CALSCALE:GREGORIAN
|
||||
// X-WR-TIMEZONE;VALUE=TEXT:Europe/Berlin
|
||||
// PRODID:-//Apple Computer\, Inc//iCal 1.0//EN
|
||||
// X-WR-CALNAME;VALUE=TEXT:shire-cal1
|
||||
// X-WR-RELCALID;VALUE=TEXT:C3CBA0E4-DBCC-11D6-A381-00039340AF4A
|
||||
// VERSION:2.0
|
||||
// BEGIN:VEVENT
|
||||
// DTSTAMP:20021008T155243Z
|
||||
// SUMMARY:work
|
||||
// UID:C3CB87C0-DBCC-11D6-A381-00039340AF4A
|
||||
// DTSTART;TZID=Europe/Berlin:20021009T120000
|
||||
// DURATION:PT3H45M
|
||||
// END:VEVENT
|
||||
// BEGIN:VEVENT
|
||||
// ATTENDEE;CN=Anja Berlin:mailto:anja.berlin@regiocom.net
|
||||
// ATTENDEE;CN=Marcus Müller:mailto:mm@codeon.de
|
||||
// DTSTAMP:20021009T211904Z
|
||||
// SUMMARY:trink
|
||||
// UID:C3CB8E9A-DBCC-11D6-A381-00039340AF4A
|
||||
// ORGANIZER;CN=Helge Heß:mailto:helge.hess@skyrix.com
|
||||
// DTSTART;TZID=Europe/Berlin:20021010T190000
|
||||
// DURATION:PT45M
|
||||
// BEGIN:VALARM
|
||||
// TRIGGER;VALUE=DURATION:-PT15M
|
||||
// ACTION:DISPLAY
|
||||
// DESCRIPTION:Event reminder
|
||||
// END:VALARM
|
||||
// BEGIN:VALARM
|
||||
// ATTACH;VALUE=URI:Ping
|
||||
// TRIGGER;VALUE=DURATION:-PT15M
|
||||
// ACTION:AUDIO
|
||||
// END:VALARM
|
||||
// END:VEVENT
|
||||
// BEGIN:VEVENT
|
||||
// DTSTAMP:20021008T155256Z
|
||||
// SUMMARY:Zahnarzt
|
||||
// DTEND;TZID=Europe/Berlin:20021009T110000
|
||||
// UID:C3CB92B0-DBCC-11D6-A381-00039340AF4A
|
||||
// DTSTART;TZID=Europe/Berlin:20021009T094500
|
||||
// END:VEVENT
|
||||
// BEGIN:VTODO
|
||||
// DTSTAMP:20021009T154221Z
|
||||
// SUMMARY:testjob
|
||||
// UID:C3CB96C7-DBCC-11D6-A381-00039340AF4A
|
||||
// DUE;TZID=Europe/Berlin:20021011T175228
|
||||
// PRIORITY:5
|
||||
// DTSTART;TZID=Europe/Berlin:20021008T175228
|
||||
// END:VTODO
|
||||
// BEGIN:VTODO
|
||||
// UID:C3CB9A9F-DBCC-11D6-A381-00039340AF4A
|
||||
// DTSTART;TZID=Europe/Berlin:20021010T000000
|
||||
// DTSTAMP:20021009T154205Z
|
||||
// SUMMARY:testjob2
|
||||
// END:VTODO
|
||||
// END:VCALENDAR
|
||||
|
||||
@end
|
||||
|
||||
int main (int argc, char **argv, char **env)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
subtest *test;
|
||||
int rc;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
|
||||
#endif
|
||||
|
||||
test = [subtest new];
|
||||
if (test) {
|
||||
NS_DURING
|
||||
[test run];
|
||||
NS_HANDLER
|
||||
abort();
|
||||
NS_ENDHANDLER;
|
||||
|
||||
[test release];
|
||||
}
|
||||
else
|
||||
rc = 1;
|
||||
|
||||
[pool release];
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
Copyright (C) 2005 Helge Hess
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
// Note: this does not yet produce valid XML output
|
||||
|
||||
#import <Foundation/NSObject.h>
|
||||
#include <SaxObjC/SaxObjC.h>
|
||||
|
||||
@interface vcf2xml : NSObject
|
||||
{
|
||||
id<NSObject,SaxXMLReader> parser;
|
||||
id sax;
|
||||
}
|
||||
|
||||
- (int)runWithArguments:(NSArray *)_args;
|
||||
|
||||
@end
|
||||
|
||||
#include "common.h"
|
||||
|
||||
@interface MySAXHandler : SaxDefaultHandler
|
||||
{
|
||||
id locator;
|
||||
int indent;
|
||||
|
||||
NSString *lastNS;
|
||||
}
|
||||
|
||||
- (void)indent;
|
||||
|
||||
@end
|
||||
|
||||
@implementation vcf2xml
|
||||
|
||||
- (id)init {
|
||||
if ((self = [super init]) != nil) {
|
||||
self->parser = [[[SaxXMLReaderFactory standardXMLReaderFactory]
|
||||
createXMLReaderForMimeType:@"text/x-vcard"] retain];
|
||||
if (parser == nil) {
|
||||
fprintf(stderr, "Error: could not load a vCard SAX driver bundle!\n");
|
||||
exit(2);
|
||||
}
|
||||
//NSLog(@"Using parser: %@", self->parser);
|
||||
|
||||
self->sax = [[MySAXHandler alloc] init];
|
||||
[parser setContentHandler:self->sax];
|
||||
[parser setErrorHandler:self->sax];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self->sax release];
|
||||
[self->parser release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* process files */
|
||||
|
||||
- (void)processFile:(NSString *)_path {
|
||||
[self->parser parseFromSystemId:_path];
|
||||
}
|
||||
|
||||
/* error handling */
|
||||
|
||||
- (NSException *)handleException:(NSException *)_exc onPath:(NSString *)_p {
|
||||
fprintf(stderr, "Error: catched exception on path '%s': %s\n",
|
||||
[_p cString], [[_exc description] cString]);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* main entry */
|
||||
|
||||
- (int)runWithArguments:(NSArray *)_args {
|
||||
NSEnumerator *args;
|
||||
NSString *arg;
|
||||
|
||||
/* begin processing */
|
||||
|
||||
args = [_args objectEnumerator];
|
||||
[args nextObject]; // skip tool name ...
|
||||
|
||||
while ((arg = [args nextObject]) != nil) {
|
||||
NSAutoreleasePool *pool2;
|
||||
|
||||
if ([arg hasPrefix:@"-"]) { /* consume defaults */
|
||||
[args nextObject];
|
||||
continue;
|
||||
}
|
||||
|
||||
pool2 = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
if (![arg isAbsolutePath]) {
|
||||
arg = [[[NSFileManager defaultManager] currentDirectoryPath]
|
||||
stringByAppendingPathComponent:arg];
|
||||
}
|
||||
|
||||
NS_DURING
|
||||
[self->parser parseFromSystemId:arg];
|
||||
NS_HANDLER
|
||||
[[self handleException:localException onPath:arg] raise];
|
||||
NS_ENDHANDLER;
|
||||
|
||||
[pool2 release];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end /* vcf2xml */
|
||||
|
||||
|
||||
@implementation MySAXHandler
|
||||
|
||||
- (void)dealloc {
|
||||
[self->lastNS release];
|
||||
[self->locator release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* output */
|
||||
|
||||
- (void)indent {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (self->indent * 4); i++)
|
||||
fputc(' ', stdout);
|
||||
}
|
||||
|
||||
/* documents */
|
||||
|
||||
- (void)setDocumentLocator:(id<NSObject,SaxLocator>)_loc {
|
||||
[self->locator autorelease];
|
||||
self->locator = [_loc retain];
|
||||
}
|
||||
|
||||
- (void)startDocument {
|
||||
//puts("start document ..");
|
||||
//self->indent++;
|
||||
}
|
||||
- (void)endDocument {
|
||||
//self->indent--;
|
||||
//puts("end document.");
|
||||
}
|
||||
|
||||
- (void)startPrefixMapping:(NSString *)_prefix uri:(NSString *)_uri {
|
||||
[self indent];
|
||||
//printf("ns-map: %s=%s\n", [_prefix cString], [_uri cString]);
|
||||
}
|
||||
- (void)endPrefixMapping:(NSString *)_prefix {
|
||||
[self indent];
|
||||
//printf("ns-unmap: %s\n", [_prefix cString]);
|
||||
}
|
||||
|
||||
- (void)startElement:(NSString *)_localName
|
||||
namespace:(NSString *)_ns
|
||||
rawName:(NSString *)_rawName
|
||||
attributes:(id<SaxAttributes>)_attrs
|
||||
{
|
||||
int i, c;
|
||||
[self indent];
|
||||
printf("<%s", [_localName cString]);
|
||||
|
||||
if ([_ns length] > 0) {
|
||||
if ([_ns isEqualToString:self->lastNS])
|
||||
;
|
||||
else {
|
||||
printf(" xmlns='%s'", [_ns cString]);
|
||||
ASSIGNCOPY(self->lastNS, _ns);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, c = [_attrs count]; i < c; i++) {
|
||||
NSString *type;
|
||||
NSString *ans;
|
||||
|
||||
ans = [_attrs uriAtIndex:i];
|
||||
|
||||
printf(" %s=\"%s\"",
|
||||
[[_attrs nameAtIndex:i] cString],
|
||||
[[_attrs valueAtIndex:i] cString]);
|
||||
|
||||
if (![_ns isEqualToString:ans])
|
||||
printf("(ns=%s)", [ans cString]);
|
||||
|
||||
type = [_attrs typeAtIndex:i];
|
||||
if (![type isEqualToString:@"CDATA"] && (type != nil))
|
||||
printf("[%s]", [type cString]);
|
||||
}
|
||||
puts(">");
|
||||
self->indent++;
|
||||
}
|
||||
- (void)endElement:(NSString *)_localName
|
||||
namespace:(NSString *)_ns
|
||||
rawName:(NSString *)_rawName
|
||||
{
|
||||
self->indent--;
|
||||
[self indent];
|
||||
printf("</%s>\n", [_localName cString]);
|
||||
}
|
||||
|
||||
- (void)characters:(unichar *)_chars length:(int)_len {
|
||||
NSString *str;
|
||||
id tmp;
|
||||
unsigned i, len;
|
||||
|
||||
if (_len == 0) {
|
||||
[self indent];
|
||||
printf("\"\"\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < (unsigned)_len; i++) {
|
||||
if (_chars[i] > 255) {
|
||||
NSLog(@"detected large char: o%04o d%03i h%04X",
|
||||
_chars[i], _chars[i], _chars[i]);
|
||||
}
|
||||
}
|
||||
|
||||
str = [NSString stringWithCharacters:_chars length:_len];
|
||||
len = [str length];
|
||||
|
||||
tmp = [str componentsSeparatedByString:@"\n"];
|
||||
str = [tmp componentsJoinedByString:@"\\n"];
|
||||
tmp = [str componentsSeparatedByString:@"\r"];
|
||||
str = [tmp componentsJoinedByString:@"\\r"];
|
||||
|
||||
[self indent];
|
||||
printf("\"%s\"\n", [str cString]);
|
||||
}
|
||||
- (void)ignorableWhitespace:(unichar *)_chars length:(int)_len {
|
||||
NSString *data;
|
||||
id tmp;
|
||||
|
||||
data = [NSString stringWithCharacters:_chars length:_len];
|
||||
tmp = [data componentsSeparatedByString:@"\n"];
|
||||
data = [tmp componentsJoinedByString:@"\\n"];
|
||||
tmp = [data componentsSeparatedByString:@"\r"];
|
||||
data = [tmp componentsJoinedByString:@"\\r"];
|
||||
|
||||
[self indent];
|
||||
printf("whitespace: \"%s\"\n", [data cString]);
|
||||
}
|
||||
|
||||
- (void)processingInstruction:(NSString *)_pi data:(NSString *)_data {
|
||||
[self indent];
|
||||
printf("PI: '%s' '%s'\n", [_pi cString], [_data cString]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
- (xmlEntityPtr)getEntity:(NSString *)_name {
|
||||
NSLog(@"get entity %@", _name);
|
||||
return NULL;
|
||||
}
|
||||
- (xmlEntityPtr)getParameterEntity:(NSString *)_name {
|
||||
NSLog(@"get para entity %@", _name);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* entities */
|
||||
|
||||
- (id)resolveEntityWithPublicId:(NSString *)_pubId
|
||||
systemId:(NSString *)_sysId
|
||||
{
|
||||
[self indent];
|
||||
printf("shall resolve entity with '%s' '%s'",
|
||||
[_pubId cString], [_sysId cString]);
|
||||
return nil;
|
||||
}
|
||||
|
||||
/* errors */
|
||||
|
||||
- (void)warning:(SaxParseException *)_exception {
|
||||
NSLog(@"warning(%@:%i): %@",
|
||||
[[_exception userInfo] objectForKey:@"publicId"],
|
||||
[[[_exception userInfo] objectForKey:@"line"] intValue],
|
||||
[_exception reason]);
|
||||
}
|
||||
|
||||
- (void)error:(SaxParseException *)_exception {
|
||||
NSLog(@"error(%@:%i): %@",
|
||||
[[_exception userInfo] objectForKey:@"publicId"],
|
||||
[[[_exception userInfo] objectForKey:@"line"] intValue],
|
||||
[_exception reason]);
|
||||
}
|
||||
|
||||
- (void)fatalError:(SaxParseException *)_exception {
|
||||
NSLog(@"fatal error(%@:%i): %@",
|
||||
[[_exception userInfo] objectForKey:@"publicId"],
|
||||
[[[_exception userInfo] objectForKey:@"line"] intValue],
|
||||
[_exception reason]);
|
||||
[_exception raise];
|
||||
}
|
||||
|
||||
@end /* MySAXHandler */
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
NSAutoreleasePool *pool;
|
||||
vcf2xml *tool;
|
||||
int rc;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
|
||||
#endif
|
||||
|
||||
if ((tool = [[vcf2xml alloc] init])) {
|
||||
NS_DURING
|
||||
rc = [tool runWithArguments:[[NSProcessInfo processInfo] arguments]];
|
||||
NS_HANDLER
|
||||
abort();
|
||||
NS_ENDHANDLER;
|
||||
|
||||
[tool release];
|
||||
}
|
||||
else
|
||||
rc = 1;
|
||||
|
||||
[pool release];
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
Copyright (C) 2005 Helge Hess
|
||||
|
||||
This file is part of SOPE.
|
||||
|
||||
SOPE 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 2, or (at your option) any
|
||||
later version.
|
||||
|
||||
SOPE 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 SOPE; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <NGCards/NGVCard.h>
|
||||
|
||||
@interface vcsparsetest : NSObject
|
||||
{
|
||||
}
|
||||
|
||||
- (int)runWithArguments:(NSArray *)_args;
|
||||
|
||||
@end
|
||||
|
||||
@implementation vcsparsetest
|
||||
|
||||
- (id)init {
|
||||
if ((self = [super init])) {
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* parsing */
|
||||
|
||||
- (id)parseFile:(NSString *)_path {
|
||||
if ([_path length] == 0) return nil;
|
||||
return [NGVCard parseVCardsFromSource:[NSURL fileURLWithPath:_path]];
|
||||
}
|
||||
|
||||
- (void)printParsedObject: (NSArray *)_cards
|
||||
{
|
||||
NSEnumerator *cardObjects;
|
||||
NGVCard *card;
|
||||
|
||||
cardObjects = [_cards objectEnumerator];
|
||||
card = [cardObjects nextObject];
|
||||
while (card)
|
||||
{
|
||||
NSLog (@"-------s\n%@\ne-------", [card versitString]);
|
||||
card = [cardObjects nextObject];
|
||||
}
|
||||
|
||||
#if 0
|
||||
NSLog(@" subcomponents: %@", [_object subComponents]);
|
||||
|
||||
printf("%s", [[_object icalString] cString]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* run */
|
||||
|
||||
- (int)runWithArguments:(NSArray *)_args {
|
||||
NSEnumerator *args;
|
||||
NSString *arg;
|
||||
|
||||
args = [_args objectEnumerator];
|
||||
[args nextObject]; // process name ...
|
||||
|
||||
while ((arg = [args nextObject])) {
|
||||
NSAutoreleasePool *pool2;
|
||||
|
||||
if ([arg hasPrefix:@"-"]) { /* consume defaults */
|
||||
[args nextObject];
|
||||
continue;
|
||||
}
|
||||
|
||||
pool2 = [[NSAutoreleasePool alloc] init];
|
||||
{
|
||||
NSArray *cards;
|
||||
|
||||
NS_DURING
|
||||
cards = [self parseFile:arg];
|
||||
NS_HANDLER
|
||||
abort();
|
||||
NS_ENDHANDLER;
|
||||
|
||||
if (!cards)
|
||||
NSLog(@"could not parse file: '%@'", arg);
|
||||
else
|
||||
[self printParsedObject:cards];
|
||||
}
|
||||
[pool2 release];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end /* vcsparsetest */
|
||||
|
||||
int main(int argc, char **argv, char **env) {
|
||||
NSAutoreleasePool *pool;
|
||||
vcsparsetest *tool;
|
||||
int rc;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
[NSProcessInfo initializeWithArguments:argv count:argc environment:env];
|
||||
#endif
|
||||
|
||||
if ((tool = [[vcsparsetest alloc] init]) != nil) {
|
||||
NS_DURING
|
||||
rc = [tool runWithArguments:[[NSProcessInfo processInfo] arguments]];
|
||||
NS_HANDLER
|
||||
abort();
|
||||
NS_ENDHANDLER;
|
||||
|
||||
[tool release];
|
||||
}
|
||||
else
|
||||
rc = 1;
|
||||
|
||||
[pool release];
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
/* versittest.m - this file is part of $PROJECT_NAME_HERE$
|
||||
*
|
||||
* Copyright (C) 2006 Inverse groupe conseil
|
||||
*
|
||||
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This file 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "CardElement.h"
|
||||
#import "CardGroup.h"
|
||||
#import "CardVersitRenderer.h"
|
||||
#import "NSString+NGCards.h"
|
||||
|
||||
#import "unittest.h"
|
||||
|
||||
@interface versittest : unittest
|
||||
|
||||
@end
|
||||
|
||||
@implementation versittest
|
||||
|
||||
- (BOOL) testRendering
|
||||
{
|
||||
NSLog (@"rendering>");
|
||||
CardVersitRenderer *renderer;
|
||||
CardGroup *g, *g2;
|
||||
CardElement *e;
|
||||
|
||||
g = [CardGroup groupWithTag: @"VCALENDAR"];
|
||||
e = [CardElement simpleElementWithTag: @"CALSCALE"
|
||||
value: @"GREGORIAN"];
|
||||
[g addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"X-WR-TIMEZONE"
|
||||
value: @"Europe/Berlin"];
|
||||
[e addAttribute: @"VALUE" value: @"TEXT"];
|
||||
[g addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"PRODID"
|
||||
value: @"-//Apple Computer, Inc//iCal 1.0//EN"];
|
||||
[g addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"X-WR-CALNAME"
|
||||
value: @"shire-cal1"];
|
||||
[e addAttribute: @"VALUE" value: @"TEXT"];
|
||||
[e setGroup: @"item1"];
|
||||
[g addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"X-WR-RELCALID"
|
||||
value: @"C3CBA0E4-DBCC-11D6-A381-00039340AF4A"];
|
||||
[e addAttribute: @"VALUE" value: @"TEXT"];
|
||||
[g addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"VERSION"
|
||||
value: @"2.0"];
|
||||
[g addChild: e];
|
||||
|
||||
g2 = [CardGroup groupWithTag: @"VEVENT"];
|
||||
e = [CardElement simpleElementWithTag: @"DTSTAMP"
|
||||
value: @"20021008T155243Z"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"SUMMARY"
|
||||
value: @"work"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"UID"
|
||||
value: @"C3CB87C0-DBCC-11D6-A381-00039340AF4A"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"DTSTART"
|
||||
value: @"20021009T120000"];
|
||||
[e addAttribute: @"TZID" value: @"Europe/Berlin"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"DURATION"
|
||||
value: @"PT3H45M"];
|
||||
[g2 addChild: e];
|
||||
[g addChild: g2];
|
||||
|
||||
g2 = [CardGroup groupWithTag: @"VEVENT"];
|
||||
e = [CardElement simpleElementWithTag: @"ATTENDEE"
|
||||
value: @"mailto:anja.berlin@regiocom.net"];
|
||||
[e addAttribute: @"CN" value: @"Anja Berlin"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"ATTENDEE"
|
||||
value: @"mailto:mm@codeon.de"];
|
||||
[e addAttribute: @"CN" value: @"Marcus Müller"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"DTSTAMP"
|
||||
value: @"20021009T211904Z"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"SUMMARY"
|
||||
value: @"trink"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"UID"
|
||||
value: @"C3CB8E9A-DBCC-11D6-A381-00039340AF4A"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"ORGANIZER"
|
||||
value: @"mailto:helge.hess@skyrix.com"];
|
||||
[e addAttribute: @"CN" value: @"Helge Heß"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"DTSTART"
|
||||
value: @"20021010T190000"];
|
||||
[e addAttribute: @"TZID" value: @"Europe/Berlin"];
|
||||
[g2 addChild: e];
|
||||
e = [CardElement simpleElementWithTag: @"DURATION"
|
||||
value: @"PT45M"];
|
||||
[g2 addChild: e];
|
||||
[g addChild: g2];
|
||||
|
||||
renderer = [CardVersitRenderer new];
|
||||
NSLog (@"\n\n%@\n", [renderer render: g]);
|
||||
[renderer release];
|
||||
|
||||
NSLog (@"<done");
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testNSStringFoldedForVersitCards
|
||||
{
|
||||
NSString *shortString, *longString, *foldedString;
|
||||
|
||||
shortString = @"PATATE";
|
||||
testStringsEqual(shortString, [shortString foldedForVersitCards]);
|
||||
|
||||
longString = @"blabla PATATE blabla PATATE blabla PATATE blabla PATATE blabla PATATE blabl"
|
||||
@"a PATATE blabla PATATE blabla PATATE blabla PATATE blabla PATATE blabla PA"
|
||||
@"TATE blabla PATATE blabla PATATE blabla PATATE blabla PATATE blabla PATATE"
|
||||
@"blabla PATATE blabla PATATE blabla PATATE";
|
||||
|
||||
foldedString = @"blabla PATATE blabla PATATE blabla PATATE blabla PATATE blabla PATATE blabl\r\n"
|
||||
@" a PATATE blabla PATATE blabla PATATE blabla PATATE blabla PATATE blabla PA\r\n"
|
||||
@" TATE blabla PATATE blabla PATATE blabla PATATE blabla PATATE blabla PATATE\r\n"
|
||||
@" blabla PATATE blabla PATATE blabla PATATE";
|
||||
|
||||
testStringsEqual(foldedString, [longString foldedForVersitCards]);
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) testNSStringAsCardValues
|
||||
{
|
||||
NSString *values[5];
|
||||
NSArray *array[5];
|
||||
NSArray *testarray[5];
|
||||
unsigned int i, count, max;
|
||||
|
||||
// patate,pouetpouet
|
||||
values[0] = @"patate,pouetpouet";
|
||||
// patate\,pouetpouet
|
||||
values[1] = @"patate\\,pouetpouet";
|
||||
// patate\\,pouetpouet
|
||||
values[2] = @"patate\\\\,pouetpouet";
|
||||
// patate\\\,pouetpouet
|
||||
values[3] = @"patate\\\\\\,pouetpouet";
|
||||
// patate,pouetpouet
|
||||
values[4] = @"patate, pouetpouet";
|
||||
|
||||
testarray[0] = [NSArray arrayWithObjects: @"patate", @"pouetpouet", nil];
|
||||
testarray[1] = [NSArray arrayWithObjects: @"patate,pouetpouet", nil];
|
||||
// should give [ @"patate\\", @"pouetpouet" ] instead...:
|
||||
testarray[2] = [NSArray arrayWithObjects: @"patate\\,pouetpouet", nil];
|
||||
testarray[3] = [NSArray arrayWithObjects: @"patate\\\\,pouetpouet", nil];
|
||||
testarray[4] = [NSArray arrayWithObjects: @"patate", @"pouetpouet", nil];
|
||||
|
||||
for (i = 0; i < (sizeof(values) / sizeof(NSString *)); i++)
|
||||
{
|
||||
array[i] = [values[i] asCardAttributeValues];
|
||||
max = [testarray[i] count];
|
||||
for (count = 0; count < max; count++)
|
||||
testStringsEqual([testarray[i] objectAtIndex: count],
|
||||
[array[i] objectAtIndex: count]);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main (int argc, char **argv, char **env)
|
||||
{
|
||||
NSAutoreleasePool *pool;
|
||||
versittest *test;
|
||||
int rc;
|
||||
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
#if LIB_FOUNDATION_LIBRARY
|
||||
[NSProcessInfo initializeWithArguments: argv
|
||||
count: argc
|
||||
environment: env];
|
||||
#endif
|
||||
|
||||
test = [versittest new];
|
||||
if (test) {
|
||||
NS_DURING
|
||||
[test run];
|
||||
NS_HANDLER
|
||||
abort();
|
||||
NS_ENDHANDLER;
|
||||
|
||||
[test release];
|
||||
}
|
||||
else
|
||||
rc = 1;
|
||||
|
||||
[pool release];
|
||||
|
||||
return rc;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>NGiCalTests</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.OpenGroupware.SOPE.ical.NGiCalTests</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string></string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>4.5</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,8 @@
|
|||
This folder contains unit tests for the NGiCal project.
|
||||
|
||||
It uses SEN:TE's OCUnit project which can be found at
|
||||
http://www.sente.ch/software/ocunit/
|
||||
|
||||
I used OCUnitRoot v38, later versions might work as well.
|
||||
|
||||
NOTE: This is currently provided in Xcode only.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue