| 1 |
|
| 2 /* |
|
| 3 Meanwhile - Unofficial Lotus Sametime Community Client Library |
|
| 4 Copyright (C) 2004 Christopher (siege) O'Brien |
|
| 5 |
|
| 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. |
|
| 10 |
|
| 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. |
|
| 15 |
|
| 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 |
|
| 19 */ |
|
| 20 |
|
| 21 #include <stdio.h> |
|
| 22 #include <string.h> |
|
| 23 #include <glib/gstring.h> |
|
| 24 |
|
| 25 #include "mw_debug.h" |
|
| 26 #include "mw_util.h" |
|
| 27 #include "mw_st_list.h" |
|
| 28 |
|
| 29 |
|
| 30 struct mwSametimeList { |
|
| 31 guint ver_major; |
|
| 32 guint ver_minor; |
|
| 33 guint ver_micro; |
|
| 34 |
|
| 35 GList *groups; |
|
| 36 }; |
|
| 37 |
|
| 38 |
|
| 39 struct mwSametimeGroup { |
|
| 40 struct mwSametimeList *list; |
|
| 41 |
|
| 42 enum mwSametimeGroupType type; |
|
| 43 char *name; |
|
| 44 char *alias; |
|
| 45 gboolean open; |
|
| 46 |
|
| 47 GList *users; |
|
| 48 }; |
|
| 49 |
|
| 50 |
|
| 51 struct mwSametimeUser { |
|
| 52 struct mwSametimeGroup *group; |
|
| 53 |
|
| 54 enum mwSametimeUserType type; |
|
| 55 struct mwIdBlock id; |
|
| 56 char *name; |
|
| 57 char *alias; |
|
| 58 }; |
|
| 59 |
|
| 60 |
|
| 61 static void user_free(struct mwSametimeUser *u) { |
|
| 62 struct mwSametimeGroup *g; |
|
| 63 |
|
| 64 g = u->group; |
|
| 65 g->users = g_list_remove(g->users, u); |
|
| 66 |
|
| 67 mwIdBlock_clear(&u->id); |
|
| 68 g_free(u->name); |
|
| 69 g_free(u->alias); |
|
| 70 g_free(u); |
|
| 71 } |
|
| 72 |
|
| 73 |
|
| 74 static void group_free(struct mwSametimeGroup *g) { |
|
| 75 struct mwSametimeList *l; |
|
| 76 |
|
| 77 l = g->list; |
|
| 78 l->groups = g_list_remove(l->groups, g); |
|
| 79 |
|
| 80 while(g->users) |
|
| 81 mwSametimeUser_free(g->users->data); |
|
| 82 |
|
| 83 g_free(g->name); |
|
| 84 g_free(g->alias); |
|
| 85 g_free(g); |
|
| 86 } |
|
| 87 |
|
| 88 |
|
| 89 static void list_free(struct mwSametimeList *l) { |
|
| 90 while(l->groups) |
|
| 91 mwSametimeGroup_free(l->groups->data); |
|
| 92 |
|
| 93 g_free(l); |
|
| 94 } |
|
| 95 |
|
| 96 |
|
| 97 struct mwSametimeList * |
|
| 98 mwSametimeList_new() { |
|
| 99 |
|
| 100 struct mwSametimeList *stl; |
|
| 101 |
|
| 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; |
|
| 106 |
|
| 107 return stl; |
|
| 108 } |
|
| 109 |
|
| 110 |
|
| 111 void mwSametimeList_setMajor(struct mwSametimeList *l, guint v) { |
|
| 112 g_return_if_fail(l != NULL); |
|
| 113 l->ver_major = v; |
|
| 114 } |
|
| 115 |
|
| 116 |
|
| 117 guint mwSametimeList_getMajor(struct mwSametimeList *l) { |
|
| 118 g_return_val_if_fail(l != NULL, 0); |
|
| 119 return l->ver_major; |
|
| 120 } |
|
| 121 |
|
| 122 |
|
| 123 void mwSametimeList_setMinor(struct mwSametimeList *l, guint v) { |
|
| 124 g_return_if_fail(l != NULL); |
|
| 125 l->ver_minor = v; |
|
| 126 } |
|
| 127 |
|
| 128 |
|
| 129 guint mwSametimeList_getMinor(struct mwSametimeList *l) { |
|
| 130 g_return_val_if_fail(l != NULL, 0); |
|
| 131 return l->ver_minor; |
|
| 132 } |
|
| 133 |
|
| 134 |
|
| 135 void mwSametimeList_setMicro(struct mwSametimeList *l, guint v) { |
|
| 136 g_return_if_fail(l != NULL); |
|
| 137 l->ver_micro = v; |
|
| 138 } |
|
| 139 |
|
| 140 |
|
| 141 guint mwSametimeList_getMicro(struct mwSametimeList *l) { |
|
| 142 g_return_val_if_fail(l != NULL, 0); |
|
| 143 return l->ver_micro; |
|
| 144 } |
|
| 145 |
|
| 146 |
|
| 147 GList *mwSametimeList_getGroups(struct mwSametimeList *l) { |
|
| 148 g_return_val_if_fail(l != NULL, NULL); |
|
| 149 return g_list_copy(l->groups); |
|
| 150 } |
|
| 151 |
|
| 152 |
|
| 153 struct mwSametimeGroup * |
|
| 154 mwSametimeList_findGroup(struct mwSametimeList *l, |
|
| 155 const char *name) { |
|
| 156 GList *s; |
|
| 157 |
|
| 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); |
|
| 161 |
|
| 162 for(s = l->groups; s; s = s->next) { |
|
| 163 struct mwSametimeGroup *g = s->data; |
|
| 164 if(! strcmp(g->name, name)) return g; |
|
| 165 } |
|
| 166 |
|
| 167 return NULL; |
|
| 168 } |
|
| 169 |
|
| 170 |
|
| 171 void mwSametimeList_free(struct mwSametimeList *l) { |
|
| 172 g_return_if_fail(l != NULL); |
|
| 173 list_free(l); |
|
| 174 } |
|
| 175 |
|
| 176 |
|
| 177 struct mwSametimeGroup * |
|
| 178 mwSametimeGroup_new(struct mwSametimeList *list, |
|
| 179 enum mwSametimeGroupType type, |
|
| 180 const char *name) { |
|
| 181 |
|
| 182 struct mwSametimeGroup *stg; |
|
| 183 |
|
| 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); |
|
| 187 |
|
| 188 stg = g_new0(struct mwSametimeGroup, 1); |
|
| 189 stg->list = list; |
|
| 190 stg->type = type; |
|
| 191 stg->name = g_strdup(name); |
|
| 192 |
|
| 193 list->groups = g_list_append(list->groups, stg); |
|
| 194 |
|
| 195 return stg; |
|
| 196 } |
|
| 197 |
|
| 198 |
|
| 199 enum mwSametimeGroupType mwSametimeGroup_getType(struct mwSametimeGroup *g) { |
|
| 200 g_return_val_if_fail(g != NULL, mwSametimeGroup_UNKNOWN); |
|
| 201 return g->type; |
|
| 202 } |
|
| 203 |
|
| 204 |
|
| 205 const char *mwSametimeGroup_getName(struct mwSametimeGroup *g) { |
|
| 206 g_return_val_if_fail(g != NULL, NULL); |
|
| 207 return g->name; |
|
| 208 } |
|
| 209 |
|
| 210 |
|
| 211 void mwSametimeGroup_setAlias(struct mwSametimeGroup *g, |
|
| 212 const char *alias) { |
|
| 213 g_return_if_fail(g != NULL); |
|
| 214 |
|
| 215 g_free(g->alias); |
|
| 216 g->alias = g_strdup(alias); |
|
| 217 } |
|
| 218 |
|
| 219 |
|
| 220 const char *mwSametimeGroup_getAlias(struct mwSametimeGroup *g) { |
|
| 221 g_return_val_if_fail(g != NULL, NULL); |
|
| 222 return g->alias; |
|
| 223 } |
|
| 224 |
|
| 225 |
|
| 226 void mwSametimeGroup_setOpen(struct mwSametimeGroup *g, gboolean open) { |
|
| 227 g_return_if_fail(g != NULL); |
|
| 228 g->open = open; |
|
| 229 } |
|
| 230 |
|
| 231 |
|
| 232 gboolean mwSametimeGroup_isOpen(struct mwSametimeGroup *g) { |
|
| 233 g_return_val_if_fail(g != NULL, FALSE); |
|
| 234 return g->open; |
|
| 235 } |
|
| 236 |
|
| 237 |
|
| 238 struct mwSametimeList *mwSametimeGroup_getList(struct mwSametimeGroup *g) { |
|
| 239 g_return_val_if_fail(g != NULL, NULL); |
|
| 240 return g->list; |
|
| 241 } |
|
| 242 |
|
| 243 |
|
| 244 GList *mwSametimeGroup_getUsers(struct mwSametimeGroup *g) { |
|
| 245 g_return_val_if_fail(g != NULL, NULL); |
|
| 246 return g_list_copy(g->users); |
|
| 247 } |
|
| 248 |
|
| 249 |
|
| 250 struct mwSametimeUser * |
|
| 251 mwSametimeGroup_findUser(struct mwSametimeGroup *g, |
|
| 252 struct mwIdBlock *user) { |
|
| 253 GList *s; |
|
| 254 |
|
| 255 g_return_val_if_fail(g != NULL, NULL); |
|
| 256 g_return_val_if_fail(user != NULL, NULL); |
|
| 257 |
|
| 258 for(s = g->users; s; s = s->next) { |
|
| 259 struct mwSametimeUser *u = s->data; |
|
| 260 if(mwIdBlock_equal(user, &u->id)) return u; |
|
| 261 } |
|
| 262 |
|
| 263 return NULL; |
|
| 264 } |
|
| 265 |
|
| 266 |
|
| 267 void mwSametimeGroup_free(struct mwSametimeGroup *g) { |
|
| 268 g_return_if_fail(g != NULL); |
|
| 269 g_return_if_fail(g->list != NULL); |
|
| 270 group_free(g); |
|
| 271 } |
|
| 272 |
|
| 273 |
|
| 274 struct mwSametimeUser * |
|
| 275 mwSametimeUser_new(struct mwSametimeGroup *group, |
|
| 276 enum mwSametimeUserType type, |
|
| 277 struct mwIdBlock *id) { |
|
| 278 |
|
| 279 struct mwSametimeUser *stu; |
|
| 280 |
|
| 281 g_return_val_if_fail(group != NULL, NULL); |
|
| 282 g_return_val_if_fail(id != NULL, NULL); |
|
| 283 |
|
| 284 stu = g_new0(struct mwSametimeUser, 1); |
|
| 285 stu->group = group; |
|
| 286 stu->type = type; |
|
| 287 mwIdBlock_clone(&stu->id, id); |
|
| 288 |
|
| 289 group->users = g_list_append(group->users, stu); |
|
| 290 |
|
| 291 return stu; |
|
| 292 } |
|
| 293 |
|
| 294 |
|
| 295 struct mwSametimeGroup *mwSametimeUser_getGroup(struct mwSametimeUser *u) { |
|
| 296 g_return_val_if_fail(u != NULL, NULL); |
|
| 297 return u->group; |
|
| 298 } |
|
| 299 |
|
| 300 |
|
| 301 enum mwSametimeUserType mwSametimeUser_getType(struct mwSametimeUser *u) { |
|
| 302 g_return_val_if_fail(u != NULL, mwSametimeUser_UNKNOWN); |
|
| 303 return u->type; |
|
| 304 } |
|
| 305 |
|
| 306 |
|
| 307 const char *mwSametimeUser_getUser(struct mwSametimeUser *u) { |
|
| 308 g_return_val_if_fail(u != NULL, NULL); |
|
| 309 return u->id.user; |
|
| 310 } |
|
| 311 |
|
| 312 |
|
| 313 const char *mwSametimeUser_getCommunity(struct mwSametimeUser *u) { |
|
| 314 g_return_val_if_fail(u != NULL, NULL); |
|
| 315 return u->id.community; |
|
| 316 } |
|
| 317 |
|
| 318 |
|
| 319 void mwSametimeUser_setShortName(struct mwSametimeUser *u, const char *name) { |
|
| 320 g_return_if_fail(u != NULL); |
|
| 321 g_free(u->name); |
|
| 322 u->name = g_strdup(name); |
|
| 323 } |
|
| 324 |
|
| 325 |
|
| 326 const char *mwSametimeUser_getShortName(struct mwSametimeUser *u) { |
|
| 327 g_return_val_if_fail(u != NULL, NULL); |
|
| 328 return u->name; |
|
| 329 } |
|
| 330 |
|
| 331 |
|
| 332 void mwSametimeUser_setAlias(struct mwSametimeUser *u, const char *alias) { |
|
| 333 g_return_if_fail(u != NULL); |
|
| 334 g_free(u->alias); |
|
| 335 u->alias = g_strdup(alias); |
|
| 336 } |
|
| 337 |
|
| 338 |
|
| 339 const char *mwSametimeUser_getAlias(struct mwSametimeUser *u) { |
|
| 340 g_return_val_if_fail(u != NULL, NULL); |
|
| 341 return u->alias; |
|
| 342 } |
|
| 343 |
|
| 344 |
|
| 345 void mwSametimeUser_free(struct mwSametimeUser *u) { |
|
| 346 g_return_if_fail(u != NULL); |
|
| 347 g_return_if_fail(u->group != NULL); |
|
| 348 user_free(u); |
|
| 349 } |
|
| 350 |
|
| 351 |
|
| 352 static void str_replace(char *str, char from, char to) { |
|
| 353 if(! str) return; |
|
| 354 for(; *str; str++) if(*str == from) *str = to; |
|
| 355 } |
|
| 356 |
|
| 357 |
|
| 358 static char user_type_to_char(enum mwSametimeUserType type) { |
|
| 359 switch(type) { |
|
| 360 case mwSametimeUser_NORMAL: return '1'; |
|
| 361 case mwSametimeUser_EXTERNAL: return '2'; |
|
| 362 case mwSametimeUser_UNKNOWN: |
|
| 363 default: return '9'; |
|
| 364 } |
|
| 365 } |
|
| 366 |
|
| 367 |
|
| 368 static enum mwSametimeUserType user_char_to_type(char type) { |
|
| 369 switch(type) { |
|
| 370 case '1': return mwSametimeUser_NORMAL; |
|
| 371 case '2': return mwSametimeUser_EXTERNAL; |
|
| 372 default: return mwSametimeUser_UNKNOWN; |
|
| 373 } |
|
| 374 } |
|
| 375 |
|
| 376 |
|
| 377 static void user_put(GString *str, struct mwSametimeUser *u) { |
|
| 378 char *id, *name, *alias; |
|
| 379 char type; |
|
| 380 |
|
| 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); |
|
| 385 |
|
| 386 if(id) str_replace(id, ' ', ';'); |
|
| 387 if(name) str_replace(name, ' ', ';'); |
|
| 388 if(alias) str_replace(alias, ' ', ';'); |
|
| 389 |
|
| 390 if(!name && alias) { |
|
| 391 name = alias; |
|
| 392 alias = NULL; |
|
| 393 } |
|
| 394 |
|
| 395 g_string_append_printf(str, "U %s%c:: %s,%s\r\n", |
|
| 396 id, type, (name? name: ""), (alias? alias: "")); |
|
| 397 |
|
| 398 g_free(id); |
|
| 399 g_free(name); |
|
| 400 g_free(alias); |
|
| 401 } |
|
| 402 |
|
| 403 |
|
| 404 static char group_type_to_char(enum mwSametimeGroupType type) { |
|
| 405 switch(type) { |
|
| 406 case mwSametimeGroup_NORMAL: return '2'; |
|
| 407 case mwSametimeGroup_DYNAMIC: return '3'; |
|
| 408 case mwSametimeGroup_UNKNOWN: |
|
| 409 default: return '9'; |
|
| 410 } |
|
| 411 } |
|
| 412 |
|
| 413 |
|
| 414 static enum mwSametimeGroupType group_char_to_type(char type) { |
|
| 415 switch(type) { |
|
| 416 case '2': return mwSametimeGroup_NORMAL; |
|
| 417 case '3': return mwSametimeGroup_DYNAMIC; |
|
| 418 default: return mwSametimeGroup_UNKNOWN; |
|
| 419 } |
|
| 420 } |
|
| 421 |
|
| 422 |
|
| 423 static void group_put(GString *str, struct mwSametimeGroup *g) { |
|
| 424 char *name, *alias; |
|
| 425 char type; |
|
| 426 GList *gl; |
|
| 427 |
|
| 428 name = g_strdup(g->name); |
|
| 429 alias = g_strdup((g->alias)? g->alias: name); |
|
| 430 type = group_type_to_char(g->type); |
|
| 431 |
|
| 432 str_replace(name, ' ', ';'); |
|
| 433 str_replace(alias, ' ', ';'); |
|
| 434 |
|
| 435 g_string_append_printf(str, "G %s%c %s %c\r\n", |
|
| 436 name, type, alias, (g->open? 'O':'C')); |
|
| 437 |
|
| 438 for(gl = g->users; gl; gl = gl->next) { |
|
| 439 user_put(str, gl->data); |
|
| 440 } |
|
| 441 |
|
| 442 g_free(name); |
|
| 443 g_free(alias); |
|
| 444 } |
|
| 445 |
|
| 446 |
|
| 447 /** composes a GString with the written contents of a sametime list */ |
|
| 448 static GString *list_store(struct mwSametimeList *l) { |
|
| 449 GString *str; |
|
| 450 GList *gl; |
|
| 451 |
|
| 452 g_return_val_if_fail(l != NULL, NULL); |
|
| 453 |
|
| 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); |
|
| 457 |
|
| 458 for(gl = l->groups; gl; gl = gl->next) { |
|
| 459 group_put(str, gl->data); |
|
| 460 } |
|
| 461 |
|
| 462 return str; |
|
| 463 } |
|
| 464 |
|
| 465 |
|
| 466 char *mwSametimeList_store(struct mwSametimeList *l) { |
|
| 467 GString *str; |
|
| 468 char *s; |
|
| 469 |
|
| 470 g_return_val_if_fail(l != NULL, NULL); |
|
| 471 |
|
| 472 str = list_store(l); |
|
| 473 s = str->str; |
|
| 474 g_string_free(str, FALSE); |
|
| 475 return s; |
|
| 476 } |
|
| 477 |
|
| 478 |
|
| 479 void mwSametimeList_put(struct mwPutBuffer *b, struct mwSametimeList *l) { |
|
| 480 GString *str; |
|
| 481 guint16 len; |
|
| 482 |
|
| 483 g_return_if_fail(l != NULL); |
|
| 484 g_return_if_fail(b != NULL); |
|
| 485 |
|
| 486 str = list_store(l); |
|
| 487 len = (guint16) str->len; |
|
| 488 guint16_put(b, len); |
|
| 489 mwPutBuffer_write(b, str->str, len); |
|
| 490 |
|
| 491 g_string_free(str, TRUE); |
|
| 492 } |
|
| 493 |
|
| 494 |
|
| 495 static void get_version(const char *line, struct mwSametimeList *l) { |
|
| 496 guint major = 0, minor = 0, micro = 0; |
|
| 497 int ret; |
|
| 498 |
|
| 499 ret = sscanf(line, "Version=%u.%u.%u\n", &major, &minor, µ); |
|
| 500 if(ret != 3) { |
|
| 501 g_warning("strange sametime list version line:\n%s", line); |
|
| 502 } |
|
| 503 |
|
| 504 l->ver_major = major; |
|
| 505 l->ver_minor = minor; |
|
| 506 l->ver_micro = micro; |
|
| 507 } |
|
| 508 |
|
| 509 |
|
| 510 static struct mwSametimeGroup *get_group(const char *line, |
|
| 511 struct mwSametimeList *l) { |
|
| 512 struct mwSametimeGroup *group; |
|
| 513 char *name, *alias; |
|
| 514 char type = '2', open = 'O'; |
|
| 515 int ret; |
|
| 516 |
|
| 517 ret = strlen(line); |
|
| 518 name = g_malloc0(ret); |
|
| 519 alias = g_malloc0(ret); |
|
| 520 |
|
| 521 ret = sscanf(line, "G %s %s %c\n", |
|
| 522 name, alias, &open); |
|
| 523 |
|
| 524 if(ret < 3) { |
|
| 525 g_warning("strange sametime list group line:\n%s", line); |
|
| 526 } |
|
| 527 |
|
| 528 str_replace(name, ';', ' '); |
|
| 529 str_replace(alias, ';', ' '); |
|
| 530 |
|
| 531 if(name && *name) { |
|
| 532 int l = strlen(name)-1; |
|
| 533 type = name[l]; |
|
| 534 name[l] = '\0'; |
|
| 535 } |
|
| 536 |
|
| 537 group = g_new0(struct mwSametimeGroup, 1); |
|
| 538 group->list = l; |
|
| 539 group->name = name; |
|
| 540 group->type = group_char_to_type(type); |
|
| 541 group->alias = alias; |
|
| 542 group->open = (open == 'O'); |
|
| 543 |
|
| 544 l->groups = g_list_append(l->groups, group); |
|
| 545 |
|
| 546 return group; |
|
| 547 } |
|
| 548 |
|
| 549 |
|
| 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; |
|
| 554 char type = '1'; |
|
| 555 int ret; |
|
| 556 |
|
| 557 ret = strlen(line); |
|
| 558 idb.user = g_malloc0(ret); |
|
| 559 name = g_malloc0(ret); |
|
| 560 |
|
| 561 ret = sscanf(line, "U %s %s", |
|
| 562 idb.user, name); |
|
| 563 |
|
| 564 if(ret < 2) { |
|
| 565 g_warning("strange sametime list user line:\n%s", line); |
|
| 566 } |
|
| 567 |
|
| 568 str_replace(idb.user, ';', ' '); |
|
| 569 str_replace(name, ';', ' '); |
|
| 570 |
|
| 571 if(idb.user && *idb.user) { |
|
| 572 char *tmp = strstr(idb.user, "::"); |
|
| 573 if(tmp--) { |
|
| 574 type = *(tmp); |
|
| 575 *tmp = '\0'; |
|
| 576 } |
|
| 577 } |
|
| 578 |
|
| 579 if(name && *name) { |
|
| 580 char *tmp = strrchr(name, ','); |
|
| 581 if(tmp) { |
|
| 582 *tmp++ = '\0'; |
|
| 583 if(*tmp) alias = tmp; |
|
| 584 } |
|
| 585 } |
|
| 586 |
|
| 587 user = g_new0(struct mwSametimeUser, 1); |
|
| 588 user->group = g; |
|
| 589 user->id.user = idb.user; |
|
| 590 user->type = user_char_to_type(type); |
|
| 591 user->name = name; |
|
| 592 user->alias = g_strdup(alias); |
|
| 593 |
|
| 594 g->users = g_list_append(g->users, user); |
|
| 595 } |
|
| 596 |
|
| 597 |
|
| 598 /** returns a line from str, and advances str */ |
|
| 599 static char *fetch_line(char **str) { |
|
| 600 char *start = *str; |
|
| 601 char *end; |
|
| 602 |
|
| 603 /* move to first non-whitespace character */ |
|
| 604 while(*start && g_ascii_isspace(*start)) start++; |
|
| 605 if(! *start) return NULL; |
|
| 606 |
|
| 607 for(end = start + 1; *end; end++) { |
|
| 608 if(*end == '\n' || *end == '\r') { |
|
| 609 *(end++) = '\0'; |
|
| 610 break; |
|
| 611 } |
|
| 612 } |
|
| 613 |
|
| 614 *str = end; |
|
| 615 return start; |
|
| 616 } |
|
| 617 |
|
| 618 |
|
| 619 void list_get(const char *lines, struct mwSametimeList *l) { |
|
| 620 char *s = (char *) lines; |
|
| 621 char *line; |
|
| 622 |
|
| 623 struct mwSametimeGroup *g = NULL; |
|
| 624 |
|
| 625 while( (line = fetch_line(&s)) ) { |
|
| 626 switch(*line) { |
|
| 627 case 'V': |
|
| 628 get_version(line, l); |
|
| 629 break; |
|
| 630 |
|
| 631 case 'G': |
|
| 632 g = get_group(line, l); |
|
| 633 break; |
|
| 634 |
|
| 635 case 'U': |
|
| 636 get_user(line, g); |
|
| 637 break; |
|
| 638 |
|
| 639 default: |
|
| 640 g_warning("unknown sametime list data line:\n%s", line); |
|
| 641 } |
|
| 642 } |
|
| 643 } |
|
| 644 |
|
| 645 |
|
| 646 struct mwSametimeList *mwSametimeList_load(const char *data) { |
|
| 647 struct mwSametimeList *l; |
|
| 648 |
|
| 649 g_return_val_if_fail(data != NULL, NULL); |
|
| 650 |
|
| 651 l = mwSametimeList_new(); |
|
| 652 list_get(data, l); |
|
| 653 |
|
| 654 return l; |
|
| 655 } |
|
| 656 |
|
| 657 |
|
| 658 void mwSametimeList_get(struct mwGetBuffer *b, struct mwSametimeList *l) { |
|
| 659 char *str = NULL; |
|
| 660 |
|
| 661 g_return_if_fail(l != NULL); |
|
| 662 g_return_if_fail(b != NULL); |
|
| 663 |
|
| 664 mwString_get(b, &str); |
|
| 665 list_get(str, l); |
|
| 666 g_free(str); |
|
| 667 } |
|
| 668 |
|