Solaris Common Desktop Environment: Programmer's Guide

Code Examples

Listing and Printing Calendars


Example 10-1 Listing and Printing Calendars Supported by Server

Example:
List and print out the calendars supported by a server.
 	   Free memory returned by a CSA function. 
list_calendar() 
{
 	CSA_return_code		stat;
	CSA_uint32		i, number;
 	CSA_calendar_user	*calendars;
 	char			*host;

  	/*specify some machine in the network */
 	host = "somehost";

  	stat= csa_list_calendars(host, &number, &calendars, NULL);
  	for (i = 0; i< number; i++) {
 		/* the calendar_address field contains the address of the
 		 * the calendar in the format "user@host" 		 */
 	printf("%d: %s\n", i, calendars[i].calendar_address); 	
   }

  	/* Example: free memory returned by a CSA function
 	 * free the memory returned by csa_list_calendars above
 	 */
 	stat = csa_free(calendars); 
}

Adding a Calendar


Example 10-2 Adding a Calendar Named "activity" to Host "host1"

#include <csa/csa.h>  

CSA_access_rights *setup_access_list() {
 	CSA_access_rights	*ptr1, *ptr2;
  	/* Allow any user to view public and confidential entries and
 	 * user "user1" to view and insert public entries.
 	 * The special user name "world" means any user.
   */

  	ptr2 = (CSA_access_rights *)calloc(1, sizeof(CSA_access_rights));
 	ptr2->user = (CSA_calendar_user *)calloc(1, sizeof(CSA_calendar_user));
 	ptr2->user->user_name = strdup("world");
 	ptr2->user->user_type = CSA_USER_TYPE_INDIVIDUAL;
 	ptr2->flags = CSA_VIEW_PUBLIC_ENTRIES | CSA_VIEW_CONFIDENTIAL_ENTRIES;
  	ptr1 = (CSA_access_rights *)calloc(1, sizeof(CSA_access_rights));
 	ptr1->user = (CSA_calendar_user *)calloc(1, sizeof(CSA_calendar_user));
 	ptr1->user->user_name = strdup("user1");
 	ptr1->user->user_type = CSA_USER_TYPE_INDIVIDUAL;
 	ptr1->flags = CSA_VIEW_PUBLIC_ENTRIES | CSA_INSERT_PUBLIC_ENTRIES;
 	ptr1->next = ptr2; 
} 

void destroy_access_list(CSA_access_rights *list) 
{
 	CSA_access_rights	*ptr;

  	while (list != NULL) {
 		ptr = list->next;

  		if (list->user) {
 			if (list->user->user_name)
 				free(list->user->user_name);
 			free(list->user);
 		} 		free(list);
  		list = ptr;
 	}
} 
add_calendar() 
{
 	CSA_return_code		stat;
 	CSA_calendar_user	caddr;
 	CSA_attribute		attr;
 	CSA_attribute_value	attr_val;

  	/* Specify the calendar to add */

 	caddr.user_name = NULL;
 	caddr.user_type = NULL;
 	caddr.calendar_address = "activity@host1";
 	caddr.calendar_user_extensions = NULL;

  	/* set up the access list */
 	attr_val.type			= CSA_VALUE_ACCESS_LIST;
 	attr_val.item.access_list_value	= setup_access_list();
 	attr.name			= CSA_CAL_ATTR_ACCESS_LIST;
 	attr.value			= &attr_val;
 	attr.attribute_extensions	= NULL;
  	stat = csa_add_calendar(NULL, &caddr, 1, &attr, NULL);
  	destroy_access_list(attr_val.item.access_list_value);
}

Logging on to a Calendar


Example 10-3 Logging on to a Calendar

CSA_session_handle	cal;

logon() 
{
  CSA_return_code		stat;
  CSA_calendar_user	caddr
;  CSA_flags		access;
  CSA_extension		logon_exts[2];
  CSA_X_COM_support	check_support[2];

  /* Specify the calendar to logon to */
 caddr.user_name = NULL;
 caddr.user_type = CSA_USER_TYPE_INDIVIDUAL;
caddr.calendar_address = "user@host";
caddr.calendar_user_extensions = NULL;

 /* Specify the get user access extension (CSA_X_DT_GET_USER_ACCESS_EXT)
  * to retrieve the user's access right with respect to the calendar.
  */
 logon_exts[0].item_code		= CSA_X_DT_GET_USER_ACCESS_EXT;
 logon_exts[0].item_data		= 0;
 logon_exts[0].item_reference	= NULL;
 logon_exts[0].extension_flags	= NULL;

  /* Specify the CSA_X_COM_SUPPORT_EXT extension to check
   * whether the CSA_X_XT_APP_CONTEXT_EXT extension and the
   * CSA_X_UI_ID_EXT extension are supported.
   */
  check_support[0].item_code	= CSA_X_XT_APP_CONTEXT_EXT;
check_support[0].flags		= NULL;
 check_support[1].item_code	= CSA_X_UI_ID_EXT;
 check_support[1].flags		= NULL;
  logon_exts[1].item_code		= CSA_X_COM_SUPPORT_EXT;
 logon_exts[1].item_data		= 2;
 logon_exts[1].item_reference	= (CSA_buffer)check_support;
 logon_exts[0].extension_flags	= CSA_EXT_LAST_ELEMENT;

  stat = csa_logon(NULL, &caddr, NULL, NULL, NULL, &cal, logon_exts);

  if (stat == CSA_SUCCESS) {
  access = (CSA_flags)get_access_ext.item_data;
   if (check_support[0].flag & CSA_X_COM_SUPPORTED)
   printf("The CSA_X_XT_APP_CONTEXT_EXT extension is supported\n");
   if (check_support[1].flag & CSA_X_COM_SUPPORTED)
   printf("The CSA_X_UI_ID_EXT extension is supported\n");
  }
 }

Terminating a Calendar Session


Example 10-4 Terminating a Calendar Session

logoff() 
{
 	CSA_return_code		stat;

  	/* When the session is no longer needed, it can be terminated by
 	 * calling csa_logoff.
 	 * Terminate the session returned by csa_logon in the previous
 	 * example.
 	 */
 	stat = csa_logoff(cal, NULL); 
}

Deleting a Calendar


Example 10-5 Deleting a Calendar

delete_calendar() 
{
 	/* After a calendar session is established by calling csa_logon(),
 	 * a calendar can be deleted using csa_delete_calendar().
 	 */
 	CSA_return_code		stat;
  	stat = csa_delete_calendar(cal, NULL);
} 

Adding a Calendar Entry


Example 10-6 Adding a Calendar Entry

#include <csa/csa.h>  

CSA_return_code		stat;
CSA_session_handle	cal;
CSA_attribute		attrs[9];
CSA_attribute_value	attr_val[9];
CSA_reminder		audio;
CSA_reminder		mail;
CSA_entry_handle	new_entry;
int			i;

i = 0;

/* The start date attribute. This attribute has no default
  * value and must be specified.
  * A CSA_date_time value is a UTC based date and time value
  * expressed in the ISO 8601 standard.
  */
attrs[i].name = CSA_ENTRY_ATTR_START_DATE;
 attrs[i].value = &attr_val[i];
 attrs[i].attribute_extensions = NULL;
 attr_val[i].type = CSA_VALUE_DATE_TIME;
 attr_val[i].item.date_time_value = iso8601time(time(NULL));
 i++;

/* The end date attribute.
  * If not specified, the entry will not have the end date
  * attribute.
  */ 
attrs[i].name = CSA_ENTRY_ATTR_END_DATE;
 attrs[i].value = &attr_val[i];
 attrs[i].attribute_extensions = NULL;
 attr_val[i].type = CSA_VALUE_DATE_TIME;
 attr_val[i].item.date_time_value = iso8601time(time(NULL) + 3600);
 i++;

/* The classification attribute.
  * If not specified, the default value is CSA_CLASS_PUBLIC.
  */ 
attrs[i].name = CSA_ENTRY_ATTR_CLASSIFICATION;
attrs[i].value = &attr_val[i];
attrs[i].attribute_extensions = NULL;
attr_val[i].type = CSA_VALUE_UINT32;
attr_val[i].item.sint32_value = CSA_CLASS_CONFIDENTIAL;
i++;  

/* The type attribute. This attribute has no default value and
  * must be specified.
  */
attrs[i].name = CSA_ENTRY_ATTR_TYPE;
attrs[i].value = &attr_val[i];
attrs[i].attribute_extensions = NULL;
attr_val[i].type = CSA_VALUE_UINT32;
attr_val[i].item.sint32_value = CSA_TYPE_EVENT;
i++;  

/* The sub-type attribute.
  * If not specified, the default value is CSA_SUBTYPE_APPOINTMENT
  */ 
attrs[i].name = CSA_ENTRY_ATTR_SUBTYPE;
attrs[i].value = &attr_val[i];
attrs[i].attribute_extensions = NULL;
attr_val[i].type = CSA_VALUE_STRING; 
attr_val[i].item.string_value = CSA_SUBTYPE_APPOINTMENT; 
i++;  

/* The summary attribute */ 
attrs[i].name = CSA_ENTRY_ATTR_SUMMARY; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_STRING; 
attr_val[i].item.string_value = argv6; 
attrs[i].attribute_extensions = NULL; 
i++;  

/* The recurrence rule attribute.
  * If not specified, the entry is a one time entry.
  * The recurrence rule "D1 #3" specifies that the
  * entry is to be repeated daily for 3 days.
  */ 
attrs[i].name = CSA_ENTRY_ATTR_RECURRENCE_RULE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_STRING; 
attr_val[i].item.string_value = argv7; 
i++;

/* The audio reminder attribute.
  * The lead time of a reminder is a CSA_time_duration value
  * which is expressed in the ISO 8601 standard.
  * For example, a lead time of 5 minutes is expressed as
  * the string "+PT300S". A negative lead time of 5 minutes
  * is expressed as "-PT300S".
  */ 
attrs[i].name = CSA_ENTRY_ATTR_AUDIO_REMINDER; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_REMINDER; 
attr_val[i].item.reminder_value = &audio; 
memset((void *)&audio, NULL, sizeof(audio)); 
audio.lead_time = "+PT300S"; i++;

/* The mail reminder attribute.
  * The e-mail address is specified in the reminder_data field
  * This reminder has a lead time of one day.
  */ 
attrs[i].name = CSA_ENTRY_ATTR_MAIL_REMINDER; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_REMINDER; 
attr_val[i].item.reminder_value = &mail; 
memset((void *)&mail, NULL, sizeof(mail)); 
mail.lead_time = "+PT86400S"; 
mail.reminder_data.data = "someuser@somehost"; 
mail.reminder_data.size = strlen(mail.reminder_data.data); 
i++;  

/* add an entry with the specified attribute values */ 
stat = csa_add_entry(cal, i, attrs, &newentry, NULL);  
if (stat == CSA_SUCCESS)
 	csa_free((CSA_buffer)newentry);

Looking Up Entries in a Calendar


Example 10-7 Looking up Calendar Entries; Reading Attribute Values

#include <csa/csa.h>  

CSA_return_code		stat; 
CSA_session_handle	cal;
CSA_attribute		attrs[4]; 
CSA_attribute_value	attr_val[4]; 
CSA_enum		ops[4];
CSA_uint32		i; 
CSA_uint32		num_entries;
 CSA_entry_handle	*entries;
CSA_uint32		num_attributes; 
CSA_attribute		*entry_attrs;  

/* find all entries with the following criteria:
  * (all appointments in the month of August 1996 UTC time)
  * start date equals to or after 00:00:00 Aug 1 1996 UTC time
  * and start date before 00:00:00 Sep 1 1996 UTC time
  * and type equals to CSA_TYPE_EVENT
  * and sub-type equals CSA_SUBTYPE_APPOINTMENT
  */  

i = 0;  

/* start date equals to or after 00:00:00 Aug 1 1996 UTC time */ 
attrs[i].name = CSA_ENTRY_ATTR_START_DATE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_DATE_TIME;
attr_val[i].item.date_time_value = "19960801T000000Z"; 
ops[i] = CSA_MATCH_GREATER_THAN_OR_EQUAL_TO; 
i++;  

/* start date before 00:00:00 Sep 1 1996 UTC time */ 
attrs[i].name = CSA_ENTRY_ATTR_START_DATE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_DATE_TIME; 
attr_val[i].item.date_time_value = "19960901T000000Z" 
ops[i] = CSA_MATCH_LESS_THAN; 
i++;  

/* type equals to CSA_TYPE_EVENT */ 
attrs[i].name = CSA_ENTRY_ATTR_TYPE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_UINT32; 
attr_val[i].item.sint32_value = CSA_TYPE_EVENT; 
ops[i] = CSA_MATCH_EQUAL_TO; 
i++;  

/* sub-type equals CSA_SUBTYPE_APPOINTMENT */ 
attrs[i].name = CSA_ENTRY_ATTR_SUBTYPE; 
attrs[i].value = &attr_val[i]; 
attrs[i].attribute_extensions = NULL; 
attr_val[i].type = CSA_VALUE_STRING; 
attr_val[i].item.string_value = CSA_SUBTYPE_APPOINTMENT; 
ops[i] = CSA_MATCH_EQUAL_TO; 
i++;  

/* do look up */ 
stat = csa_list_entries(csa, i, attrs, ops, &num_entries, &entries, NULL);

  if (stat == CSA_SUCCESS) {
     for (i = 0; i < num_entries; i++) {
  /* get all attribute values of the entry;
   * specifying 0 for number_names and NULL for attribute_names
   * will cause all attribute values to be returned
   */ 	
   stat = csa_read_entry_attributes(cal, entries[i], 0, NULL,
       &num_attributes, &entry_attrs,
       NULL); 	if (stat == CSA_SUCCESS) {
      /* use the returned attribute values,
       * free the memory when done
       */
      csa_free(entry_attrs);
  } else {
      /* handle error */
  }
     }
 } else {
     /* handle error */ 
}   

Example: Change the end time of the returned appointments to be
   one hour later. 

CSA_attribute_reference	name = CSA_ENTRY_ATTR_END_DATE; 
char   buffer[80]; 
time_t   endtime; 
CSA_entry_handle new_entry;  

for (i = 0; i < num_entries; i++) {
     /* get the end time of the appointment */
     stat = csa_read_entry_attributes(cal, entries[i], 0, &name,
         &num_attributes, &entry_attrs, NULL);
     if (stat == CSA_SUCCESS) {
 /* change the end time to be one hour later */
from_iso8601_time(entry_attrs[0].value->item.date_time_value, &endtime);
endtime += 60*60 /* number of second in an hour */
to_iso8601_time(endtime, buffer);
 attrs[0].name = CSA_ENTRY_ATTR_END_DATE;
 attrs[0].value = &attr_val[i];
attrs[0].attribute_extensions = NULL;	
 attr_val[0].type = CSA_VALUE_DATE_TIME;
attr_val[0].item.date_time_value = buffer;
 stat = csa_update_entry_attributes(cal, entries[0], CSA_SCOPE_ALL,
         CSA_FALSE, 1, attrs, &new_entry,
       NULL);
 if (stat == CSA_SUCCESS) {
     csa_free(new_entry);
 } else {
     /* handle error */
 }
  csa_free(entry_attrs);
      } else {
      /* handle error */
     } 
}

Updating a Calendar Entry


Example 10-8 Changing End Time of Returned Appointments: One Hour Later

CSA_attribute_reference	name = CSA_ENTRY_ATTR_END_DATE; 
char			buffer[80]; 
time_t			endtime; 
CSA_entry_handle	new_entry;  

for (i = 0; i < num_entries; i++) {
     /* get the end time of the appointment */
     stat = csa_read_entry_attributes(cal, entries[i], 0, &name,
          &num_attributes, &entry_attrs, NULL);
     if (stat == CSA_SUCCESS) {
  /* change the end time to be one hour later */
  from_iso8601_time(entry_attrs[0].value->item.date_time_value, &endtime);
  endtime += 60*60 /* number of second in an hour */
  to_iso8601_time(endtime, buffer);

   attrs[0].name = CSA_ENTRY_ATTR_END_DATE;
  attrs[0].value = &attr_val[i];
  attrs[0].attribute_extensions = NULL;
  attr_val[0].type = CSA_VALUE_DATE_TIME;
  attr_val[0].item.date_time_value = buffer;
   stat = csa_update_entry_attributes(cal, entries[0], CSA_SCOPE_ALL,
         CSA_FALSE, 1, attrs, &new_entry,
         NULL); 	if (stat == CSA_SUCCESS) {
      csa_free(new_entry);
  } else {
      /* handle error */
  }
   csa_free(entry_attrs);
      } else {
      /* handle error */ 
    }
}

Registering Callback and Keep Reminders

/* The example code shows the usage of csa_register_callback,
  * csa_read_next_reminder, and csa_call_callbacks.
  * The skeleton code registers a callback routine for
  * events CSA_CB_ENTRY_ADDED, CSA_CB_ENTRY_DELETED, and
  * CSA_CB_ENTRY_UPDATED; and another callback routine for the
  * CSA_CB_CALENDAR_ATTRIBUTE_UPDATED event.
  * It also shows how to set up a timer for reminder delivery.
  * Two utilities routines for conversion between time representation
  * in the ISO 8601 format and the tick representing time in seconds
  * since 00:00:00 UTC 1/1/70 are also included.
  */ 

 #include <csa/csa.h> 
#include <time.h> 
#include <unistd.h>  

CSA_session_handle	cal;	 /* a calendar session */ 
time_t			run_time; /* the time the reminders is to be run */ 
CSA_uint32		num_rems; /* number of reminders returned */ 
CSA_reminder_reference *rems;   /* an array of reminder information */  

void 
set_up_callback_handler() 
{
 	CSA_return_code		stat;
 	CSA_flags		flags;

  	/* Xt based applications can use the CSA_X_XT_APP_CONTEXT_EXT
 	 * extension to specify the Xt application context so that
 	 * callback routines will be invoked asynchronously
 	 *
 	 *	CSA_extension callback_ext;
 	 *	callback_ext.item_code = CSA_X_XT_APP_CONTEXT_EXT;
 	 * 	callback_ext.item_data = (CSA_uint32)application_context;
 	 *	callback_ext.extension_flags = CSA_EXT_LAST_ELEMENT;
 	 *
 	 * Pass the callback_ext as the last parameter to
 	 * csa_register_callback.
 	 */

  	flags = CSA_CB_ENTRY_ADDED|CSA_CB_ENTRY_DELETED|CSA_CB_ENTRY_UPDATED;
 	stat = csa_register_callback(cal, flags, entry_update_callback,
 		NULL, NULL);

  	if (stat != CSA_SUCCESS) {
 		/* error handling code */
 	}

  	stat = csa_register_callback(cal, CSA_CB_CALENDAR_ATTRIBUTE_UPDATED,
 		calendar_update_callback, NULL, NULL);
  	if (stat != CSA_SUCCESS) {
 		/* error handling code */
 	} 
}  

/*  * This routine polls the library and causes the registered
  * callback to be invoked if the interested event has occurred.
  * If an application does not use the CSA_X_XT_APP_CONTEXT_EXT
  * extension to set up asynchronously callback invocation,
  * it needs to call csa_call_callbacks to force the invocation
  * of callbacks.
  */ 

check_events(CSA_flags event)
{
 	csa_call_callbacks(cal, event, NULL); 
}

  /*
  * This is the callback routine for events CSA_CB_ENTRY_ADDED,
  * CSA_CB_ENTRY_ADDED, and CSA_CB_ENTRY_UPDATED.
  */ 
void 
entry_update_callback(
 	CSA_session_handle	cal,
 	CSA_flags		flags,
 	CSA_buffer		call_data,
 	CSA_buffer		client_data,
 	CSA_extension		*ext) 
{
 	/* An entry is either added, deleted or updated.
 	 * Possible things to do in this callback routine:
	 *
 	 * 1. Update the calendar view, or
 	 * 2. If this is your own calendar, update reminder information.
 	 *
 	 * The sample code in this routine updates reminder information
 	 */ 	reset_reminder();
}

  /*
  * This is the callback routine for the CSA_CB_CALENDAR_ATTRIBUTE_UPDATED
  * event
  */ 
void 
calendar_update_callback(
 	CSA_session_handle	cal,
 	CSA_flags		flags,
 	CSA_buffer		call_data,
 	CSA_buffer		client_data,
 	CSA_extension		*ext) 
{
 	/* update calendar attributes */ 
}

   /*
  * This routine updates reminder information:
  *	- get rid of existing information if any
  *	- call csa_read_next_reminder() to get the next
  *	 reminder to deliver
  *	- check the run time and set timer
  */ 
void 
reset_reminder() {
 	CSA_return_code		stat;
 	time_t			current_time;
 	char			isotime[BUFSIZ];
 	CSA_uint32		number_reminders;
 	CSA_reminder_reference	*reminders;
 
  	current_time = time(NULL);

  	/* get rid of existing information */
 	if (rems) {
 		/* this comparison is to make sure that we don't lose
 		 * any reminders whose run time is between the last
 		 * run time and the current time
 		 */
 		if (current_time > run_time)
 			current_time = run_time;

  		csa_free((CSA_buffer)rems);
 	}

 	to_iso8601_time(current_time, isotime);
 	stat = csa_read_next_reminder(cal, 0, NULL, isotime,
 		&number_reminders, &reminders, NULL);

  	if (stat == CSA_SUCCESS && num_rems > 0) {
 		num_rems = number_reminders;
 		rems = reminders;

  		/* Set timer to deliver the reminder.
 		 * sigset() should be used to set up the signal
 		 * disposition for the SIGALRM signal.
 		 */
 		from_iso8601_time(reminders[0].run_time, &run_time);
 		remain = run_time - time(NULL);
 		alarm((remain > 0) ? remain : 1);

  		/* Xt based application can set the timer using
 		 * XtAppAddTimeOut
 		 */
 	}
}
  
/*
  * This routine converts a time value in the iso8601 format to
  * a tick (representing time in seconds since 00:00:00 UTC, 1/1/70).
  * The tick is adjusted to the local time.
  */ int from_iso8601_time(char *buf, time_t *tick_out) 
{
  	int		year, month, day, hour, min, sec;
 	struct tm	time_str;

  	sscanf(buf, "%4d%2d%2dT%2d%2d%2dZ",
 	    &year, &month, &day, &hour, &min, &sec);

  	time_str.tm_year	= year - 1900;
 	time_str.tm_mon		= month - 1;
 	time_str.tm_mday	= day;
 	time_str.tm_hour	= hour;
 	time_str.tm_min		= min;
 	time_str.tm_sec		= sec;
 	time_str.tm_isdst	= -1;
  	*tick_out = mktime(&time_str);

  	if (*tick_out != (long)-1) {

  		/* adjust for local time zone */
 		if (time_str.tm_isdst == 0)
 			*tick_out -= timezone;
 		else
 			*tick_out -= altzone;
  		return(0);
 	} else
 		return(-1); 
}  

/*
  * This routine converts a tick (representing time in seconds
  * since 00:00:00 UTC, 1/1/70) to the iso8601 format.
  */ 
int 
to_iso8601_time(time_t tick, char *buf_out) 
{
 	struct tm	time_str;
  	if (gmtime_r(&tick, &time_str)) {

  		/* format string forces fixed width (zero-padded) fields */
 		sprintf(buf_out, "%04d%02d%02dT%02d%02d%02dZ",
 			time_str.tm_year + 1900,
 			time_str.tm_mon + 1,
 			time_str.tm_mday,
 			time_str.tm_hour,
 			time_str.tm_min,
 			time_str.tm_sec);
  		return (0);
 	} else {
 		return (-1);
 	} 
}