cdesktopenv/cde/programs/dtcm/server/insert.c

389 lines
10 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they 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 these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $XConsortium: insert.c /main/5 1996/10/03 10:29:24 drk $ */
/*
* (c) Copyright 1993, 1994 Hewlett-Packard Company
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Novell, Inc.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
*/
#include <EUSCompat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <pwd.h>
#include <time.h>
#if !defined(CSRG_BASED)
#include <values.h>
#endif
#ifdef SunOS
#include <sys/systeminfo.h>
#endif
#include "insert.h"
#include "cm.h"
#include "cmscalendar.h"
#include "cmsdata.h"
#include "attr.h"
#include "delete.h"
#include "log.h"
#include "tree.h"
#include "list.h"
#include "iso8601.h"
#include "rerule.h"
#include "reutil.h"
#include "lutil.h"
#include "v5ops.h"
#include "repeat.h"
extern char *_DtCm_rule_buf; /* buffer to hold a rule for parser */
extern RepeatEvent *_DtCm_repeat_info; /* parsed recurrence info */
/******************************************************************************
* forward declaration of static functions used within the file
******************************************************************************/
static boolean_t _IsOnetimeEntry(cms_entry *entry);
static CSA_return_code _RuleToRepeatInfo(cms_entry *entry, RepeatEvent *re);
static int _RuleToRepeatType(RepeatEvent *re);
static int _DailyRuleToRepeatType(RepeatEvent *re);
static int _WeeklyRuleToRepeatType(RepeatEvent *re);
static int _MonthlyRuleToRepeatType(RepeatEvent *re);
/*****************************************************************************
* extern functions used in the library
*****************************************************************************/
extern CSA_return_code
_DtCmsInsertEntry(_DtCmsCalendar *cal, cms_entry *entry)
{
CSA_return_code stat;
Rb_Status rb_stat;
List_node *lnode = NULL;
cms_entry *newptr;
time_t current_time;
time_t key, tick, endtime;
char *date, buf[80];
CSA_opaque_data opq;
cms_attribute *aptr;
RepeatEvent *re = NULL;
RepeatEventState *res = NULL;
extern void _DtCm_rule_parser();
uint count;
int i;
if (cal == NULL || entry == NULL)
return (CSA_E_INVALID_PARAMETER);
/* assign key if this is a new appointment */
key = entry->key.id;
_DtCmsGenerateKey(cal, &(entry->key.id));
if (key == 0) {
/* set start date */
date = entry->attrs[CSA_ENTRY_ATTR_START_DATE_I].value->\
item.date_time_value;
_csa_iso8601_to_tick(date, &entry->key.time);
/* set reference id */
sprintf(buf, "%ld:%s@%s", entry->key.id, cal->calendar,
_DtCmGetHostAtDomain());
opq.size = strlen(buf);
opq.data = (unsigned char *)buf;
if ((stat = _DtCm_set_opaque_attrval(&opq,
&entry->attrs[CSA_ENTRY_ATTR_REFERENCE_IDENTIFIER_I].value)) != CSA_SUCCESS) {
return (stat);
}
}
/* check recurrence rule */
if (_IsOnetimeEntry(entry) == B_FALSE) {
/* check recurrence rule */
aptr = &entry->attrs[CSA_ENTRY_ATTR_RECURRENCE_RULE_I];
_DtCm_rule_buf = aptr->value->item.string_value;
_DtCm_rule_parser();
if ((re = _DtCm_repeat_info) == NULL)
return (CSA_E_INVALID_RULE);
/* get number of recurrences */
aptr = &entry->attrs[CSA_ENTRY_ATTR_EXCEPTION_DATES_I];
count = CountEvents(entry->key.time, re,
(aptr->value ?
aptr->value->item.date_time_list_value : NULL));
if (count == 1) {
/* turn into onetime entry */
_DtCmsConvertToOnetime(entry, re);
re = NULL;
} else {
if (count == 0)
return (CSA_E_INVALID_RULE);
else if (count == RE_INFINITY)
count = CSA_X_DT_DT_REPEAT_FOREVER;
if ((stat = _DtCm_set_uint32_attrval(count,
&entry->attrs[CSA_ENTRY_ATTR_NUMBER_RECURRENCES_I].\
value)) != CSA_SUCCESS)
return (stat);
/* adjust start date */
tick = ClosestTick(entry->key.time, entry->key.time,
re, &res);
if (tick != entry->key.time &&
!_DtCmsInExceptionList(entry, tick)) {
/* start date */
_csa_tick_to_iso8601(tick, entry->attrs\
[CSA_ENTRY_ATTR_START_DATE_I].value->\
item.date_time_value);
/* end date */
_csa_iso8601_to_tick(entry->attrs\
[CSA_ENTRY_ATTR_END_DATE_I].value->\
item.date_time_value, &endtime);
endtime += (tick - entry->key.time);
_csa_tick_to_iso8601(endtime, entry->attrs\
[CSA_ENTRY_ATTR_END_DATE_I].value->\
item.date_time_value);
/* start tick */
entry->key.time = tick;
}
}
}
/* Tidy unused variable */
free(res);
if ((stat = _DtCmsCheckStartEndTime(entry)) != CSA_SUCCESS)
return (stat);
if ((stat = _RuleToRepeatInfo(entry, re)) != CSA_SUCCESS)
return (stat);
if ((stat = _DtCm_copy_cms_entry(entry, &newptr)) != CSA_SUCCESS)
return (stat);
/* Add the entry into the data structure */
if (re == NULL) {
rb_stat = rb_insert (cal->tree, (caddr_t)newptr,
(caddr_t)&(newptr->key));
} else {
rb_stat = hc_insert (REPT_LIST(cal), (caddr_t)newptr,
(caddr_t)&(newptr->key), re, &lnode);
}
if (rb_stat == rb_ok) {
/* Add the qualified reminder attrs to the reminder queue */
_DtCmsAddReminders4Entry(&cal->remq, newptr, lnode);
}
return (_DtCmsRbToCsaStat(rb_stat));
}
extern CSA_return_code
_DtCmsInsertEntryAndLog(_DtCmsCalendar *cal, cms_entry *entry)
{
CSA_return_code stat;
if ((stat = _DtCmsInsertEntry(cal, entry)) == CSA_SUCCESS) {
/* append entry to the log file */
if ((stat = _DtCmsV5TransactLog(cal, entry, _DtCmsLogAdd))
!= CSA_SUCCESS) {
(void)_DtCmsDeleteEntry(cal, NULL, 0, &entry->key,
NULL);
}
}
return (stat);
}
/*****************************************************************************
* static functions used within the file
*****************************************************************************/
static boolean_t
_IsOnetimeEntry(cms_entry *entry)
{
cms_attribute *attr;
if (entry->attrs[CSA_ENTRY_ATTR_RECURRENCE_RULE_I].value == NULL)
return (B_TRUE);
else
return (B_FALSE);
}
static CSA_return_code
_RuleToRepeatInfo(cms_entry *entry, RepeatEvent *re)
{
CSA_return_code stat;
uint duration;
char buf[BUFSIZ];
int type;
if (re == NULL)
return (_DtCm_set_sint32_attrval(CSA_X_DT_REPEAT_ONETIME,
&entry->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I].value));
if ((stat = _DtCm_set_sint32_attrval(_RuleToRepeatType(re),
&entry->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I].value))
!= CSA_SUCCESS)
return (stat);
type = entry->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TYPE_I].value->\
item.sint32_value;
if (re->re_duration != RE_NOTSET) {
if (re->re_duration == RE_INFINITY) {
duration = 0;
} else if (type == CSA_X_DT_REPEAT_EVERY_NDAY ||
type == CSA_X_DT_REPEAT_EVERY_NWEEK ||
type == CSA_X_DT_REPEAT_EVERY_NMONTH) {
duration = re->re_duration * re->re_interval;
} else
duration = re->re_duration;
if ((stat = _DtCm_set_uint32_attrval(duration,
&entry->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_TIMES_I].value))
!= CSA_SUCCESS)
return (stat);
}
if ((stat = _DtCm_set_uint32_attrval(re->re_interval,
&entry->attrs[CSA_X_DT_ENTRY_ATTR_REPEAT_INTERVAL_I].value))
!= CSA_SUCCESS)
return (stat);
if (_csa_tick_to_iso8601(re->re_end_date, buf) == 0) {
if ((stat = _DtCm_set_string_attrval(buf,
&entry->attrs[CSA_X_DT_ENTRY_ATTR_SEQUENCE_END_DATE_I].\
value, CSA_VALUE_DATE_TIME)) != CSA_SUCCESS)
return (stat);
}
return (CSA_SUCCESS);
}
static int
_RuleToRepeatType(RepeatEvent *re)
{
switch (re->re_type) {
/* not supported in this release
* case RT_MINUTE:
*/
case RT_DAILY:
return (_DailyRuleToRepeatType(re));
case RT_WEEKLY:
return (_WeeklyRuleToRepeatType(re));
case RT_MONTHLY_POSITION:
return (_MonthlyRuleToRepeatType(re));
case RT_MONTHLY_DAY:
return (_MonthlyRuleToRepeatType(re));
case RT_YEARLY_MONTH:
if ((re->re_data.re_yearly->yd_nitems == 1 ||
re->re_data.re_yearly->yd_nitems == 0) &&
re->re_interval == 1)
return (CSA_X_DT_REPEAT_YEARLY);
else
return (CSA_X_DT_REPEAT_OTHER_YEARLY);
case RT_YEARLY_DAY:
return (CSA_X_DT_REPEAT_YEARLY);
default:
return (CSA_X_DT_REPEAT_OTHER);
}
}
static int
_DailyRuleToRepeatType(RepeatEvent *re)
{
if (re->re_interval == 1)
return (CSA_X_DT_REPEAT_DAILY);
else
return (CSA_X_DT_REPEAT_EVERY_NDAY);
}
#define _DtCms_MON_TO_FRI_MASK 0x3e
#define _DtCms_MON_WED_FRI_MASK 0x2a
#define _DtCms_TUE_THUR_MASK 0x14
static int
_WeeklyRuleToRepeatType(RepeatEvent *re)
{
int i, mask, temp;
if (re->re_data.re_weekly->wd_ndaytime == 1 ||
re->re_data.re_weekly->wd_ndaytime == 0) {
if (re->re_interval == 1)
return (CSA_X_DT_REPEAT_WEEKLY);
else if (re->re_interval == 2)
return (CSA_X_DT_REPEAT_BIWEEKLY);
else
return (CSA_X_DT_REPEAT_EVERY_NWEEK);
} else if (re->re_interval > 1)
return (CSA_X_DT_REPEAT_OTHER_WEEKLY);
/* check for MWF, M-F, TuTh */
for (i = 0, mask = 0; i < re->re_data.re_weekly->wd_ndaytime; i++) {
temp = re->re_data.re_weekly->wd_daytime[i].dt_day;
temp = 0x1 << re->re_data.re_weekly->wd_daytime[i].dt_day;
mask |= (0x1 << re->re_data.re_weekly->wd_daytime[i].dt_day);
}
if (mask == _DtCms_MON_TO_FRI_MASK)
return (CSA_X_DT_REPEAT_MON_TO_FRI);
else if (mask == _DtCms_MON_WED_FRI_MASK)
return (CSA_X_DT_REPEAT_MONWEDFRI);
else if (mask == _DtCms_TUE_THUR_MASK)
return (CSA_X_DT_REPEAT_TUETHUR);
else
return (CSA_X_DT_REPEAT_WEEKDAYCOMBO);
}
static int
_MonthlyRuleToRepeatType(RepeatEvent *re)
{
if (re->re_data.re_monthly->md_nitems == 1 ||
re->re_data.re_monthly->md_nitems == 0) {
if (re->re_interval == 1)
if (re->re_type == RT_MONTHLY_POSITION)
return (CSA_X_DT_REPEAT_MONTHLY_BY_WEEKDAY);
else
return (CSA_X_DT_REPEAT_MONTHLY_BY_DATE);
else
return (CSA_X_DT_REPEAT_EVERY_NMONTH);
} else
return (CSA_X_DT_REPEAT_OTHER_MONTHLY);
}