~ubuntu-branches/ubuntu/karmic/ekiga/karmic

« back to all changes in this revision

Viewing changes to lib/engine/components/resource-list/rl-heap.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ken VanDine
  • Date: 2009-03-17 15:14:12 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090317151412-no6uq0wl8zz2hsw3
Tags: 3.2.0-0ubuntu1
* New upstream release (LP: #341367)
  - Better NAT support in case of Cone NAT
  - Uniformise detection of libnotify; fix compilation with mingw
  - Fix "URL completion combobox shows identical completions"
  - Fix "Assistant loosing values when going backward"
  - Fix GmConf settings when compiled with another package name
  - Fix unregistration of accounts
  - Fix build with --enable-kde
  - Fixed possible crash when retrieving presence information
  - New translations: crh, or
  - Updated translations: as, bg, bn_IN, da, de, el, eu, gl, gu, hi, hu,
    ja, kn, ko, ku, lt, ml, mr, or, pt, ro, ru, ta, te, tr
  - New help translation: en_GB
  - Updated help translation: fr
  - Better NAT support in case of Cone NAT
  - There is now only one H.263 plugin implementing both H.263 and H.263+
  - Allow several ALSA devices to have the same name
  - Added support for the G.722 audio codec: G.722 is a 16 kHz wideband
    audio codec advertised as HD Voice by the famous Polycom. It is a
    great boost in quality and interoperability
  - Added support for the CELT ultral-low delay audio codec: CELT delivers
    high quality audio at 32 kHz or 48 kHz, allowing to transmit music in
    high quality, with low delay and low bitrate
  - Added support for SIP dialog-info notifications: they allow displaying
    notifications of incoming calls in the roster. With software like
    kamailio or Asterisk, it allows being informed of incoming calls
    reaching your colleagues
  - Largely improved LDAP support: the OpenLDAP guys contributed several
    patches to provide state-of-the-art LDAP support in the Ekiga address
    book. The new code even supports authentication
  - Killed the gconf_test_age test, Ekiga can now finally work with
    badly installed GConf schemas
  - Better handling of multiple network interfaces with dynamic addition
    and removal
  - Added settings migration from Ekiga 2.0.x.
  - Other various fixes, cleanups, removal of deprecated symbols etc.
  - New translations: crh, or
  - New help translation: en_GB, eu
  - Updated many translations and help
  - Experimental features:
    * Significant improvements in IPv6 support
    * Gstreamer audio and video capture support near to be finished...
* debian/patches/migrate_2.0_settings.patch:
  - Removed, migration is now upstream
* debian/patches/00_news.patch
  - Removed
* debian/patches/ubuntu_lpi.patch:
  - Modified to work with 3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* Ekiga -- A VoIP and Video-Conferencing application
 
3
 * Copyright (C) 2000-2009 Damien Sandras <dsandras@seconix.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software Foundation,
 
17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 
18
 *
 
19
 *
 
20
 * Ekiga is licensed under the GPL license and as a special exception,
 
21
 * you have permission to link or otherwise combine this program with the
 
22
 * programs OPAL, OpenH323 and PWLIB, and distribute the combination,
 
23
 * without applying the requirements of the GNU GPL to the OPAL, OpenH323
 
24
 * and PWLIB programs, as long as you do follow the requirements of the
 
25
 * GNU GPL for all the rest of the software thus combined.
 
26
 */
 
27
 
 
28
 
 
29
/*
 
30
 *                         rl-heap.cpp  -  description
 
31
 *                         ------------------------------------------
 
32
 *   begin                : written in 2008 by Julien Puydt
 
33
 *   copyright            : (c) 2008 by Julien Puydt
 
34
 *   description          : resource-list heap implementation
 
35
 *
 
36
 */
 
37
 
 
38
#include <glib/gi18n.h>
 
39
 
 
40
#include <iostream>
 
41
 
 
42
#include "robust-xml.h"
 
43
#include "form-request-simple.h"
 
44
#include "xcap-core.h"
 
45
 
 
46
#include "rl-heap.h"
 
47
 
 
48
RL::Heap::Heap (Ekiga::ServiceCore& services_,
 
49
                xmlNodePtr node_):
 
50
  services(services_),
 
51
  node(node_), name(NULL),
 
52
  root(NULL), user(NULL),
 
53
  username(NULL), password(NULL),
 
54
  doc(NULL), list_node(NULL)
 
55
{
 
56
  {
 
57
    xmlChar* xml_str = NULL;
 
58
 
 
59
    xml_str = xmlGetProp (node, BAD_CAST "writable");
 
60
    if (xml_str != NULL)
 
61
      xmlFree (xml_str);
 
62
    else {
 
63
      xmlSetProp (node, BAD_CAST "writable", BAD_CAST "0");
 
64
    }
 
65
  }
 
66
 
 
67
  for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
 
68
 
 
69
    if (child->type == XML_ELEMENT_NODE
 
70
        && child->name != NULL) {
 
71
 
 
72
      if (xmlStrEqual (BAD_CAST ("name"), child->name)) {
 
73
 
 
74
        name = child;
 
75
        continue;
 
76
      }
 
77
      if (xmlStrEqual (BAD_CAST ("root"), child->name)) {
 
78
 
 
79
        root = child;
 
80
        continue;
 
81
      }
 
82
      if (xmlStrEqual (BAD_CAST ("user"), child->name)) {
 
83
 
 
84
        user = child;
 
85
        continue;
 
86
      }
 
87
      if (xmlStrEqual (BAD_CAST ("username"), child->name)) {
 
88
 
 
89
        username = child;
 
90
        continue;
 
91
      }
 
92
      if (xmlStrEqual (BAD_CAST ("password"), child->name)) {
 
93
 
 
94
        password = child;
 
95
        continue;
 
96
      }
 
97
    }
 
98
  }
 
99
 
 
100
  if (name == NULL)
 
101
    name = xmlNewChild (node, NULL, BAD_CAST "name",
 
102
                        BAD_CAST robust_xmlEscape(node->doc,
 
103
                                                  _("Unnamed")).c_str ());
 
104
  if (root == NULL)
 
105
    root = xmlNewChild (node, NULL, BAD_CAST "root", BAD_CAST "");
 
106
  if (user == NULL)
 
107
    user = xmlNewChild (node, NULL, BAD_CAST "user", BAD_CAST "");
 
108
  if (username == NULL)
 
109
    username = xmlNewChild (node, NULL, BAD_CAST "username", BAD_CAST "");
 
110
  if (password == NULL)
 
111
    password = xmlNewChild (node, NULL, BAD_CAST "password", BAD_CAST "");
 
112
 
 
113
  refresh ();
 
114
}
 
115
 
 
116
RL::Heap::Heap (Ekiga::ServiceCore& services_,
 
117
                const std::string name_,
 
118
                const std::string root_,
 
119
                const std::string user_,
 
120
                const std::string username_,
 
121
                const std::string password_,
 
122
                bool writable_):
 
123
  services(services_),
 
124
  node(NULL), name(NULL),
 
125
  root(NULL), user(NULL),
 
126
  username(NULL), password(NULL),
 
127
  doc(NULL), list_node(NULL)
 
128
{
 
129
  node = xmlNewNode (NULL, BAD_CAST "entry");
 
130
  if (writable_)
 
131
    xmlSetProp (node, BAD_CAST "writable", BAD_CAST "1");
 
132
  else
 
133
    xmlSetProp (node, BAD_CAST "writable", BAD_CAST "0");
 
134
 
 
135
  if ( !name_.empty ())
 
136
    name = xmlNewChild (node, NULL,
 
137
                        BAD_CAST "name",
 
138
                        BAD_CAST robust_xmlEscape (node->doc,
 
139
                                                   name_).c_str ());
 
140
  else
 
141
    name = xmlNewChild (node, NULL,
 
142
                        BAD_CAST "name",
 
143
                        BAD_CAST robust_xmlEscape (node->doc,
 
144
                                                   _("Unnamed")).c_str ());
 
145
  root = xmlNewChild (node, NULL,
 
146
                      BAD_CAST "root",
 
147
                      BAD_CAST robust_xmlEscape (node->doc,
 
148
                                                 root_).c_str ());
 
149
  user = xmlNewChild (node, NULL,
 
150
                      BAD_CAST "user",
 
151
                      BAD_CAST robust_xmlEscape (node->doc,
 
152
                                                 user_).c_str ());
 
153
  username = xmlNewChild (node, NULL,
 
154
                          BAD_CAST "username",
 
155
                          BAD_CAST robust_xmlEscape (node->doc,
 
156
                                                     username_).c_str ());
 
157
  password = xmlNewChild (node, NULL,
 
158
                          BAD_CAST "password",
 
159
                          BAD_CAST robust_xmlEscape (node->doc,
 
160
                                                     password_).c_str ());
 
161
  refresh ();
 
162
}
 
163
 
 
164
RL::Heap::~Heap ()
 
165
{
 
166
  if (doc != NULL)
 
167
    xmlFreeDoc (doc);
 
168
}
 
169
 
 
170
const std::string
 
171
RL::Heap::get_name () const
 
172
{
 
173
  std::string result;
 
174
  xmlChar* str = xmlNodeGetContent (name);
 
175
  if (str != NULL)
 
176
    result = (const char*)str;
 
177
  else
 
178
    result = _("Unnamed");
 
179
 
 
180
  xmlFree (str);
 
181
 
 
182
  return result;
 
183
}
 
184
 
 
185
void
 
186
RL::Heap::visit_presentities (sigc::slot1<bool, gmref_ptr<Ekiga::Presentity> > visitor)
 
187
{
 
188
  bool go_on = true;
 
189
 
 
190
  for (std::map<gmref_ptr<Presentity>,std::list<sigc::connection> >::iterator
 
191
         iter = presentities.begin ();
 
192
       go_on && iter != presentities.end ();
 
193
       ++iter)
 
194
    go_on = visitor (iter->first);
 
195
}
 
196
 
 
197
bool
 
198
RL::Heap::populate_menu (Ekiga::MenuBuilder& builder)
 
199
{
 
200
  builder.add_action ("add", _("_Add a new contact"),
 
201
                      sigc::mem_fun (this, &RL::Heap::new_entry));
 
202
  builder.add_action ("refresh", _("_Refresh contact list"),
 
203
                      sigc::mem_fun (this, &RL::Heap::refresh));
 
204
  builder.add_action ("properties", _("Contact list _properties"),
 
205
                      sigc::mem_fun (this, &RL::Heap::edit));
 
206
  return true;
 
207
}
 
208
 
 
209
bool
 
210
RL::Heap::populate_menu_for_group (std::string /*group*/,
 
211
                                   Ekiga::MenuBuilder& /*builder*/)
 
212
{
 
213
  return false; // FIXME
 
214
}
 
215
 
 
216
xmlNodePtr
 
217
RL::Heap::get_node () const
 
218
{
 
219
  return node;
 
220
}
 
221
 
 
222
void
 
223
RL::Heap::refresh ()
 
224
{
 
225
  gmref_ptr<XCAP::Core> xcap(services.get ("xcap-core"));
 
226
  std::string root_str;
 
227
  std::string username_str;
 
228
  std::string password_str;
 
229
  std::string user_str;
 
230
 
 
231
  {
 
232
    xmlChar* str = xmlNodeGetContent (root);
 
233
    if (str != NULL)
 
234
      root_str = (const char*)str;
 
235
  }
 
236
  {
 
237
    xmlChar* str = xmlNodeGetContent (user);
 
238
    if (str != NULL)
 
239
      user_str = (const char*)str;
 
240
  }
 
241
  {
 
242
    xmlChar* str = xmlNodeGetContent (username);
 
243
    if (str != NULL)
 
244
      username_str = (const char*)str;
 
245
  }
 
246
  {
 
247
    xmlChar* str = xmlNodeGetContent (password);
 
248
    if (str != NULL)
 
249
      password_str = (const char*)str;
 
250
  }
 
251
  gmref_ptr<XCAP::Path> path(new XCAP::Path (root_str, "resource-lists",
 
252
                                             user_str));
 
253
  path->set_credentials (username_str, password_str);
 
254
  path = path->build_child ("resource-lists");
 
255
 
 
256
  while (presentities.begin () != presentities.end ()) {
 
257
 
 
258
    presentities.begin()->first->removed.emit ();
 
259
    for (std::list<sigc::connection>::iterator iter2
 
260
           = presentities.begin()->second.begin ();
 
261
         iter2 != presentities.begin()->second.end ();
 
262
         ++iter2)
 
263
      iter2->disconnect ();
 
264
    presentities.erase (presentities.begin()->first);
 
265
  }
 
266
 
 
267
  if (doc)
 
268
    xmlFreeDoc (doc);
 
269
  doc = NULL;
 
270
 
 
271
  xcap->read (path, sigc::mem_fun (this, &RL::Heap::on_document_received));
 
272
}
 
273
 
 
274
void
 
275
RL::Heap::on_document_received (bool error,
 
276
                                std::string value)
 
277
{
 
278
  if (error) {
 
279
 
 
280
    // FIXME: do something
 
281
    std::cout << "XCAP error: " << value << std::endl;
 
282
  } else {
 
283
 
 
284
    parse_doc (value);
 
285
  }
 
286
}
 
287
 
 
288
void
 
289
RL::Heap::parse_doc (std::string raw)
 
290
{
 
291
  doc = xmlRecoverMemory (raw.c_str (), raw.length ());
 
292
 
 
293
  xmlNodePtr doc_root = xmlDocGetRootElement (doc);
 
294
 
 
295
  if (doc_root == NULL
 
296
      || doc_root->name == NULL
 
297
      || !xmlStrEqual (BAD_CAST "resource-lists", doc_root->name)) {
 
298
 
 
299
    std::cout << "Invalid document in " << __PRETTY_FUNCTION__ << std::endl;
 
300
    // FIXME: warn the user somehow?
 
301
    xmlFreeDoc (doc);
 
302
    doc = NULL;
 
303
  } else {
 
304
 
 
305
 
 
306
    for (xmlNodePtr child = doc_root->children;
 
307
         child != NULL;
 
308
         child = child->next)
 
309
      if (child->type == XML_ELEMENT_NODE
 
310
          && child->name != NULL
 
311
          && xmlStrEqual (BAD_CAST ("list"), child->name)) {
 
312
 
 
313
        parse_list (child);
 
314
        break; // read only one!
 
315
      }
 
316
  }
 
317
}
 
318
 
 
319
void
 
320
RL::Heap::parse_list (xmlNodePtr list)
 
321
{
 
322
  std::string root_str;
 
323
  std::string user_str;
 
324
  std::string username_str;
 
325
  std::string password_str;
 
326
  bool writable = false;
 
327
 
 
328
  list_node = list;
 
329
  {
 
330
    xmlChar* str = xmlNodeGetContent (root);
 
331
    if (str != NULL)
 
332
      root_str = (const char*)str;
 
333
  }
 
334
  {
 
335
    xmlChar* str = xmlNodeGetContent (user);
 
336
    if (str != NULL)
 
337
      user_str = (const char*)str;
 
338
  }
 
339
  {
 
340
    xmlChar* str = xmlNodeGetContent (username);
 
341
    if (str != NULL)
 
342
      username_str = (const char*)str;
 
343
  }
 
344
  {
 
345
    xmlChar* str = xmlNodeGetContent (password);
 
346
    if (str != NULL)
 
347
      password_str = (const char*)str;
 
348
  }
 
349
  {
 
350
    xmlChar* str = xmlGetProp (node, BAD_CAST "writable");
 
351
    if (str != NULL) {
 
352
 
 
353
      if (xmlStrEqual (str, BAD_CAST "1"))
 
354
        writable = true;
 
355
      xmlFree (str);
 
356
    }
 
357
  }
 
358
 
 
359
  gmref_ptr<XCAP::Path> path(new XCAP::Path (root_str, "resource-lists",
 
360
                                             user_str));
 
361
  path->set_credentials (username_str, password_str);
 
362
  path = path->build_child ("resource-lists");
 
363
  path = path->build_child ("list");
 
364
 
 
365
  for (xmlNodePtr child = list->children;
 
366
       child != NULL;
 
367
       child = child->next)
 
368
    if (child->type == XML_ELEMENT_NODE
 
369
        && child->name != NULL
 
370
        && xmlStrEqual (BAD_CAST ("entry"), child->name)) {
 
371
 
 
372
      gmref_ptr<Presentity> presentity(new Presentity (services, path, child, writable));
 
373
      std::list<sigc::connection> conns;
 
374
      conns.push_back (presentity->updated.connect (sigc::bind (presentity_updated.make_slot (),presentity)));
 
375
      conns.push_back (presentity->removed.connect (sigc::bind(presentity_removed.make_slot (),presentity)));
 
376
      conns.push_back (presentity->trigger_reload.connect (sigc::mem_fun (this, &RL::Heap::refresh)));
 
377
      conns.push_back (presentity->questions.connect (questions.make_slot()));
 
378
      presentities[presentity]=conns;
 
379
      presentity_added.emit (presentity);
 
380
      continue;
 
381
    }
 
382
}
 
383
 
 
384
void
 
385
RL::Heap::push_presence (const std::string uri_,
 
386
                         const std::string presence)
 
387
{
 
388
  for (std::map<gmref_ptr<Presentity>,std::list<sigc::connection> >::iterator
 
389
         iter = presentities.begin ();
 
390
       iter != presentities.end ();
 
391
       ++iter) {
 
392
 
 
393
    if (iter->first->get_uri () == uri_)
 
394
      iter->first->set_presence (presence);
 
395
  }
 
396
}
 
397
 
 
398
void
 
399
RL::Heap::push_status (const std::string uri_,
 
400
                       const std::string status)
 
401
{
 
402
  for (std::map<gmref_ptr<Presentity>,std::list<sigc::connection> >::iterator
 
403
         iter = presentities.begin ();
 
404
       iter != presentities.end ();
 
405
       ++iter) {
 
406
 
 
407
    if (iter->first->get_uri () == uri_)
 
408
      iter->first->set_status (status);
 
409
  }
 
410
}
 
411
 
 
412
void
 
413
RL::Heap::edit ()
 
414
{
 
415
  Ekiga::FormRequestSimple request(sigc::mem_fun (this,
 
416
                                                  &RL::Heap::on_edit_form_submitted));
 
417
 
 
418
  std::string name_str;
 
419
  std::string root_str;
 
420
  std::string username_str;
 
421
  std::string password_str;
 
422
  std::string user_str;
 
423
  bool writable = false;
 
424
 
 
425
  {
 
426
    xmlChar* str = xmlNodeGetContent (root);
 
427
    if (str != NULL) {
 
428
 
 
429
      root_str = (const char*)str;
 
430
      xmlFree (str);
 
431
    }
 
432
  }
 
433
  {
 
434
    xmlChar* str = xmlNodeGetContent (user);
 
435
    if (str != NULL) {
 
436
 
 
437
      user_str = (const char*)str;
 
438
      xmlFree (str);
 
439
    }
 
440
  }
 
441
  {
 
442
    xmlChar* str = xmlNodeGetContent (username);
 
443
    if (str != NULL) {
 
444
 
 
445
      username_str = (const char*)str;
 
446
      xmlFree (str);
 
447
    }
 
448
  }
 
449
  {
 
450
    xmlChar* str = xmlNodeGetContent (password);
 
451
    if (str != NULL) {
 
452
 
 
453
      password_str = (const char*)str;
 
454
      xmlFree (str);
 
455
    }
 
456
  }
 
457
  {
 
458
    xmlChar* str = xmlGetProp (node, BAD_CAST "writable");
 
459
    if (str != NULL) {
 
460
 
 
461
      if (xmlStrEqual (str, BAD_CAST "1"))
 
462
        writable = true;
 
463
      xmlFree (str);
 
464
    }
 
465
  }
 
466
 
 
467
  request.title (_("Edit contact list properties"));
 
468
 
 
469
  request.instructions (_("Please edit the following fields (no identifier"
 
470
                          " means global)"));
 
471
 
 
472
  request.text ("name", _("Contact list's name"), get_name ());
 
473
  /* "Document" used as a name -- uri point to the root of a document tree */
 
474
  request.text ("root", _("Document root"), root_str);
 
475
  request.text ("user", _("Identifier"), user_str);
 
476
  request.boolean ("writable", _("Writable"), writable);
 
477
  request.text ("username", _("Server username"), username_str);
 
478
  request.private_text ("password", _("Server password"), password_str);
 
479
 
 
480
  if (!questions.handle_request (&request)) {
 
481
 
 
482
    // FIXME: better error reporting
 
483
#ifdef __GNUC__
 
484
    std::cout << "Unhandled form request in "
 
485
              << __PRETTY_FUNCTION__ << std::endl;
 
486
#endif
 
487
  }
 
488
}
 
489
 
 
490
void
 
491
RL::Heap::on_edit_form_submitted (bool submitted,
 
492
                                  Ekiga::Form& result)
 
493
{
 
494
  if (!submitted)
 
495
    return;
 
496
 
 
497
  try {
 
498
 
 
499
    std::string name_str = result.text ("name");
 
500
    std::string root_str = result.text ("root");
 
501
    std::string user_str = result.text ("user");
 
502
    std::string username_str = result.text ("username");
 
503
    std::string password_str = result.private_text ("password");
 
504
    bool writable = result.boolean ("writable");
 
505
 
 
506
    if (writable)
 
507
      xmlSetProp (node, BAD_CAST "writable", BAD_CAST "1");
 
508
    else
 
509
      xmlSetProp (node, BAD_CAST "writable", BAD_CAST "0");
 
510
    robust_xmlNodeSetContent (node, &name, "name", name_str);
 
511
    robust_xmlNodeSetContent (node, &root, "root", root_str);
 
512
    robust_xmlNodeSetContent (node, &user, "user", user_str);
 
513
    robust_xmlNodeSetContent (node, &username, "username", username_str);
 
514
    robust_xmlNodeSetContent (node, &password, "password", password_str);
 
515
 
 
516
    trigger_saving.emit ();
 
517
    updated.emit ();
 
518
    refresh ();
 
519
  } catch (Ekiga::Form::not_found) {
 
520
 
 
521
    std::cerr << "Invalid result form" << std::endl; // FIXME: do better
 
522
  }
 
523
}
 
524
 
 
525
void
 
526
RL::Heap::new_entry ()
 
527
{
 
528
  Ekiga::FormRequestSimple request(sigc::mem_fun (this, &RL::Heap::on_new_entry_form_submitted));
 
529
 
 
530
  request.title (_("Add a remote contact"));
 
531
  request.instructions (_("Please fill in this form to create a new "
 
532
                          "contact on a remote server"));
 
533
 
 
534
  std::set<std::string> all_groups;
 
535
  for (std::map<gmref_ptr<Presentity>,std::list<sigc::connection> >::iterator
 
536
         iter = presentities.begin ();
 
537
       iter != presentities.end ();
 
538
       ++iter) {
 
539
 
 
540
    std::set<std::string> groups = iter->first->get_groups ();
 
541
    all_groups.insert (groups.begin (), groups.end ());
 
542
  }
 
543
 
 
544
  request.text ("name", _("Name:"), "");
 
545
  request.text ("uri", _("Address:"), "");
 
546
  request.editable_set ("groups", _("Choose groups:"),
 
547
                        std::set<std::string>(), all_groups);
 
548
 
 
549
  if (!questions.handle_request (&request)) {
 
550
 
 
551
    // FIXME: better error reporting
 
552
#ifdef __GNUC__
 
553
    std::cout << "Unhandled form request in "
 
554
              << __PRETTY_FUNCTION__ << std::endl;
 
555
#endif
 
556
  }
 
557
}
 
558
 
 
559
void
 
560
RL::Heap::on_new_entry_form_submitted (bool submitted,
 
561
                                       Ekiga::Form& result)
 
562
{
 
563
  if (!submitted)
 
564
    return;
 
565
 
 
566
  try {
 
567
 
 
568
    std::string entry_name = result.text ("name");
 
569
    std::string entry_uri = result.text ("uri");
 
570
    std::set<std::string> entry_groups = result.editable_set ("groups");
 
571
 
 
572
    xmlNodePtr entry_node = xmlNewChild (list_node, NULL,
 
573
                                         BAD_CAST "entry", NULL);
 
574
    xmlSetProp (entry_node, BAD_CAST "uri",
 
575
                BAD_CAST robust_xmlEscape (doc, entry_uri).c_str ());
 
576
    xmlNewChild (entry_node, NULL, BAD_CAST "display-name",
 
577
                 BAD_CAST robust_xmlEscape (doc, entry_name).c_str ());
 
578
    xmlNsPtr ns = xmlSearchNsByHref (doc, entry_node,
 
579
                                     BAD_CAST "http://www.ekiga.org");
 
580
    if (ns == NULL) {
 
581
 
 
582
      // FIXME: we should handle the case, even if it shouldn't happen
 
583
    }
 
584
 
 
585
    for (std::set<std::string>::const_iterator iter = entry_groups.begin ();
 
586
         iter != entry_groups.end ();
 
587
         ++iter) {
 
588
 
 
589
      xmlNewChild (entry_node, ns, BAD_CAST "group",
 
590
                   BAD_CAST robust_xmlEscape (doc, *iter).c_str ());
 
591
    }
 
592
 
 
593
    xmlBufferPtr buffer = xmlBufferCreate ();
 
594
    int res = xmlNodeDump (buffer, doc, entry_node, 0, 0);
 
595
 
 
596
    if (res >= 0) {
 
597
 
 
598
      std::string root_str;
 
599
      std::string username_str;
 
600
      std::string password_str;
 
601
      std::string user_str;
 
602
 
 
603
      {
 
604
        xmlChar* str = xmlNodeGetContent (root);
 
605
        if (str != NULL)
 
606
          root_str = (const char*)str;
 
607
      }
 
608
      {
 
609
        xmlChar* str = xmlNodeGetContent (user);
 
610
        if (str != NULL)
 
611
          user_str = (const char*)str;
 
612
      }
 
613
      {
 
614
        xmlChar* str = xmlNodeGetContent (username);
 
615
        if (str != NULL)
 
616
          username_str = (const char*)str;
 
617
      }
 
618
      {
 
619
        xmlChar* str = xmlNodeGetContent (password);
 
620
        if (str != NULL)
 
621
          password_str = (const char*)str;
 
622
      }
 
623
      gmref_ptr<XCAP::Path> path(new XCAP::Path (root_str, "resource-lists",
 
624
                                                 user_str));
 
625
      path->set_credentials (username_str, password_str);
 
626
      path = path->build_child ("resource-lists");
 
627
      path = path->build_child ("list");
 
628
      path = path->build_child_with_attribute ("entry", "uri", entry_uri);
 
629
      gmref_ptr<XCAP::Core> xcap(services.get ("xcap-core"));
 
630
      xcap->write (path, "application/xcap-el+xml",
 
631
                   (const char*)xmlBufferContent (buffer),
 
632
                   sigc::mem_fun (this,
 
633
                                  &RL::Heap::new_entry_result));
 
634
    }
 
635
    xmlBufferFree (buffer);
 
636
  } catch (Ekiga::Form::not_found exc) {
 
637
 
 
638
    std::cerr << "Invalid result form" << std::endl; // FIXME: do better
 
639
  }
 
640
}
 
641
 
 
642
void
 
643
RL::Heap::new_entry_result (std::string error)
 
644
{
 
645
  if ( !error.empty ()) {
 
646
 
 
647
    std::cout << "XCAP Error: " << error << std::endl;
 
648
  }
 
649
 
 
650
  refresh ();
 
651
}