2
/* Ekiga -- A VoIP and Video-Conferencing application
3
* Copyright (C) 2000-2009 Damien Sandras <dsandras@seconix.com>
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.
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.
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.
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.
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
38
#include <glib/gi18n.h>
40
#include "robust-xml.h"
41
#include "form-request-simple.h"
42
#include "xcap-core.h"
46
RL::Heap::Heap (Ekiga::ServiceCore& services_,
47
boost::shared_ptr<xmlDoc> doc_,
50
node(node_), name(NULL),
51
root(NULL), user(NULL),
52
username(NULL), password(NULL),
53
doc(doc_), list_node(NULL)
56
xmlChar* xml_str = NULL;
58
xml_str = xmlGetProp (node, BAD_CAST "writable");
62
xmlSetProp (node, BAD_CAST "writable", BAD_CAST "0");
66
for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
68
if (child->type == XML_ELEMENT_NODE
69
&& child->name != NULL) {
71
if (xmlStrEqual (BAD_CAST ("name"), child->name)) {
76
if (xmlStrEqual (BAD_CAST ("root"), child->name)) {
81
if (xmlStrEqual (BAD_CAST ("user"), child->name)) {
86
if (xmlStrEqual (BAD_CAST ("username"), child->name)) {
91
if (xmlStrEqual (BAD_CAST ("password"), child->name)) {
100
name = xmlNewChild (node, NULL, BAD_CAST "name",
101
BAD_CAST robust_xmlEscape(doc.get (),
102
_("Unnamed")).c_str ());
104
root = xmlNewChild (node, NULL, BAD_CAST "root", BAD_CAST "");
106
user = xmlNewChild (node, NULL, BAD_CAST "user", BAD_CAST "");
107
if (username == NULL)
108
username = xmlNewChild (node, NULL, BAD_CAST "username", BAD_CAST "");
109
if (password == NULL)
110
password = xmlNewChild (node, NULL, BAD_CAST "password", BAD_CAST "");
115
RL::Heap::Heap (Ekiga::ServiceCore& services_,
116
boost::shared_ptr<xmlDoc> doc_,
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_,
124
node(NULL), name(NULL),
125
root(NULL), user(NULL),
126
username(NULL), password(NULL),
127
doc(doc_), list_node(NULL)
129
node = xmlNewNode (NULL, BAD_CAST "entry");
131
xmlSetProp (node, BAD_CAST "writable", BAD_CAST "1");
133
xmlSetProp (node, BAD_CAST "writable", BAD_CAST "0");
135
if ( !name_.empty ())
136
name = xmlNewChild (node, NULL,
138
BAD_CAST robust_xmlEscape (node->doc,
141
name = xmlNewChild (node, NULL,
143
BAD_CAST robust_xmlEscape (node->doc,
144
_("Unnamed")).c_str ());
145
root = xmlNewChild (node, NULL,
147
BAD_CAST robust_xmlEscape (node->doc,
149
user = xmlNewChild (node, NULL,
151
BAD_CAST robust_xmlEscape (node->doc,
153
username = xmlNewChild (node, NULL,
155
BAD_CAST robust_xmlEscape (node->doc,
156
username_).c_str ());
157
password = xmlNewChild (node, NULL,
159
BAD_CAST robust_xmlEscape (node->doc,
160
password_).c_str ());
169
RL::Heap::get_name () const
172
xmlChar* str = xmlNodeGetContent (name);
174
result = (const char*)str;
176
result = _("Unnamed");
184
RL::Heap::visit_presentities (boost::function1<bool, Ekiga::PresentityPtr > visitor) const
188
for (std::map<PresentityPtr,std::list<boost::signals::connection> >::const_iterator
189
iter = presentities.begin ();
190
go_on && iter != presentities.end ();
192
go_on = visitor (iter->first);
196
RL::Heap::populate_menu (Ekiga::MenuBuilder& builder)
198
builder.add_action ("add", _("_Add a new contact"),
199
boost::bind (&RL::Heap::new_entry, this));
200
builder.add_action ("refresh", _("_Refresh contact list"),
201
boost::bind (&RL::Heap::refresh, this));
202
builder.add_action ("properties", _("Contact list _properties"),
203
boost::bind (&RL::Heap::edit, this));
208
RL::Heap::populate_menu_for_group (std::string /*group*/,
209
Ekiga::MenuBuilder& /*builder*/)
211
return false; // FIXME
215
RL::Heap::get_node () const
223
boost::shared_ptr<XCAP::Core> xcap = services.get<XCAP::Core> ("xcap-core");
224
std::string root_str;
225
std::string username_str;
226
std::string password_str;
227
std::string user_str;
230
xmlChar* str = xmlNodeGetContent (root);
232
root_str = (const char*)str;
235
xmlChar* str = xmlNodeGetContent (user);
237
user_str = (const char*)str;
240
xmlChar* str = xmlNodeGetContent (username);
242
username_str = (const char*)str;
245
xmlChar* str = xmlNodeGetContent (password);
247
password_str = (const char*)str;
249
boost::shared_ptr<XCAP::Path> path(new XCAP::Path (root_str, "resource-lists",
251
path->set_credentials (username_str, password_str);
252
path = path->build_child ("resource-lists");
254
while ( !presentities.empty ()) {
256
presentities.begin()->first->removed ();
257
for (std::list<boost::signals::connection>::const_iterator iter2
258
= presentities.begin()->second.begin ();
259
iter2 != presentities.begin()->second.end ();
261
iter2->disconnect ();
262
presentities.erase (presentities.begin()->first);
267
xcap->read (path, boost::bind (&RL::Heap::on_document_received, this, _1, _2));
271
RL::Heap::on_document_received (bool error,
276
// FIXME: do something
277
std::cout << "XCAP error: " << value << std::endl;
285
RL::Heap::parse_doc (std::string raw)
287
doc = boost::shared_ptr<xmlDoc> (xmlRecoverMemory (raw.c_str (), raw.length ()), xmlFreeDoc);
289
doc = boost::shared_ptr<xmlDoc> (xmlNewDoc (BAD_CAST "1.0"), xmlFreeDoc);
290
xmlNodePtr doc_root = xmlDocGetRootElement (doc.get ());
293
|| doc_root->name == NULL
294
|| !xmlStrEqual (BAD_CAST "resource-lists", doc_root->name)) {
296
std::cout << "Invalid document in " << __PRETTY_FUNCTION__ << std::endl;
297
// FIXME: warn the user somehow?
302
for (xmlNodePtr child = doc_root->children;
305
if (child->type == XML_ELEMENT_NODE
306
&& child->name != NULL
307
&& xmlStrEqual (BAD_CAST ("list"), child->name)) {
310
break; // read only one!
316
RL::Heap::parse_list (xmlNodePtr list)
318
std::string root_str;
319
std::string user_str;
320
std::string username_str;
321
std::string password_str;
322
bool writable = false;
326
xmlChar* str = xmlNodeGetContent (root);
328
root_str = (const char*)str;
331
xmlChar* str = xmlNodeGetContent (user);
333
user_str = (const char*)str;
336
xmlChar* str = xmlNodeGetContent (username);
338
username_str = (const char*)str;
341
xmlChar* str = xmlNodeGetContent (password);
343
password_str = (const char*)str;
346
xmlChar* str = xmlGetProp (node, BAD_CAST "writable");
349
if (xmlStrEqual (str, BAD_CAST "1"))
355
boost::shared_ptr<XCAP::Path> path(new XCAP::Path (root_str, "resource-lists",
357
path->set_credentials (username_str, password_str);
358
path = path->build_child ("resource-lists");
359
path = path->build_child ("list");
361
for (xmlNodePtr child = list->children;
364
if (child->type == XML_ELEMENT_NODE
365
&& child->name != NULL
366
&& xmlStrEqual (BAD_CAST ("entry"), child->name)) {
368
PresentityPtr presentity(new Presentity (services, path, doc, child, writable));
369
std::list<boost::signals::connection> conns;
370
conns.push_back (presentity->updated.connect (boost::bind (boost::ref (presentity_updated), presentity)));
371
conns.push_back (presentity->removed.connect (boost::bind(boost::ref (presentity_removed),presentity)));
372
conns.push_back (presentity->trigger_reload.connect (boost::bind (&RL::Heap::refresh, this)));
373
conns.push_back (presentity->questions.connect (boost::ref (questions)));
374
presentities[presentity]=conns;
375
presentity_added (presentity);
381
RL::Heap::push_presence (const std::string uri_,
382
const std::string presence)
384
for (std::map<PresentityPtr,std::list<boost::signals::connection> >::const_iterator
385
iter = presentities.begin ();
386
iter != presentities.end ();
389
if (iter->first->get_uri () == uri_)
390
iter->first->set_presence (presence);
395
RL::Heap::push_status (const std::string uri_,
396
const std::string status)
398
for (std::map<PresentityPtr,std::list<boost::signals::connection> >::const_iterator
399
iter = presentities.begin ();
400
iter != presentities.end ();
403
if (iter->first->get_uri () == uri_)
404
iter->first->set_status (status);
411
boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind (&RL::Heap::on_edit_form_submitted, this, _1, _2)));
413
std::string name_str;
414
std::string root_str;
415
std::string username_str;
416
std::string password_str;
417
std::string user_str;
418
bool writable = false;
421
xmlChar* str = xmlNodeGetContent (root);
424
root_str = (const char*)str;
429
xmlChar* str = xmlNodeGetContent (user);
432
user_str = (const char*)str;
437
xmlChar* str = xmlNodeGetContent (username);
440
username_str = (const char*)str;
445
xmlChar* str = xmlNodeGetContent (password);
448
password_str = (const char*)str;
453
xmlChar* str = xmlGetProp (node, BAD_CAST "writable");
456
if (xmlStrEqual (str, BAD_CAST "1"))
462
request->title (_("Edit contact list properties"));
464
request->instructions (_("Please edit the following fields (no identifier"
467
request->text ("name", _("Contact list's name:"), get_name (), std::string ());
468
/* "Document" used as a name -- uri point to the root of a document tree */
469
request->text ("root", _("Document root:"), root_str, std::string ());
470
request->text ("user", _("Identifier:"), user_str, std::string ());
471
request->boolean ("writable", _("Writable:"), writable);
472
request->text ("username", _("Server username:"), username_str, std::string ());
473
request->private_text ("password", _("Server password:"), password_str, std::string ());
479
RL::Heap::on_edit_form_submitted (bool submitted,
485
std::string name_str = result.text ("name");
486
std::string root_str = result.text ("root");
487
std::string user_str = result.text ("user");
488
std::string username_str = result.text ("username");
489
std::string password_str = result.private_text ("password");
490
bool writable = result.boolean ("writable");
493
xmlSetProp (node, BAD_CAST "writable", BAD_CAST "1");
495
xmlSetProp (node, BAD_CAST "writable", BAD_CAST "0");
496
robust_xmlNodeSetContent (node, &name, "name", name_str);
497
robust_xmlNodeSetContent (node, &root, "root", root_str);
498
robust_xmlNodeSetContent (node, &user, "user", user_str);
499
robust_xmlNodeSetContent (node, &username, "username", username_str);
500
robust_xmlNodeSetContent (node, &password, "password", password_str);
508
RL::Heap::new_entry ()
510
boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind (&RL::Heap::on_new_entry_form_submitted, this, _1, _2)));
512
request->title (_("Add a remote contact"));
513
request->instructions (_("Please fill in this form to create a new "
514
"contact on a remote server"));
516
std::set<std::string> all_groups;
517
for (std::map<PresentityPtr,std::list<boost::signals::connection> >::const_iterator
518
iter = presentities.begin ();
519
iter != presentities.end ();
522
std::set<std::string> groups = iter->first->get_groups ();
523
all_groups.insert (groups.begin (), groups.end ());
526
request->text ("name", _("Name:"), "", std::string ());
527
request->text ("uri", _("Address:"), "", std::string ());
528
request->editable_set ("groups", _("Choose groups:"),
529
std::set<std::string>(), all_groups);
535
RL::Heap::on_new_entry_form_submitted (bool submitted,
541
std::string entry_name = result.text ("name");
542
std::string entry_uri = result.text ("uri");
543
std::set<std::string> entry_groups = result.editable_set ("groups");
545
xmlNodePtr entry_node = xmlNewChild (list_node, NULL,
546
BAD_CAST "entry", NULL);
547
xmlSetProp (entry_node, BAD_CAST "uri",
548
BAD_CAST robust_xmlEscape (doc.get (), entry_uri).c_str ());
549
xmlNewChild (entry_node, NULL, BAD_CAST "display-name",
550
BAD_CAST robust_xmlEscape (doc.get (), entry_name).c_str ());
551
xmlNsPtr ns = xmlSearchNsByHref (doc.get (), entry_node,
552
BAD_CAST "http://www.ekiga.org");
555
// FIXME: we should handle the case, even if it shouldn't happen
558
for (std::set<std::string>::const_iterator iter = entry_groups.begin ();
559
iter != entry_groups.end ();
562
xmlNewChild (entry_node, ns, BAD_CAST "group",
563
BAD_CAST robust_xmlEscape (doc.get (), *iter).c_str ());
566
xmlBufferPtr buffer = xmlBufferCreate ();
567
int res = xmlNodeDump (buffer, doc.get (), entry_node, 0, 0);
571
std::string root_str;
572
std::string username_str;
573
std::string password_str;
574
std::string user_str;
577
xmlChar* str = xmlNodeGetContent (root);
579
root_str = (const char*)str;
582
xmlChar* str = xmlNodeGetContent (user);
584
user_str = (const char*)str;
587
xmlChar* str = xmlNodeGetContent (username);
589
username_str = (const char*)str;
592
xmlChar* str = xmlNodeGetContent (password);
594
password_str = (const char*)str;
596
boost::shared_ptr<XCAP::Path> path(new XCAP::Path (root_str, "resource-lists",
598
path->set_credentials (username_str, password_str);
599
path = path->build_child ("resource-lists");
600
path = path->build_child ("list");
601
path = path->build_child_with_attribute ("entry", "uri", entry_uri);
602
boost::shared_ptr<XCAP::Core> xcap = services.get<XCAP::Core> ("xcap-core");
603
xcap->write (path, "application/xcap-el+xml",
604
(const char*)xmlBufferContent (buffer),
605
boost::bind (&RL::Heap::new_entry_result, this, _1));
607
xmlBufferFree (buffer);
611
RL::Heap::new_entry_result (std::string error)
613
if ( !error.empty ()) {
615
std::cout << "XCAP Error: " << error << std::endl;