3
Meanwhile - Unofficial Lotus Sametime Community Client Library
4
Copyright (C) 2004 Christopher (siege) O'Brien
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Library General Public
8
License as published by the Free Software Foundation; either
9
version 2 of the License, or (at your option) any later version.
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Library General Public License for more details.
16
You should have received a copy of the GNU Library General Public
17
License along with this library; if not, write to the Free
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
#include <glib/gstring.h>
27
#include "mw_st_list.h"
30
struct mwSametimeList {
39
struct mwSametimeGroup {
40
struct mwSametimeList *list;
42
enum mwSametimeGroupType type;
51
struct mwSametimeUser {
52
struct mwSametimeGroup *group;
54
enum mwSametimeUserType type;
61
static void user_free(struct mwSametimeUser *u) {
62
struct mwSametimeGroup *g;
65
g->users = g_list_remove(g->users, u);
67
mwIdBlock_clear(&u->id);
74
static void group_free(struct mwSametimeGroup *g) {
75
struct mwSametimeList *l;
78
l->groups = g_list_remove(l->groups, g);
81
mwSametimeUser_free(g->users->data);
89
static void list_free(struct mwSametimeList *l) {
91
mwSametimeGroup_free(l->groups->data);
97
struct mwSametimeList *
98
mwSametimeList_new() {
100
struct mwSametimeList *stl;
102
stl = g_new0(struct mwSametimeList, 1);
103
stl->ver_major = ST_LIST_MAJOR;
104
stl->ver_minor = ST_LIST_MINOR;
105
stl->ver_micro = ST_LIST_MICRO;
111
void mwSametimeList_setMajor(struct mwSametimeList *l, guint v) {
112
g_return_if_fail(l != NULL);
117
guint mwSametimeList_getMajor(struct mwSametimeList *l) {
118
g_return_val_if_fail(l != NULL, 0);
123
void mwSametimeList_setMinor(struct mwSametimeList *l, guint v) {
124
g_return_if_fail(l != NULL);
129
guint mwSametimeList_getMinor(struct mwSametimeList *l) {
130
g_return_val_if_fail(l != NULL, 0);
135
void mwSametimeList_setMicro(struct mwSametimeList *l, guint v) {
136
g_return_if_fail(l != NULL);
141
guint mwSametimeList_getMicro(struct mwSametimeList *l) {
142
g_return_val_if_fail(l != NULL, 0);
147
GList *mwSametimeList_getGroups(struct mwSametimeList *l) {
148
g_return_val_if_fail(l != NULL, NULL);
149
return g_list_copy(l->groups);
153
struct mwSametimeGroup *
154
mwSametimeList_findGroup(struct mwSametimeList *l,
158
g_return_val_if_fail(l != NULL, NULL);
159
g_return_val_if_fail(name != NULL, NULL);
160
g_return_val_if_fail(*name != '\0', NULL);
162
for(s = l->groups; s; s = s->next) {
163
struct mwSametimeGroup *g = s->data;
164
if(! strcmp(g->name, name)) return g;
171
void mwSametimeList_free(struct mwSametimeList *l) {
172
g_return_if_fail(l != NULL);
177
struct mwSametimeGroup *
178
mwSametimeGroup_new(struct mwSametimeList *list,
179
enum mwSametimeGroupType type,
182
struct mwSametimeGroup *stg;
184
g_return_val_if_fail(list != NULL, NULL);
185
g_return_val_if_fail(name != NULL, NULL);
186
g_return_val_if_fail(*name != '\0', NULL);
188
stg = g_new0(struct mwSametimeGroup, 1);
191
stg->name = g_strdup(name);
193
list->groups = g_list_append(list->groups, stg);
199
enum mwSametimeGroupType mwSametimeGroup_getType(struct mwSametimeGroup *g) {
200
g_return_val_if_fail(g != NULL, mwSametimeGroup_UNKNOWN);
205
const char *mwSametimeGroup_getName(struct mwSametimeGroup *g) {
206
g_return_val_if_fail(g != NULL, NULL);
211
void mwSametimeGroup_setAlias(struct mwSametimeGroup *g,
213
g_return_if_fail(g != NULL);
216
g->alias = g_strdup(alias);
220
const char *mwSametimeGroup_getAlias(struct mwSametimeGroup *g) {
221
g_return_val_if_fail(g != NULL, NULL);
226
void mwSametimeGroup_setOpen(struct mwSametimeGroup *g, gboolean open) {
227
g_return_if_fail(g != NULL);
232
gboolean mwSametimeGroup_isOpen(struct mwSametimeGroup *g) {
233
g_return_val_if_fail(g != NULL, FALSE);
238
struct mwSametimeList *mwSametimeGroup_getList(struct mwSametimeGroup *g) {
239
g_return_val_if_fail(g != NULL, NULL);
244
GList *mwSametimeGroup_getUsers(struct mwSametimeGroup *g) {
245
g_return_val_if_fail(g != NULL, NULL);
246
return g_list_copy(g->users);
250
struct mwSametimeUser *
251
mwSametimeGroup_findUser(struct mwSametimeGroup *g,
252
struct mwIdBlock *user) {
255
g_return_val_if_fail(g != NULL, NULL);
256
g_return_val_if_fail(user != NULL, NULL);
258
for(s = g->users; s; s = s->next) {
259
struct mwSametimeUser *u = s->data;
260
if(mwIdBlock_equal(user, &u->id)) return u;
267
void mwSametimeGroup_free(struct mwSametimeGroup *g) {
268
g_return_if_fail(g != NULL);
269
g_return_if_fail(g->list != NULL);
274
struct mwSametimeUser *
275
mwSametimeUser_new(struct mwSametimeGroup *group,
276
enum mwSametimeUserType type,
277
struct mwIdBlock *id) {
279
struct mwSametimeUser *stu;
281
g_return_val_if_fail(group != NULL, NULL);
282
g_return_val_if_fail(id != NULL, NULL);
284
stu = g_new0(struct mwSametimeUser, 1);
287
mwIdBlock_clone(&stu->id, id);
289
group->users = g_list_append(group->users, stu);
295
struct mwSametimeGroup *mwSametimeUser_getGroup(struct mwSametimeUser *u) {
296
g_return_val_if_fail(u != NULL, NULL);
301
enum mwSametimeUserType mwSametimeUser_getType(struct mwSametimeUser *u) {
302
g_return_val_if_fail(u != NULL, mwSametimeUser_UNKNOWN);
307
const char *mwSametimeUser_getUser(struct mwSametimeUser *u) {
308
g_return_val_if_fail(u != NULL, NULL);
313
const char *mwSametimeUser_getCommunity(struct mwSametimeUser *u) {
314
g_return_val_if_fail(u != NULL, NULL);
315
return u->id.community;
319
void mwSametimeUser_setShortName(struct mwSametimeUser *u, const char *name) {
320
g_return_if_fail(u != NULL);
322
u->name = g_strdup(name);
326
const char *mwSametimeUser_getShortName(struct mwSametimeUser *u) {
327
g_return_val_if_fail(u != NULL, NULL);
332
void mwSametimeUser_setAlias(struct mwSametimeUser *u, const char *alias) {
333
g_return_if_fail(u != NULL);
335
u->alias = g_strdup(alias);
339
const char *mwSametimeUser_getAlias(struct mwSametimeUser *u) {
340
g_return_val_if_fail(u != NULL, NULL);
345
void mwSametimeUser_free(struct mwSametimeUser *u) {
346
g_return_if_fail(u != NULL);
347
g_return_if_fail(u->group != NULL);
352
static void str_replace(char *str, char from, char to) {
354
for(; *str; str++) if(*str == from) *str = to;
358
static char user_type_to_char(enum mwSametimeUserType type) {
360
case mwSametimeUser_NORMAL: return '1';
361
case mwSametimeUser_EXTERNAL: return '2';
362
case mwSametimeUser_UNKNOWN:
368
static enum mwSametimeUserType user_char_to_type(char type) {
370
case '1': return mwSametimeUser_NORMAL;
371
case '2': return mwSametimeUser_EXTERNAL;
372
default: return mwSametimeUser_UNKNOWN;
377
static void user_put(GString *str, struct mwSametimeUser *u) {
378
char *id, *name, *alias;
381
id = g_strdup(u->id.user);
382
name = g_strdup(u->name);
383
alias = g_strdup(u->alias);
384
type = user_type_to_char(u->type);
386
if(id) str_replace(id, ' ', ';');
387
if(name) str_replace(name, ' ', ';');
388
if(alias) str_replace(alias, ' ', ';');
395
g_string_append_printf(str, "U %s%c:: %s,%s\r\n",
396
id, type, (name? name: ""), (alias? alias: ""));
404
static char group_type_to_char(enum mwSametimeGroupType type) {
406
case mwSametimeGroup_NORMAL: return '2';
407
case mwSametimeGroup_DYNAMIC: return '3';
408
case mwSametimeGroup_UNKNOWN:
414
static enum mwSametimeGroupType group_char_to_type(char type) {
416
case '2': return mwSametimeGroup_NORMAL;
417
case '3': return mwSametimeGroup_DYNAMIC;
418
default: return mwSametimeGroup_UNKNOWN;
423
static void group_put(GString *str, struct mwSametimeGroup *g) {
428
name = g_strdup(g->name);
429
alias = g_strdup((g->alias)? g->alias: name);
430
type = group_type_to_char(g->type);
432
str_replace(name, ' ', ';');
433
str_replace(alias, ' ', ';');
435
g_string_append_printf(str, "G %s%c %s %c\r\n",
436
name, type, alias, (g->open? 'O':'C'));
438
for(gl = g->users; gl; gl = gl->next) {
439
user_put(str, gl->data);
447
/** composes a GString with the written contents of a sametime list */
448
static GString *list_store(struct mwSametimeList *l) {
452
g_return_val_if_fail(l != NULL, NULL);
454
str = g_string_new(NULL);
455
g_string_append_printf(str, "Version=%u.%u.%u\r\n",
456
l->ver_major, l->ver_minor, l->ver_micro);
458
for(gl = l->groups; gl; gl = gl->next) {
459
group_put(str, gl->data);
466
char *mwSametimeList_store(struct mwSametimeList *l) {
470
g_return_val_if_fail(l != NULL, NULL);
474
g_string_free(str, FALSE);
479
void mwSametimeList_put(struct mwPutBuffer *b, struct mwSametimeList *l) {
483
g_return_if_fail(l != NULL);
484
g_return_if_fail(b != NULL);
487
len = (guint16) str->len;
489
mwPutBuffer_write(b, str->str, len);
491
g_string_free(str, TRUE);
495
static void get_version(const char *line, struct mwSametimeList *l) {
496
guint major = 0, minor = 0, micro = 0;
499
ret = sscanf(line, "Version=%u.%u.%u\n", &major, &minor, µ);
501
g_warning("strange sametime list version line:\n%s", line);
504
l->ver_major = major;
505
l->ver_minor = minor;
506
l->ver_micro = micro;
510
static struct mwSametimeGroup *get_group(const char *line,
511
struct mwSametimeList *l) {
512
struct mwSametimeGroup *group;
514
char type = '2', open = 'O';
518
name = g_malloc0(ret);
519
alias = g_malloc0(ret);
521
ret = sscanf(line, "G %s %s %c\n",
525
g_warning("strange sametime list group line:\n%s", line);
528
str_replace(name, ';', ' ');
529
str_replace(alias, ';', ' ');
532
int l = strlen(name)-1;
537
group = g_new0(struct mwSametimeGroup, 1);
540
group->type = group_char_to_type(type);
541
group->alias = alias;
542
group->open = (open == 'O');
544
l->groups = g_list_append(l->groups, group);
550
static void get_user(const char *line, struct mwSametimeGroup *g) {
551
struct mwSametimeUser *user;
552
struct mwIdBlock idb = { 0, 0 };
553
char *name, *alias = NULL;
558
idb.user = g_malloc0(ret);
559
name = g_malloc0(ret);
561
ret = sscanf(line, "U %s %s",
565
g_warning("strange sametime list user line:\n%s", line);
568
str_replace(idb.user, ';', ' ');
569
str_replace(name, ';', ' ');
571
if(idb.user && *idb.user) {
572
char *tmp = strstr(idb.user, "::");
580
char *tmp = strrchr(name, ',');
583
if(*tmp) alias = tmp;
587
user = g_new0(struct mwSametimeUser, 1);
589
user->id.user = idb.user;
590
user->type = user_char_to_type(type);
592
user->alias = g_strdup(alias);
594
g->users = g_list_append(g->users, user);
598
/** returns a line from str, and advances str */
599
static char *fetch_line(char **str) {
603
/* move to first non-whitespace character */
604
while(*start && g_ascii_isspace(*start)) start++;
605
if(! *start) return NULL;
607
for(end = start + 1; *end; end++) {
608
if(*end == '\n' || *end == '\r') {
619
static void list_get(const char *lines, struct mwSametimeList *l) {
620
char *s = (char *) lines;
623
struct mwSametimeGroup *g = NULL;
625
while( (line = fetch_line(&s)) ) {
628
get_version(line, l);
632
g = get_group(line, l);
640
g_warning("unknown sametime list data line:\n%s", line);
646
struct mwSametimeList *mwSametimeList_load(const char *data) {
647
struct mwSametimeList *l;
649
g_return_val_if_fail(data != NULL, NULL);
651
l = mwSametimeList_new();
658
void mwSametimeList_get(struct mwGetBuffer *b, struct mwSametimeList *l) {
661
g_return_if_fail(l != NULL);
662
g_return_if_fail(b != NULL);
664
mwString_get(b, &str);