3
* Ekiga -- A VoIP and Video-Conferencing application
4
* Copyright (C) 2000-2009 Damien Sandras <dsandras@seconix.com>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or (at
9
* your option) any later version. This program is distributed in the hope
10
* that it will be useful, but WITHOUT ANY WARRANTY; without even the
11
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
* See the GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License along
15
* with this program; if not, write to the Free Software Foundation, Inc.,
16
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18
* Ekiga is licensed under the GPL license and as a special exception, you
19
* have permission to link or otherwise combine this program with the
20
* programs OPAL, OpenH323 and PWLIB, and distribute the combination, without
21
* applying the requirements of the GNU GPL to the OPAL, OpenH323 and PWLIB
22
* programs, as long as you do follow the requirements of the GNU GPL for all
23
* the rest of the software thus combined.
28
* rl-presentity.cpp - description
29
* ------------------------------------------
30
* begin : written in 2008 by Julien Puydt
31
* copyright : (c) 2008 by Julien Puydt
32
* description : implementation of a presentity in a resource-list
39
#include <glib/gi18n.h>
41
#include "form-request-simple.h"
42
#include "robust-xml.h"
43
#include "xcap-core.h"
45
#include "rl-presentity.h"
47
/* at one point we will return a smart pointer on this... and if we don't use
48
* a false smart pointer, we will crash : the reference count isn't embedded!
52
void operator()(void const *) const
58
RL::Presentity::Presentity (Ekiga::ServiceCore &services_,
59
boost::shared_ptr<XCAP::Path> path_,
60
boost::shared_ptr<xmlDoc> doc_,
63
services(services_), doc(doc_), node(node_), writable(writable_),
64
name_node(NULL), presence("unknown"), status("")
66
boost::shared_ptr<Ekiga::PresenceCore> presence_core(services.get<Ekiga::PresenceCore> ("presence-core"));
67
xmlChar *xml_str = NULL;
68
xmlNsPtr ns = xmlSearchNsByHref (doc.get (), node,
69
BAD_CAST "http://www.ekiga.org");
73
// FIXME: we should handle the case, even if it shouldn't happen
76
xml_str = xmlGetProp (node, BAD_CAST "uri");
77
if (xml_str != NULL) {
79
uri = (const char *)xml_str;
80
path = path_->build_child_with_attribute ("entry", "uri", uri);
84
// FIXME: we should handle the case, even if it shouldn't happen
88
for (xmlNodePtr child = node->children ;
90
child = child->next) {
92
if (child->type == XML_ELEMENT_NODE
93
&& child->name != NULL) {
95
if (xmlStrEqual (BAD_CAST ("display-name"), child->name)) {
100
else if (xmlStrEqual (BAD_CAST ("group"), child->name)
101
&& child->ns == ns) {
103
xml_str = xmlNodeGetContent (child);
105
group_nodes[(const char *)xml_str] = child;
107
group_nodes[""] = child;
114
for (std::map<std::string, xmlNodePtr>::const_iterator iter
115
= group_nodes.begin ();
116
iter != group_nodes.end ();
118
groups.insert (iter->first);
120
presence_core->fetch_presence (uri);
123
RL::Presentity::~Presentity ()
129
RL::Presentity::get_name () const
133
if (name_node != NULL) {
135
xmlChar* str = xmlNodeGetContent (name_node);
138
result = ((const char*)str);
143
result = _("Unnamed");
151
RL::Presentity::get_presence () const
158
RL::Presentity::get_status () const
164
const std::set<std::string>
165
RL::Presentity::get_groups () const
172
RL::Presentity::get_uri () const
179
RL::Presentity::set_presence (const std::string _presence)
181
presence = _presence;
186
RL::Presentity::set_status (const std::string _status)
194
RL::Presentity::has_uri (const std::string uri) const
196
return uri == get_uri ();
200
RL::Presentity::populate_menu (Ekiga::MenuBuilder &builder)
202
bool populated = false;
203
boost::shared_ptr<Ekiga::PresenceCore> presence_core(services.get<Ekiga::PresenceCore> ("presence-core"));
205
populated = presence_core->populate_presentity_menu (PresentityPtr (this, null_deleter ()), uri, builder);
210
builder.add_separator ();
212
builder.add_action ("edit", _("_Edit"),
213
boost::bind (&RL::Presentity::edit_presentity, this));
214
builder.add_action ("remove", _("_Remove"),
215
boost::bind (&RL::Presentity::remove, this));
223
RL::Presentity::edit_presentity ()
225
boost::shared_ptr<Ekiga::FormRequestSimple> request = boost::shared_ptr<Ekiga::FormRequestSimple> (new Ekiga::FormRequestSimple (boost::bind (&RL::Presentity::edit_presentity_form_submitted, this, _1, _2)));
227
// FIXME: we should be able to know all groups in the heap
228
std::set<std::string> all_groups = groups;
230
request->title (_("Edit remote contact"));
231
request->instructions (_("Please fill in this form to change an existing "
232
"contact on a remote server"));
233
request->text ("name", _("Name:"), get_name (), std::string ());
234
request->text ("uri", _("Address:"), uri, std::string ());
236
request->editable_set ("groups", _("Choose groups:"),
244
RL::Presentity::edit_presentity_form_submitted (bool submitted,
250
const std::string new_name = result.text ("name");
251
const std::string new_uri = result.text ("uri");
252
const std::set<std::string> new_groups = result.editable_set ("groups");
253
std::map<std::string, xmlNodePtr> future_group_nodes;
254
xmlNsPtr ns = xmlSearchNsByHref (node->doc, node,
255
BAD_CAST "http://www.ekiga.org");
258
robust_xmlNodeSetContent (node, &name_node, "name", new_name);
260
if (uri != new_uri) {
262
xmlSetProp (node, (const xmlChar*)"uri", (const xmlChar*)uri.c_str ());
263
boost::shared_ptr<Ekiga::PresenceCore> presence_core(services.get<Ekiga::PresenceCore> ("presence-core"));
264
presence_core->unfetch_presence (uri);
268
for (std::map<std::string, xmlNodePtr>::const_iterator iter
269
= group_nodes.begin ();
270
iter != group_nodes.end () ;
273
if (new_groups.find (iter->first) == new_groups.end ()) {
275
xmlUnlinkNode (iter->second);
276
xmlFreeNode (iter->second);
279
future_group_nodes[iter->first] = iter->second;
283
for (std::set<std::string>::const_iterator iter = new_groups.begin ();
284
iter != new_groups.end ();
287
if (std::find (groups.begin (), groups.end (), *iter) == groups.end ())
288
future_group_nodes[*iter] = xmlNewChild (node, ns,
290
BAD_CAST robust_xmlEscape (node->doc, *iter).c_str ());
293
group_nodes = future_group_nodes;
300
RL::Presentity::save (bool reload)
302
xmlBufferPtr buffer = xmlBufferCreate ();
303
int result = xmlNodeDump (buffer, node->doc, node, 0, 0);
307
boost::shared_ptr<XCAP::Core> xcap = services.get<XCAP::Core> ("xcap-core");
308
xcap->write (path, "application/xcap-el+xml",
309
(const char*)xmlBufferContent (buffer),
310
boost::bind (&RL::Presentity::save_result, this, _1, reload));
313
xmlBufferFree (buffer);
318
RL::Presentity::remove ()
320
xmlUnlinkNode (node);
322
boost::shared_ptr<Ekiga::PresenceCore> presence_core = services.get<Ekiga::PresenceCore> ("presence-core");
324
presence_core->unfetch_presence (uri);
326
boost::shared_ptr<XCAP::Core> xcap = services.get<XCAP::Core> ("xcap-core");
328
boost::bind (&RL::Presentity::erase_result, this, _1));
332
RL::Presentity::save_result (std::string error,
335
if ( !error.empty ()) {
338
std::cout << "XCAP error: " << error << std::endl;
350
RL::Presentity::erase_result (std::string error)
352
if ( !error.empty ()) {
355
std::cout << "XCAP error: " << error << std::endl;