Commit Graph

275 Commits

Author SHA1 Message Date
nathangray
5fd41d95b4 Calendar - make sure notification links open properly (missing an ajax=true) 2017-09-28 10:38:31 -06:00
Ralf Becker
8dba9967e3 * Calendar/CalDAV: do not report non-participants as busy or conflict 2017-08-18 10:00:37 +02:00
nathangray
1d6fcf3f68 Change recurrence end date comparison to handle up to 1 second difference, for mix of old and new events
see 2f534beb34
2017-08-17 14:02:26 -06:00
nathangray
64a12f1ddd Calendar - fix bug in recurring event exception edit across timezones causing events to move or get lost 2017-07-31 12:39:15 -06:00
nathangray
a44bdb99f9 * Calendar - Fix edit via emailed notification link did not work properly 2017-06-22 11:07:42 -06:00
nathangray
af2ff1859c Calendar - All tests passing for daily recurring events, all day and otherwise 2017-06-07 13:19:20 -06:00
nathangray
191b129201 Calendar - Discrete (not all day) events working for all timezone combinations 2017-06-06 15:03:14 -06:00
nathangray
2bfd1c4aa9 Calendar - Ok, working for Edmonton & Berlin... 2017-06-01 11:20:38 -06:00
nathangray
11f3719348 Calendar - change how we're dealing with (all day) timezones, keeping the event in the assigned timezone instead of always changing it to the server timezone. 2017-05-31 09:55:41 -06:00
nathangray
9cf6685a77 Calendar - all day recurring events would extend one day longer for some timezone combinations 2017-05-23 13:37:34 -06:00
Hadi Nategh
479a557381 WIP of Notifications system:
- Add actions for notification messages
- Fix on message click handler
- Implement appointment request actions for calendar notifications
2017-05-23 16:54:20 +02:00
nathangray
8e13f3977f Calendar - Fix daily recurring recur end date got one day later when you save if timezone was Tahiti 2017-05-11 19:15:10 +02:00
nathangray
2f534beb34 Calendar - Update recurrence adjustment check to match range end change from 9810077eab 2017-03-31 10:27:49 -06:00
Ralf Becker
9810077eab * Calendar/CalDAV: fix wrong end-date of recurring events incl. whole-day events 2017-03-29 19:32:49 +02:00
nathangray
5946e9f7cd Avoid errors if $instance_date is not passed correctly
(thanks, Scrutenizer)
2017-01-31 09:14:50 -07:00
Ralf Becker
55edf5cfea fix warnings when importing events: $ignore_acl=true and only cal_id given 2017-01-19 11:11:40 +01:00
Ralf Becker
afaa722c47 modifications to allow exporting of all calendar entries via stylite/migrate.php script, added cal_deleted as timestamp and support again setting $updateTS=false in calendar_boupdate::save() 2017-01-18 18:31:47 +01:00
nathangray
aa63949012 Update notification popup to fit theme better 2017-01-10 11:42:44 -07:00
Ralf Becker
315ceed672 error_log if calendar can not send notifications 2016-10-06 19:09:40 +02:00
Hadi Nategh
df102aa04d * Calendar: Fix calendar to-firstname to-lastname place-holders do not get values 2016-10-04 16:39:28 +02:00
nathangray
87226bfbcb Change handling of new private events created for other users to allow them to show immediately 2016-09-15 10:46:11 -06:00
nathangray
fada2d433e When adding a mailing list as participant, immediately expand it to contacts 2016-07-12 11:22:36 -06:00
nathangray
76307c4bbf Allow contact lists as event participants 2016-07-06 13:19:54 -06:00
Ralf Becker
5374b39680 1) skip all past events and recurrences in conflict check and fix off-by-one error in recurrence limit
2) restructure config a bit:
- rename Birthday section to Addressbook
- rename Scheduling conflict section to Recurrences and conflict check
- add: Please note: conflict check is never done in the past and always limited by above recurrence horizont.
2016-07-06 16:44:06 +02:00
Ralf Becker
b4017cb8c4 * Calendar: check recurrences for conflicts too (until configured search-time is exceeded, default 3s) 2016-07-06 12:46:00 +02:00
nathangray
7e0b2543d0 Fix fatal error, get_account_name() does not exist 2016-05-16 10:13:22 -06:00
Nathan Gray
9859cfa679 Fix fatal error caused by moved Categories 2016-05-05 16:56:25 +00:00
Ralf Becker
dcc003cedf move calendar to new api 2016-05-01 17:47:59 +00:00
Ralf Becker
6f0728cd9d fix for different return values of accounts->member(s) / membership(s) 2016-03-06 16:09:58 +00:00
Ralf Becker
3971dd8915 fix use of deprecated accounts::member and accounts::membership, should be members and memberships 2016-03-06 14:58:36 +00:00
Nathan Gray
26f4c6556b Fix changing status sometimes changed time(zone) 2016-02-10 00:19:55 +00:00
Nathan Gray
f438940598 Fix alarms not updated when event is moved 2016-01-18 17:45:25 +00:00
Nathan Gray
b034eeac92 Fix changing recurring end date to earlier always gave one extra recurrence 2015-11-24 18:15:11 +00:00
Ralf Becker
66581cee3f * Calendar/CalDAV/iMip: only include replying participant in iMip REPLY messages 2015-10-14 16:39:39 +00:00
Ralf Becker
17b9b5912e fix warning if there are no participants 2015-09-29 07:31:45 +00:00
Ralf Becker
beb829c315 drop contenthistroy class and table (egw_api_content_history) formerly used by SyncML 2015-08-18 11:45:59 +00:00
Ralf Becker
9ef2cbd98a * Mail/Kalendar: remove iCal from alarms and correctly display canceled events in mail 2015-07-16 09:34:55 +00:00
Ralf Becker
6d2ef17b0f * CalDAV/Calendar: storing now all properties send by client and not known to EGroupware and fixed acknowledging and snoozing of alarms 2015-06-25 20:39:53 +00:00
Nathan Gray
e6f1f8f837 - Fix $$Recurrence$$ notification placeholder to be empty (not missing) for non-recurring events
- Avoid warning in get_link_options by making unused parameter optional
2015-03-23 19:58:58 +00:00
Ralf Becker
de4d246726 * Calendar: speed improvments for huge calendar databases
by using time-range views instead of whole calendar and dates table
Also got old, much simpler non-union code working again, but union is still slightly quicker for huge databases (not at all for small ones!)
2015-01-19 19:32:26 +00:00
Ralf Becker
4e27f324c9 improved method to query events with performance gains of a factor 10 on huge databases, currently only used in conflict check 2015-01-14 19:41:01 +00:00
Ralf Becker
a35590b8fe fix replacementes in update messages 2014-10-09 13:52:14 +00:00
Ralf Becker
4c15c2f2de * Calendar/API: allow not serialized data in async jobs, only run automatic purge if we have a real number > 0 2014-07-02 12:42:12 +00:00
Klaus Leithoff
00881d1c94 silence some warnings on mail-to-all-participants 2014-03-20 16:10:52 +00:00
Ralf Becker
866d680e6a fixed iCal and iMip method and notification text for initial responses to organizer to be replys (not added=invitation) 2014-02-20 16:14:32 +00:00
Ralf Becker
90c89e0eb7 * CalDAV/Calendar: sending now iMip response to external organizer when initialy accepting invitation via CalDAV client (before only status changes where sent) 2014-02-20 15:04:47 +00:00
Hadi Nategh
874b4b594f Fix warning "Argument #1 is not an array" in calendar conflict 2014-02-12 11:59:32 +00:00
Ralf Becker
fe2438cc53 * Calendar: automatic cancel alarms from removed or rejected participants 2013-08-15 14:56:34 +00:00
Ralf Becker
012e2e4763 * Calendar: when moving a series exceptions where lost (regular recurrences shown again) and exceptions where moved too 2013-08-15 12:23:38 +00:00
Ralf Becker
1b9c105198 * Calendar: changing an existing, recurring event to whole-day, caused an end-time on day before start 2013-06-07 11:53:45 +00:00
Ralf Becker
86d54d092c * Calendar: configuration to automatic create links for participants from addressbook 2013-06-04 18:00:39 +00:00
Ralf Becker
32751c69b6 no more querying of recurrences for etag of series master, as all update methods now update modification time of series master for recurrenc-exceptions 2013-02-26 08:48:50 +00:00
Ralf Becker
a8e6f13304 * Calendar/CalDAV: fixed wrong time in notification mails caused by updates via CalDAV (not web interface), if user-timezone differs from server 2013-01-31 15:15:48 +00:00
Klaus Leithoff
435f726bf9 select priority should map 0 to None, not empty 2013-01-31 14:13:45 +00:00
Nathan Gray
872fe5918e Some missed skip_notifications 2012-12-18 16:00:29 +00:00
Klaus Leithoff
0be74c9b87 different method to read the next occourrence of a series; (as old method also fetched deleted exeptions as next occurrence) 2012-12-07 14:10:51 +00:00
Klaus Leithoff
83981b9cad * Calendar: fix for missing 2568to-firstname2568 and 2568to-lastname2568 replacements 2012-12-06 12:01:05 +00:00
Ralf Becker
ae28edb43a * Calendar: notify responsible for a resource "participating" in a private event only with privacy-cleared details 2012-11-13 13:31:44 +00:00
Ralf Becker
f8a007bad4 * Calendar/CalDAV/eSync: fixed exceptions get not deleted with series via CalDAV or eSync
moved code from our UI to BO, to either delete exceptions (default) or keep them with a new UID
2012-10-22 13:15:40 +00:00
Ralf Becker
49f1d43ad1 * Calendar: fixed recuring event lost start-date, if single recurrence got deleted, also installed save-guard in case other code triggers that too
caused by storing an event with unset start- or end-date, to not write it
2012-10-02 16:43:49 +00:00
Ralf Becker
7ade6b4f55 * Calendar: popup notifications now include a link again 2012-09-04 12:10:37 +00:00
Ralf Becker
1b3e897eec * Calendar: fixed since last update missing event details, notification iCal adds description with (required) *~*~*~*~*~*~*~*~*~* separator, extended has description before event details and links 2012-08-21 14:49:26 +00:00
Ralf Becker
df83423ca3 * Calendar: if deleting next recurrance of an event series containing alarms, move alarms to next recurrance, to not alarm for deleted recurance 2012-08-14 17:02:34 +00:00
Ralf Becker
4ac5e799eb fixed some more "Illegal string offset" 2012-08-14 07:55:05 +00:00
Ralf Becker
56a4bdfbbe * Calendar: fixed issue of deleted first recurrence shortens event and causes it not to be find in CalDAV or eSync ("event has exceptions before startdate"), REQUIRES SCHEMA UPDATE (visit setup)! 2012-08-11 10:01:02 +00:00
Ralf Becker
cff9872f17 cast accounts->members(hips) to array, to cope without PHP warnings for not (longer) existing accounts 2012-08-09 08:41:29 +00:00
Ralf Becker
eff584ff4b * Calendar/eSync/CalDAV: meeting requests contain again nice body followed by a separator and describtion, ignore empty description in eSync ChangeMessage 2012-07-24 22:23:32 +00:00
Ralf Becker
f8ae428f32 * Calendar: fixed EGroupware owner got notified about status changes, even if email-notification preference was "never", now only external chairs get always notified 2012-07-17 12:36:48 +00:00
Ralf Becker
68f9a07917 as we want ical body to be just describtion, we can NOT set links, as they get appended to body 2012-07-17 09:48:43 +00:00
Ralf Becker
e09a9c3198 fixed 5.4 PHP Warning: Illegal string offset 'start' or 'end' 2012-07-02 08:14:27 +00:00
Klaus Leithoff
0a076525b8 improve notification by allowing to set up specific popup notification messages and subjects; this is used for calendar notification to give worthwile information in popup and meet expectations for ical/rfc type notification 2012-06-13 14:50:41 +00:00
Ralf Becker
fc7dfc1ab6 * Calendar: notifications of type iCal use event-title as subject and describtion as body, like Exchange does, type extended provides old format 2012-06-12 16:59:06 +00:00
Klaus Leithoff
2da30ad703 fix of typos 2012-06-12 16:17:25 +00:00
Ralf Becker
313eb12f19 bocalendar_update::email_update_requested() allowing eSync to check if calendar will send a notification according to preferences 2012-06-12 15:44:55 +00:00
Ralf Becker
2f81eea8ef fixed only partially translated alarms 2012-05-15 14:41:41 +00:00
Ralf Becker
4ea76b4a95 need to init lang even earlier 2012-05-15 12:48:45 +00:00
Ralf Becker
6d1dc16ac3 * Calendar: notification always use language of current user, not of user to notify 2012-05-15 12:43:32 +00:00
Ralf Becker
8c6341d551 * Calendar/EMail: when accepting email invitation from organizer who is an EGroupware user but created invitation outside: if no access to organizers calendar, make organizer a participant with role CHAIR
- show errors from calendar_boupdate::update()
2012-04-24 14:37:32 +00:00
Ralf Becker
1fc54e038b * Calendar: fixed wrong time in iCal of notification, if notifying user is not in server TZ
we need to pass $event[id] so iCal class reads event again, as event is in user TZ, but iCal class expects server TZ!
2012-01-23 02:43:06 +00:00
Ralf Becker
7630f59a13 * Calendar: new (forcable) user preference to notify external participants (non-EGroupware users), event owner has to set it, it is off by default, to keep the current behavior of not notifying externals 2012-01-05 05:47:02 +00:00
Ralf Becker
68dd900091 * Calendar: fixed groupmembers cant accept/reject group-invitations in listview via context-menu (error: failed because of insufficient rights!) 2011-11-21 14:25:44 +00:00
Ralf Becker
89ed7d49d1 fixed alarm on series got lost, if creating an exception 2011-11-11 12:46:34 +00:00
Ralf Becker
684d23326e * Calendar: fixed MyStylite bug #2434: context menu could be used to invite yourself to any event you can read 2011-11-09 09:44:28 +00:00
Ralf Becker
3819816248 * Calendar: fixed various issues with history in calendar: id display, unecessary stuff loged, ... 2011-08-04 14:00:15 +00:00
Ralf Becker
f65fd9129f * Calendar: added purge interval of half a year 2011-06-14 18:16:08 +00:00
Ralf Becker
145cf9ce68 New method to display meeting-requests for fmail and allow to (tentativ) accept or reject them 2011-05-27 20:32:46 +00:00
Ralf Becker
30259bfd4c * Calendar: fixed not included organizer in meeting request 2011-05-26 10:48:57 +00:00
Ralf Becker
678d0ed937 AS supports now two types of meeting requests:
a) meeting request arriving per mail via felamimail_activesync::GetMessage(List)
b) EGw internal meeting requests via calendar_activesync::GetMeetingRequest(s)
EGw backend returns both via INBOX to the client device (b) with negative id's to not conflict with mail uid's)
MettingResponse method in EGw backend calls calendar or fmail depending on id
Unfortunately this is NOT yet completly working:
- could not test with fmail, as I have no permanent internet access
- MeetingResponse method of calendar get never called, in fact client never sends one :-(
- meeting requests via calendar a now displayed double:
  a) via calendar_activesync::GetMessage(List), which could be switched off easily
  b) via calendar_activesync::GetMeetingRequest(s)
  client sends no MeetingResponse on either of them, for a) it displays buttons to accept, tentative or decline, but only calls SendMail and ChangeMessage (without status)
--> do NOT update if you already use AS!!!!!!!!!!!!!!!!!!!!!!!!!!
2011-05-15 18:25:16 +00:00
Klaus Leithoff
11411abef5 fix for 'cf_link_fields do not create link on inital save' in calendar: reason no id passed when called tracking for new events 2011-05-11 15:09:16 +00:00
Ralf Becker
440bcb1235 * Calendar: fixed not working "use event TZ" pref for iCal exports and allways use event TZ for calendar notifications (NOT use file export pref.) 2011-04-11 10:59:59 +00:00
Ralf Becker
f4e372747a allways update modified TS and modifier in save(), removed code to only conditionally update in update()
fixes bug that ctag got not updated when eg. a recurrence got deleted
2011-04-07 08:01:48 +00:00
Ralf Becker
0bfd238e3f * CalDAV: store name part of URL from client PUT request, to fully comply with CalDAV spec 2011-04-06 19:26:10 +00:00
Nathan Gray
bc39d9ab5b Add 'Do not notify of these changes' checkbox to list 2011-03-09 17:42:52 +00:00
Nathan Gray
f28fb14572 Add 'Do not notify of these changes' checkbox to edit dialog 2011-03-09 17:26:20 +00:00
Ralf Becker
63e61442c9 * Calendar: fixed in some cases not updated alarms, if event got moved
- sending alarms to CalDAV/GroupDAV clients as offset, not fixed time like before
- only exception to the above are alarms for recuring events to Lightning, which must be absolute, as offset lead to infinit poping up alarms in Lightning
- update all alarm times of other users alarms too, when storing events, as they might not be included in the stored event
2011-03-07 13:49:08 +00:00
Klaus Leithoff
4e07a37116 quieten warning when no participants in function remove_no_acl_invite 2011-02-01 14:28:56 +00:00
Ralf Becker
c9e5921ff1 fixed typo causing $$enddate$$ in notifcation message to show startdate 2010-11-16 13:39:19 +00:00
Ralf Becker
b19c4b3030 * fixed conflict check of resource quantity and storage of changed quantity in existing events
(changed quantity was used for conflict check, but not stored!)
There is still a bug with multiple non-overlapping events overlapping the checked event: check is against quantity sum, not the maximum
2010-11-11 08:51:13 +00:00
Jörg Lehrke
b3e551e74b * Calendar: Fix notification timezone issues (#2746) 2010-11-01 19:17:57 +00:00
Nathan Gray
7ae20bcf12 Update modified time when deleting 2010-10-04 15:09:15 +00:00
Nathan Gray
2b13b73b60 When deleting but keeping events, hold on to links as well so they can be restored if event is restored 2010-09-27 18:03:46 +00:00
Jörg Lehrke
bb9190a669 New content_history approach for calendar synchronization; fix various Sync issues 2010-09-12 20:14:46 +00:00
Jörg Lehrke
13cf31924f Fix find_event() issue 2010-09-11 23:15:05 +00:00
Jörg Lehrke
07063ebf7a Update cal_modified for all required cases; adjust CalDAV ctag function 2010-09-11 18:08:48 +00:00
Ralf Becker
8241be4091 storing deleted timestamp instead of a deleted flag, to allow to use calendar table instead of egw_api_content_history later on 2010-09-09 09:11:57 +00:00
Nathan Gray
db9bbc8460 Don't delete links until purge, same as addressbook 2010-09-02 20:55:37 +00:00
Ralf Becker
be91330030 fixed not working notifications for types:
- responses: on participant responses too (everytime)
- modifications: on all modification, but responses
2010-08-02 14:15:05 +00:00
Nathan Gray
cb3590ebab Do not send notification when a deleted event is purged 2010-06-28 11:15:25 +00:00
Jörg Lehrke
7b850eabb6 Fix recurring event issues for vCal 1.0 imports; fix bug Stylite #646 2010-06-23 14:52:55 +00:00
Nathan Gray
61099d4a89 Move purging of old calendar events to use less API and do more with the DB directly. Hopefully will be a little easier on the DB. 2010-06-14 11:45:00 +00:00
Jörg Lehrke
015245d235 Improved alarm handling 2010-06-07 17:54:29 +00:00
Ralf Becker
22406f6885 fixing call to calendar_so::search() to use new parameters, causing CalDAV to fail 2010-06-01 09:26:00 +00:00
Nathan Gray
586a58a4e7 Fix purging old events to get rid of events for all users, not just the admin that set it. 2010-06-01 07:36:14 +00:00
Nathan Gray
eeeebb5197 Delete alarms even if event is not really deleted 2010-05-28 07:24:34 +00:00
Jörg Lehrke
8cb71dfc84 Allow upgrade of single events to series via SyncML/CalDAV 2010-05-19 09:20:15 +00:00
Jörg Lehrke
7ad18fac74 Improved calendar_boupdate::find_event() (#2582) 2010-05-14 13:32:08 +00:00
Jörg Lehrke
dc8b3f2dec Fix 'non_blocking' issue (especially for Nokia) 2010-05-14 09:28:46 +00:00
Jörg Lehrke
587439511d Fix all-day recurring event issue (3) 2010-05-03 12:18:57 +00:00
Jörg Lehrke
d22a9aa537 Fix all-day recurring event timezone issue 2010-05-01 16:25:10 +00:00
Jörg Lehrke
2a2a9f5f11 Cleanup all-day handling 2010-04-23 15:15:22 +00:00
Jörg Lehrke
22bb23b8ff Fix new all-day event handling 2010-04-23 13:52:45 +00:00
Jörg Lehrke
ee18b0acac New all-day event implementation 2010-04-23 06:15:18 +00:00
Nathan Gray
c4a8515d99 Add feature to regularly remove old calendar events that are more than x years in the past. Set in Admin -> Calendar -> Site configuration 2010-04-22 20:27:14 +00:00
Nathan Gray
074b893e37 Change preserving deleted events. For speed improvements, use an extra column instead of joining to the sync tables 2010-04-22 16:09:36 +00:00
Ralf Becker
e5c782ca8e "fix warning if no participants defined (eg. iCal import)" 2010-04-14 08:41:45 +00:00
Nathan Gray
84d3643b22 Fix bug where a rejected event could still cause a schedule conflict 2010-03-25 20:23:22 +00:00
Jörg Lehrke
abfc3f522b Fix duplication by changed event title 2010-03-16 09:26:01 +00:00
Jörg Lehrke
871635002a Improve find_event() 2010-03-09 17:03:41 +00:00
Jörg Lehrke
191d0c7fd5 Fix 'search for series master' issue 2010-03-09 09:28:46 +00:00
Jörg Lehrke
a8804a44ef GroupDAV updates 2010-03-06 23:06:43 +00:00
Nathan Gray
cb5054f2e4 Add an option to keep deleted events, only an admin can purge them 2010-03-05 20:01:44 +00:00
Klaus Leithoff
a410651f6f changing a bit regarding the logic of the new feature (be notified about own changes) 2010-03-03 12:14:10 +00:00
Klaus Leithoff
f093aeff24 feature to enable to be notified of events you created/modified/deleted yourself; That is most helpful if you get a notification eMail with the ics attached, and thus be able to import the event somewhere else (another EGroupware/Outlook/...) 2010-03-03 11:59:55 +00:00
Christian Binder
fcd731a00b prevent iterating on empty array 2010-03-02 18:01:41 +00:00
Jörg Lehrke
c816b4188e Fix (pseudo) exception handling in CalDAV 2010-02-26 12:37:07 +00:00
Jörg Lehrke
08dbf52b66 Fix typos and code cleanup 2010-02-22 10:02:33 +00:00
Jörg Lehrke
e362a5b451 Use category names for history-log 2010-02-19 17:42:02 +00:00
Jörg Lehrke
21ccdd5f28 Fix various synchronization issues (SyncML & CalDAV) 2010-02-17 13:29:28 +00:00
Nathan Gray
de4a0e9239 Add history logging to calendar 2010-02-12 20:18:45 +00:00
Jörg Lehrke
41f587d584 Fix wrong classification in get_event_info() again 2010-02-11 21:04:10 +00:00
Jörg Lehrke
65c06844e5 Fix wrong classification in get_event_info() and UID handling for CalDAV 2010-02-11 20:50:35 +00:00
Jörg Lehrke
52ea4512ca Improve find_event() again 2010-02-11 07:33:32 +00:00
Jörg Lehrke
ad79f404e9 Fix recurring event issue 2010-02-10 19:47:39 +00:00
Jörg Lehrke
b6097fa156 SyncML Content Handling
* Improved find-methods
* Timezone support for InfoLog
* SyncML Preferences
    - addressbook and address list are now joined
    - Primary User Group for addressbook and calendar
* SlowSync uses old mapping information (can be disabled within the preferences)
2010-02-09 21:56:39 +00:00
Jörg Lehrke
75746226a4 Use egw_time for InfoLog, tracking backend and Tracker 2010-02-04 12:08:03 +00:00
Jörg Lehrke
b596935291 Fixes for get_event_info() and enhancements for find_event() 2010-02-03 12:24:42 +00:00
Jörg Lehrke
32639bd47e Major SyncML Calendar update
- SIFE support improved
  - various vCalendar 1.0 issues fixed
  - device specific timezone support for recurring events
  - pseudo exception handling improvements
2010-01-29 21:42:54 +00:00
Jörg Lehrke
14e7c0cd87 Add filter to calendar_so::get_recurrence_exceptions() method 2010-01-14 17:01:30 +00:00
Ralf Becker
dd55355195 "fixed several small problems in new invitation and category acl" 2009-12-07 13:31:51 +00:00
Ralf Becker
44b15c1775 Category based ACL to limit adding of a certain category or changing the
status of a participant (included moving the event), 
eg. to implement a restricted holiday calendar
*** not yet fully tested ***
2009-12-03 18:24:19 +00:00