コーディング例
カレンダのリストおよび出力
例 10–1 サーバがサポートするカレンダをリストし出力する
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;
/* ネットワーク上のいくつかのマシンを指定します */
host = “somehost”;
stat= csa_list_calendars(host, &number, &calendars, NULL);
for (i = 0; i< number; i++) {
/* calendar_address フィールドには、カレンダのアドレスが
* user@host の書式で入っています */
printf(“%d: %s\n”, i, calendars[i].calendar_address);
}
/* 例: CSA 関数により返されるメモリを解放する
* csa_list_calendars により返されるメモリを解放します
*/
stat = csa_free(calendars);
}
|
カレンダの追加
例 10–2 activity という名前のカレンダをホスト host1 に追加する
#include <csa/csa.h>
CSA_access_rights *setup_access_list() {
CSA_access_rights *ptr1, *ptr2;
/* 任意のユーザに、公開および非公開エントリを表示する許可を与え、
* ユーザ user1 に、公開エントリを表示し、挿入する許可を与えます。
* 特別なユーザ名 world は任意のユーザを意味します。
*/
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;
/* 追加するカレンダを指定します。 */
caddr.user_name = NULL;
caddr.user_type = NULL;
caddr.calendar_address = “activity@host1”;
caddr.calendar_user_extensions = NULL;
/* アクセス・リストを設定します */
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);
}
|
カレンダへのログイン
例 10–3 カレンダにログインする
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];
/* ログインするカレンダを指定します */
caddr.user_name = NULL;
caddr.user_type = CSA_USER_TYPE_INDIVIDUAL;
caddr.calendar_address = “user@host”;
caddr.calendar_user_extensions = NULL;
/* (CSA_X_DT_GET_USER_ACCESS_EXT) を指定して、
* カレンダに関するユーザのアクセス権を取得します。
*/
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;
/* CSA_X_COM_SUPPORT_EXT 拡張を指定して、
* CSA_X_XT_APP_CONTEXT_EXT 拡張と、CSA_X_UI_ID_EXT 拡張が
* サポートされているかどうかをチェックします。
*/
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”);
}
}
|
カレンダ・セッションの終了
例 10–4 カレンダ・セッションを終了する
logoff()
{
CSA_return_code stat;
/* セッションが必要ない場合は、csa_logoff を呼び出すことにより終了できます。
* 前の例で csa_logon により返されたセッションを終了します。
*/
stat = csa_logoff(cal, NULL);
}
|
カレンダの削除
例 10–5 カレンダを削除する
delete_calendar()
{
/* csa_logon() を呼び出すことによりカレンダ・セッションを確立後、
* csa_delete_calender() を使用してカレンダを削除できます。
*/
CSA_return_code stat;
stat = csa_delete_calendar(cal, NULL);
}
|
カレンダ・エントリの追加
例 10–6 カレンダ・エントリを追加する
#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;
/* 開始日の属性。この属性にはデフォルトがないため、必ず指定してください。
* CSA_date_time 値は、ISO 8601 規格にある
* UTC ベースの日付と時間を指定します。
*/
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++;
/* 終了日の属性。
* 指定しないと、エントリは終了日の属性を持ちません。
*/
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++;
/* 分類属性。
* 指定しないと、デフォルト値は 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++;
/* タイプ属性。
* この属性にはデフォルトがないため、必ず指定してください。
*/
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++;
/* サブタイプ属性。
* 指定しないと、デフォルト値は 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++;
/* サマリ属性 */
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++;
/* 反復規則属性。
* 指定しないと、エントリは 1 回だけのエントリになります。
* 反復規則 D1 #3 は、エントリが毎日
* 3 日間繰り返されるよう指定します。
*/
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++;
/* オーディオ通知属性。
* 通知プログラムのリード・タイムは、ISO 8601 規格にある
* CSA_time_duration の値で指定します。
* たとえば、5 分間のリード・タイムは、文字列 +PT300S と表します。
* マイナス 5 分間のリード・タイムは、-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++;
/* メール通知属性。
* 電子メール・アドレスは、reminder_data フィールドに指定します。
* この通知プログラムのリード・タイムは 1 日。
*/
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++;
/* 指定した属性値でエントリを追加します */
stat = csa_add_entry(cal, i, attrs, &newentry, NULL);
if (stat == CSA_SUCCESS)
csa_free((CSA_buffer)newentry);
|
カレンダのエントリの検索
例 10–7 カレンダのエントリを検索する/属性値を読み取る
#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;
/* 次の判断基準ですべてのエントリを検索します。
* UTC 時間 1996 年 8 月のすべてのアポイント
* 開始日は、UTC 時間 1996 年 8 月 1 日 00:00:00 以降
* 開始日は、UTC 時間 1996 年 9 月 1 日 00:00:00 より前
* タイプは CSA_TYPE_EVENT
* サブタイプは CSA_SUBTYPE_APPOINTMENT
*/
i = 0;
/* 開始日は、UTC 時間 1996 年 8 月 1 日 00:00:00 以降 */
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++;
/* 開始日は、UTC 時間 1996 年 9 月 1 日 00:00:00 より前 */
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++;
/* タイプは 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++;
/* サブタイプは 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++;
/* 検索の実行 */
stat = csa_list_entries(csa, i, attrs, ops, &num_entries, &entries, NULL);
if (stat == CSA_SUCCESS) {
for (i = 0; i < num_entries; i++) {
/* エントリのすべての属性値を取得します。
* number_names に 0 を指定し、attribute_names に NULL を指定すると、
* すべての属性値が返されます。
*/
stat = csa_read_entry_attributes(cal, entries[i], 0, NULL,
&num_attributes, &entry_attrs,
NULL); if (stat == CSA_SUCCESS) {
/* 返された属性値を使用し、終了時にメモリを解放します
*/
csa_free(entry_attrs);
} else {
/* ハンドル・エラー */
}
}
} else {
/* ハンドル・エラー */
}
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++) {
/* アポイントの終了時間を取得します */
stat = csa_read_entry_attributes(cal, entries[i], 0, &name,
&num_attributes, &entry_attrs, NULL);
if (stat == CSA_SUCCESS) {
/* 終了時間を 1 時間後に変更します */
from_iso8601_time(entry_attrs[0].value->item.date_time_value, &endtime);
endtime += 60*60 /* 1 時間の秒数 */
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 {
/* ハンドル・エラー */
}
csa_free(entry_attrs);
} else {
/* ハンドル・エラー */
}
}
カレンダのエントリの更新
例 10–8 返されたアポイントの終了時間を 1 時間後に変更する
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++) {
/* アポイントの終了時間を取得します */
stat = csa_read_entry_attributes(cal, entries[i], 0, &name,
&num_attributes, &entry_attrs, NULL);
if (stat == CSA_SUCCESS) {
/* 終了時間を 1 時間後に変更します */
from_iso8601_time(entry_attrs[0].value->item.date_time_value, &endtime);
endtime += 60*60 /* 1 時間の秒数 */
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 {
/* ハンドル・エラー */
}
csa_free(entry_attrs);
} else {
/* ハンドル・エラー */
}
}
|
コールバックの登録および通知プログラムの保持
例 10–9 コールバックを登録し、通知プログラムを保持する
/* このコーディング例では、csa_register_callback、csa_read_next_reminder、
* および csa_call_callbacks の使用方法について示します。
* 基本となるコードでは、イベント CSA_CB_ENTRY_ADDED、CSA_CB_ENTRY_DELETED、
* および CSA_CB_ENTRY_UPDATED 用のコールバック・ルーチンを登録します。
* また、別のコールバック・ルーチンを、CSA_CB_CALENDAR_ATTRIBUTE_UPDATE
* イベント用に登録します。
* 通知デリバリ用のタイマを設定する方法も示します。
* ISO 8601 書式の時間表記を UTC 1970 年 1 月 1 日 00:00:00 からの
* 経過秒数を示すティック数への変換用の 2 つのユーティリティ・ルーチン
* も含みます。
*/
#include <csa/csa.h>
#include <time.h>
#include <unistd.h>
CSA_session_handle cal; /* カレンダ・セッション */
time_t run_time; /* 通知プログラムを実行する時間 */
CSA_uint32 num_rems; /* 返される通知数 */
CSA_reminder_reference *rems; /* 通知情報の配列 */
void
set_up_callback_handler()
{
CSA_return_code stat;
CSA_flags flags;
/* Xt ベースのアプリケーションは、コールバック・ルーチンが
* 非同期に呼び出せるように
* するため、CSA_X_XT_APP_CONTEXT_EXT 拡張を使用して、
* Xt アプリケーションのコンテキストを指定できます。
*
* 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;
*
* callback_ext を最後のパラメータとして、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) {
/* エラー処理コード */
}
stat = csa_register_callback(cal, CSA_CB_CALENDAR_ATTRIBUTE_UPDATED,
calendar_update_callback, NULL, NULL);
if (stat != CSA_SUCCESS) {
/* エラー処理コード */
}
}
/ * このルーチンはライブラリをポーリングし、特定のイベントが発生して
* いた場合に、登録されているコールバックを呼び出します。
* アプリケーションが CSA_X_XT_APP_CONTEXT_EXT 拡張を使用してコールバックの
* 呼び出しを非同期に設していない場合、csa_call_callbacks を呼び出して、
* コールバックの呼び出し強制する必要あります。
*/
check_events(CSA_flags event)
{
csa_call_callbacks(cal, event, NULL);
}
/*
* これは、イベント CSA_CB_ENTRY_ADDED、CSA_CB_ENTRY_ADDED、および
* 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)
{
/* エントリが追加、削除、または更新されます。
* このコールバック・ルーチンで行う可能性があるのは次のとおりです。
*
* 1. カレンダ表示の更新
* 2. ユーザ自身のカレンダの場合は、通知情報の更新
*
* このルーチンのコーディング例は通知情報を更新します。
*/ reset_reminder();
}
/*
* これは CSA_CB_CALENDAR_ATTRIBUTE_UPDATED イベントのための
* コールバック・ルーチンです。
*/
void
calendar_update_callback(
CSA_session_handle cal,
CSA_flags flags,
CSA_buffer call_data,
CSA_buffer client_data,
CSA_extension *ext)
{
/* カレンダ属性を更新する */
}
/*
* このルーチンは通知情報を更新します。
* - 既存の情報がある場合は削除する
* - csa_read_next_reminder() を呼び出して、次に転送する通知を取得する
* - 実行時間をチェックし、タイマーを設定する
*/
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);
/* 既存の情報を削除する */
if (rems) {
/* この比較の目的は、最後に実行された時刻から、
* 現在の時刻までの間に実行された通知が
* 失われていないかを確認することです。
*/
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;
/* タイマーを設定し、通知を転送する。
* sigset() を使用して、SIGALRM シグナルのための
* シグナル処理を設定します。
*/
from_iso8601_time(reminders[0].run_time, &run_time);
remain = run_time - time(NULL);
alarm((remain > 0) ? remain : 1);
/* Xt ベースのアプリケーションは、XtAppAddTimeOut を使用して
* タイマーを設定できます。
*/
}
}
/*
* このルーチンは、ISO 8601 書式の時間表記を、
* UTC 1970 年 1 月 1 日 00:00:00 からの
* 経過秒数を示すティック数へ変換します。
* このティックはローカル時間に調整されます。
*/ 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) {
/* ローカル・タイムゾーンに調整 */
if (time_str.tm_isdst == 0)
*tick_out -= timezone;
else
*tick_out -= altzone;
return(0);
} else
return(-1);
}
/*
* このルーチンは、UTC 1970 年 1 月 1 日 00:00:00 からの経過秒数を
* 示すティック数を、ISO 8601 書式の時間表記へ変換します。
*/
int
to_iso8601_time(time_t tick, char *buf_out)
{
struct tm time_str;
if (gmtime_r(&tick, &time_str)) {
/* 書式文字列が固定幅 (ゼロで埋め込み) フィールドを強制する。 */
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);
}
}