Browse code

- added a xcap client for OpenSER module (it retrieves info from XCAP servers using HTTP GET request; works with libcurl library)

git-svn-id: https://openser.svn.sourceforge.net/svnroot/openser/trunk@2627 689a6050-402a-0410-94f2-e92a70836424

Anca Vamanu authored on 22/08/2007 13:27:42
Showing 12 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,18 @@
1
+# $Id: Makefile $
2
+#
3
+# XCAP client for OpenSer
4
+#
5
+# 
6
+# WARNING: do not run this directly, it should be run by the master Makefile
7
+
8
+include ../../Makefile.defs
9
+auto_gen=
10
+NAME=xcap_client.so
11
+LIBS=
12
+
13
+DEFS+=-I$(SYSBASE)/include/libxml2 -I$(LOCALBASE)/include/libxml2 \
14
+      -I$(LOCALBASE)/include
15
+
16
+LIBS+=-L$(SYSBASE)/include/lib  -L$(LOCALBASE)/lib   -lcurl -lxml2 
17
+
18
+include ../../Makefile.modules
0 19
new file mode 100644
... ...
@@ -0,0 +1,221 @@
1
+
2
+Presence_XML Module
3
+
4
+Anca-Maria Vamanu
5
+
6
+   voice-system.ro
7
+
8
+Edited by
9
+
10
+Anca-Maria Vamanu
11
+
12
+   Copyright � 2007 voice-system.ro
13
+     _________________________________________________________
14
+
15
+   Table of Contents
16
+   1. User's Guide
17
+
18
+        1.1. Overview
19
+        1.2. Dependencies
20
+
21
+              1.2.1. OpenSER Modules
22
+              1.2.2. External Libraries or Applications
23
+
24
+        1.3. Exported Functions
25
+
26
+   2. Developer's Guide
27
+
28
+        2.1. bind_xcap_api(xcap_api_t* api)
29
+        2.2. get_elem
30
+        2.3. register_xcb
31
+
32
+   3. Frequently Asked Questions
33
+
34
+   List of Examples
35
+   2-1. xcap_api structure
36
+     _________________________________________________________
37
+
38
+Chapter 1. User's Guide
39
+
40
+1.1. Overview
41
+
42
+   The modules is an XCAP client for OpenSER that can be used by
43
+   other modules. It fetches XCAP elements, either documents or
44
+   part of them, by sending HTTP GET requests. It uses libcurl
45
+   library as a HTTP client.
46
+
47
+   The XCAP servers the module works with have to be able to send
48
+   a MI command, 'refreshXcapDoc [doc_url]' when a document is
49
+   updated.
50
+
51
+   The module is currently used by the presence_xml module, if
52
+   the 'integrated_xcap_server' parameter is not set.
53
+     _________________________________________________________
54
+
55
+1.2. Dependencies
56
+
57
+1.2.1. OpenSER Modules
58
+
59
+   The modules is not dependent of any OpenSER module.
60
+     _________________________________________________________
61
+
62
+1.2.2. External Libraries or Applications
63
+
64
+   The following libraries or applications must be installed
65
+   before running OpenSER with this module loaded:
66
+
67
+     * libxml.
68
+     * libcurl.
69
+     _________________________________________________________
70
+
71
+1.3. Exported Functions
72
+
73
+   None to be used in configuration file.
74
+     _________________________________________________________
75
+
76
+Chapter 2. Developer's Guide
77
+
78
+   The module exports a number of functions that allow selecting
79
+   and retrieving an element from an xcap server and also
80
+   registering a callback to be called when a MI command
81
+   refreshXcapDoc is received and the document in question is
82
+   retrieved.
83
+     _________________________________________________________
84
+
85
+2.1. bind_xcap_api(xcap_api_t* api)
86
+
87
+   This function allows binding the needed functions.
88
+
89
+   Example 2-1. xcap_api structure
90
+...
91
+typedef struct xcap_api {
92
+
93
+        /* xcap node selection and retrieving functions*/
94
+        xcap_get_elem_t get_elem;
95
+        xcap_nodeSel_init_t int_node_sel;
96
+        xcap_nodeSel_add_step_t add_step;
97
+        xcap_nodeSel_add_terminal_t add_terminal;
98
+        xcap_nodeSel_free_t free_node_sel;
99
+
100
+        /* function to register a callback to document changes*/
101
+        register_xcapcb_t register_xcb;
102
+}xcap_api_t;
103
+...
104
+     _________________________________________________________
105
+
106
+2.2. get_elem
107
+
108
+   Field type:
109
+...
110
+typedef char* (*xcap_get_elem_t)(char* xcap_root,
111
+xcap_doc_sel_t* doc_sel, xcap_node_sel_t* node_sel);
112
+...
113
+
114
+   This function sends a HTTP request and gets the specified
115
+   information from the xcap server.
116
+
117
+   The parameters signification:
118
+
119
+     * xcap_root- the XCAP server address;
120
+     * doc_sel- structure with document selection info;
121
+Parameter type:
122
+...
123
+typedef struct xcap_doc_sel
124
+{
125
+        str auid; /* application defined Unique ID*/
126
+        int type; /* the type of the path segment
127
+                                after the AUID  which must either
128
+                                be GLOBAL_TYPE (for "global") or
129
+                                USERS_TYPE (for "users") */
130
+        str xid; /* the XCAP User Identifier
131
+                                if type is USERS_TYPE */
132
+        str filename;
133
+}xcap_doc_sel_t;
134
+...
135
+     * node_sel- structure with node selection info;
136
+Parameter type:
137
+...
138
+typedef struct xcap_node_sel
139
+{
140
+        step_t* steps;
141
+        step_t* last_step;
142
+        int size;
143
+        ns_list_t* ns_list;
144
+        ns_list_t* last_ns;
145
+        int ns_no;
146
+
147
+}xcap_node_sel_t;
148
+
149
+typedef struct step
150
+{
151
+        str val;
152
+        struct step* next;
153
+}step_t;
154
+
155
+typedef struct ns_list
156
+{
157
+        int name;
158
+        str value;
159
+        struct ns_list* next;
160
+}ns_list_t;
161
+...
162
+       The node selector is represented like a list of steps that
163
+       will be represented in the path string separated by '/'
164
+       signs. The namespaces for the nodes are stored also in a
165
+       list, as an association of name and value, where the value
166
+       is to be included in the respective string val field of
167
+       the step.
168
+       To construct the node structure the following functions in
169
+       the xcap_api structure should be used: 'int_node_sel',
170
+       'add_step' and if needed, 'add_terminal'.
171
+       If the intention is to retrieve the whole document this
172
+       argument must be NULL.
173
+     _________________________________________________________
174
+
175
+2.3. register_xcb
176
+
177
+   Field type:
178
+...
179
+typedef int (*register_xcapcb_t)(int types, xcap_cb f);
180
+...
181
+
182
+   - 'types' parameter can have a combined value of PRES_RULES,
183
+   RESOURCE_LIST, RLS_SERVICES and PIDF_MANIPULATION.
184
+
185
+   -the callback function has type :
186
+...
187
+typedef int (xcap_cb)(int doc_type, str xid, char* doc);
188
+...
189
+     _________________________________________________________
190
+
191
+Chapter 3. Frequently Asked Questions
192
+
193
+   3.1. Where can I find more about OpenSER?
194
+   3.2. Where can I post a question about this module?
195
+   3.3. How can I report a bug?
196
+
197
+   3.1. Where can I find more about OpenSER?
198
+
199
+   Take a look at http://openser.org/.
200
+
201
+   3.2. Where can I post a question about this module?
202
+
203
+   First at all check if your question was already answered on
204
+   one of our mailing lists:
205
+
206
+     * User Mailing List -
207
+       http://openser.org/cgi-bin/mailman/listinfo/users
208
+     * Developer Mailing List -
209
+       http://openser.org/cgi-bin/mailman/listinfo/devel
210
+
211
+   E-mails regarding any stable OpenSER release should be sent to
212
+   <users@openser.org> and e-mails regarding development versions
213
+   should be sent to <devel@openser.org>.
214
+
215
+   If you want to keep the mail private, send it to
216
+   <team@openser.org>.
217
+
218
+   3.3. How can I report a bug?
219
+
220
+   Please follow the guidelines provided at:
221
+   http://sourceforge.net/tracker/?group_id=139143.
0 222
new file mode 100644
... ...
@@ -0,0 +1,57 @@
1
+<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [
2
+
3
+
4
+<!ENTITY user SYSTEM "xcap_client_user.sgml">
5
+<!ENTITY devel SYSTEM "xcap_client_devel.sgml">
6
+<!ENTITY faq SYSTEM "xcap_client_faq.sgml">
7
+
8
+<!-- Include general documentation entities -->
9
+<!ENTITY % docentities SYSTEM "../../../doc/entities.sgml">
10
+%docentities;
11
+
12
+]>
13
+
14
+<book>
15
+    <bookinfo>
16
+	<title>Presence_XML Module</title>
17
+	<productname class="trade">&sername;</productname>
18
+	<authorgroup>
19
+	    <author>
20
+		<firstname>Anca-Maria</firstname>
21
+		<surname>Vamanu</surname>
22
+		<affiliation><orgname>&voicesystem;</orgname></affiliation>
23
+		<address>
24
+		<email>anca@voice-system.ro</email>
25
+		<otheraddr>
26
+		<ulink url="http://www.voice-system.ro">http://www.voice-system.ro</ulink>
27
+		</otheraddr>
28
+		</address>
29
+	    </author>
30
+	    <editor>
31
+		<firstname>Anca-Maria</firstname>
32
+		<surname>Vamanu</surname>
33
+		<address>
34
+		    <email>anca@voice-system.ro</email>
35
+		</address>
36
+	    </editor>
37
+	</authorgroup>
38
+	<copyright>
39
+	    <year>2007</year>
40
+	    <holder>&voicesystem;</holder>
41
+	</copyright>
42
+	<revhistory>
43
+	    <revision>
44
+		<revnumber>$Revision: 1499 $</revnumber>
45
+		<date>$Date: 2007-01-12 14:05:57 +0200 (Fri, 12 Jan 2007) $</date>
46
+	    </revision>
47
+	</revhistory>
48
+  </bookinfo>
49
+    <toc></toc>
50
+    
51
+    &user;
52
+    &devel;
53
+    &faq;
54
+    
55
+</book>
56
+
57
+
0 58
new file mode 100644
... ...
@@ -0,0 +1,181 @@
1
+<!-- Module Developer's Guide -->
2
+
3
+<chapter>
4
+    <chapterinfo>
5
+	<revhistory>
6
+	    <revision>
7
+		<revnumber>$Revision: 1168 $</revnumber>
8
+		<date>$Date: 2006-10-13 15:21:23 +0300 (Fri, 13 Oct 2006) $</date>
9
+	    </revision>
10
+	</revhistory>
11
+    </chapterinfo>
12
+    <title>Developer's Guide</title>
13
+	<para>
14
+		The module exports a number of functions that allow selecting 
15
+		and retrieving an element from an xcap server and also registering
16
+		a callback to be called when a MI command refreshXcapDoc is received
17
+		and the document in question is retrieved.
18
+   </para>
19
+   <section>
20
+      <title>
21
+	     <function moreinfo="none">bind_xcap_api(xcap_api_t* api)</function>
22
+     </title>
23
+		<para>
24
+		This function allows binding the needed functions. 
25
+		</para>
26
+			<example>
27
+			<title><function>xcap_api</function> structure</title>
28
+			<programlisting format="linespecific">
29
+...
30
+typedef struct xcap_api {
31
+	
32
+	/* xcap node selection and retrieving functions*/
33
+	xcap_get_elem_t get_elem;
34
+	xcap_nodeSel_init_t int_node_sel;
35
+	xcap_nodeSel_add_step_t add_step;
36
+	xcap_nodeSel_add_terminal_t add_terminal;
37
+	xcap_nodeSel_free_t free_node_sel;
38
+
39
+	/* function to register a callback to document changes*/
40
+	register_xcapcb_t register_xcb;
41
+}xcap_api_t;
42
+...
43
+			</programlisting>
44
+			</example>
45
+	</section>
46
+	
47
+	<section>
48
+		<title>
49
+			<function moreinfo="none">get_elem</function>
50
+		</title>
51
+		<para>
52
+			Field type:
53
+				<programlisting format="linespecific">
54
+...
55
+typedef char* (*xcap_get_elem_t)(char* xcap_root,
56
+xcap_doc_sel_t* doc_sel, xcap_node_sel_t* node_sel);
57
+...
58
+				</programlisting>
59
+		</para>		
60
+		<para>
61
+			This function sends a HTTP request and gets the specified information
62
+			from the xcap server.
63
+		</para>
64
+		<para>
65
+		The parameters signification:
66
+			<itemizedlist>
67
+			<listitem>
68
+			<para>
69
+				<emphasis>xcap_root</emphasis>-
70
+				the XCAP server address;
71
+			</para>
72
+			</listitem>
73
+			<listitem>
74
+			<para>
75
+				<emphasis>doc_sel</emphasis>-
76
+				structure with document selection info;
77
+			<programlisting format="linespecific">
78
+Parameter type:
79
+...
80
+typedef struct xcap_doc_sel
81
+{
82
+	str auid; /* application defined Unique ID*/
83
+	int type; /* the type of the path segment
84
+				after the AUID  which must either
85
+				be GLOBAL_TYPE (for "global") or
86
+				USERS_TYPE (for "users") */ 
87
+	str xid; /* the XCAP User Identifier 
88
+				if type is USERS_TYPE */
89
+	str filename; 
90
+}xcap_doc_sel_t;
91
+...
92
+</programlisting>
93
+</para>
94
+</listitem>
95
+			
96
+<listitem>
97
+<para>
98
+<emphasis>node_sel</emphasis>-
99
+structure with node selection info;
100
+</para>
101
+<programlisting format="linespecific">
102
+Parameter type:
103
+...
104
+typedef struct xcap_node_sel
105
+{
106
+	step_t* steps;
107
+	step_t* last_step;
108
+	int size;
109
+	ns_list_t* ns_list;
110
+	ns_list_t* last_ns;
111
+	int ns_no;
112
+
113
+}xcap_node_sel_t;
114
+
115
+typedef struct step
116
+{
117
+	str val;
118
+	struct step* next;
119
+}step_t;
120
+
121
+typedef struct ns_list
122
+{
123
+	int name;
124
+	str value;
125
+	struct ns_list* next;
126
+}ns_list_t;
127
+...
128
+
129
+</programlisting>
130
+		<para>
131
+		The node selector is represented like a list of steps that will
132
+		be represented in the path string separated by '/' signs. 
133
+		The namespaces for the nodes are stored also in a list, as an
134
+		association of name and value, where the value is to be included
135
+		in the respective string val field of the step.
136
+		</para>
137
+		<para>
138
+		To construct the node structure the following functions in the xcap_api
139
+		structure should be used: 'int_node_sel', 'add_step' and if needed, 
140
+		'add_terminal'.
141
+		</para>
142
+		<para>
143
+		If the intention is to retrieve the whole document this argument must
144
+		be NULL.
145
+		</para>
146
+		</listitem>
147
+		</itemizedlist>	
148
+	
149
+		</section>
150
+<section>
151
+		<title>
152
+			<function moreinfo="none">register_xcb</function>
153
+		</title>
154
+		<para>
155
+			Field type:
156
+				<programlisting format="linespecific">
157
+...
158
+typedef int (*register_xcapcb_t)(int types, xcap_cb f);
159
+...
160
+	</programlisting>
161
+	</para>
162
+	<para>
163
+	- 'types' parameter can have a combined value of PRES_RULES, RESOURCE_LIST,
164
+	RLS_SERVICES and PIDF_MANIPULATION.
165
+	</para>
166
+	<para>
167
+	-the callback function has type :
168
+	<programlisting format="linespecific">
169
+...
170
+typedef int (xcap_cb)(int doc_type, str xid, char* doc);
171
+...
172
+	</programlisting>
173
+	</para>
174
+	</section>	
175
+	</chapter>
176
+
177
+<!-- Keep this element at the end of the file
178
+Local Variables:
179
+sgml-parent-document: ("xcap_client.sgml" "book" "chapter")
180
+End:
181
+-->
0 182
new file mode 100644
... ...
@@ -0,0 +1,70 @@
1
+<!-- Module FAQ -->
2
+
3
+<chapter>
4
+    <chapterinfo>
5
+	<revhistory>
6
+	    <revision>
7
+		<revnumber>$Revision: 1168 $</revnumber>
8
+		<date>$Date: 2006-10-13 15:21:23 +0300 (Fri, 13 Oct 2006) $</date>
9
+	    </revision>
10
+	</revhistory>
11
+    </chapterinfo>
12
+    <title>Frequently Asked Questions</title>
13
+    <qandaset defaultlabel="number">
14
+	<qandaentry>
15
+	    <question>
16
+		<para>Where can I find more about OpenSER?</para>
17
+	    </question>
18
+	    <answer>
19
+		<para>
20
+			Take a look at &serhomelink;.
21
+		</para>
22
+	    </answer>
23
+	</qandaentry>
24
+	<qandaentry>
25
+	    <question>
26
+		<para>Where can I post a question about this module?</para>
27
+	    </question>
28
+	    <answer>
29
+		<para>
30
+			First at all check if your question was already answered on one of
31
+			our mailing lists: 
32
+		</para>
33
+		<itemizedlist>
34
+		    <listitem>
35
+			<para>User Mailing List - &seruserslink;</para>
36
+		    </listitem>
37
+		    <listitem>
38
+			<para>Developer Mailing List - &serdevlink;</para>
39
+		    </listitem>
40
+		</itemizedlist>
41
+		<para>
42
+			E-mails regarding any stable &ser; release should be sent to 
43
+			&serusersmail; and e-mails regarding development versions
44
+			should be sent to &serdevmail;.
45
+		</para>
46
+		<para>
47
+			If you want to keep the mail private, send it to 
48
+			&serhelpmail;.
49
+		</para>
50
+	    </answer>
51
+	</qandaentry>
52
+	<qandaentry>
53
+	    <question>
54
+		<para>How can I report a bug?</para>
55
+	    </question>
56
+	    <answer>
57
+		<para>
58
+			Please follow the guidelines provided at:
59
+			&serbugslink;.
60
+		</para>
61
+	    </answer>
62
+	</qandaentry>
63
+    </qandaset>
64
+</chapter>
65
+
66
+<!-- Keep this element at the end of the file
67
+Local Variables:
68
+sgml-parent-document: ("presence_xml.sgml" "Book" "chapter")
69
+End:
70
+-->
0 71
new file mode 100644
... ...
@@ -0,0 +1,74 @@
1
+<!-- Module User's Guide -->
2
+
3
+<chapter>
4
+	<chapterinfo>
5
+	<revhistory>
6
+		<revision>
7
+		<revnumber>$Revision: 1953 $</revnumber>
8
+		<date>$Date: 2007-04-04 11:50:33 +0300 (Wed, 04 Apr 2007) $</date>
9
+		</revision>
10
+	</revhistory>
11
+	</chapterinfo>
12
+	<title>User's Guide</title>
13
+	
14
+	<section>
15
+	<title>Overview</title>
16
+	<para> 
17
+	The modules is an XCAP client for OpenSER that can be used by other modules.
18
+	It fetches XCAP elements, either documents or part of them, by sending 
19
+	HTTP GET requests. It uses libcurl library as a HTTP client.
20
+	</para>
21
+	<para>The XCAP servers the module works with have to be able to send
22
+	a MI command,  'refreshXcapDoc [doc_url]' when a document is updated.
23
+	</para>
24
+	<para>
25
+	The module is currently used by the presence_xml module, if the 
26
+	'integrated_xcap_server' parameter is not set.
27
+	</para>
28
+	</section>
29
+
30
+	<section>
31
+	<title>Dependencies</title>
32
+	<section>
33
+		<title>&ser; Modules</title>
34
+		<para>
35
+			The modules is not dependent of any &ser; module.
36
+		</para>
37
+	</section>
38
+
39
+	<section>
40
+		<title>External Libraries or Applications</title>
41
+		<para>
42
+		The following libraries or applications must be installed before running
43
+		&ser; with this module loaded:
44
+			<itemizedlist>
45
+			<listitem>
46
+			<para>
47
+				<emphasis>libxml</emphasis>.
48
+			</para>
49
+			</listitem>
50
+			<listitem>
51
+			<para>
52
+				<emphasis>libcurl</emphasis>.
53
+			</para>
54
+			</listitem>
55
+			</itemizedlist>
56
+		</para>
57
+	</section>
58
+	</section>
59
+	
60
+<section>
61
+	<title>Exported Functions</title>
62
+	<para>
63
+	None to be used in configuration file.
64
+	</para>
65
+</section>
66
+
67
+</chapter>
68
+
69
+<!-- Keep this element at the end of the file
70
+Local Variables:
71
+sgml-parent-document: ("xcap_client.sgml" "Book" "chapter")
72
+End:
73
+-->
74
+
0 75
new file mode 100644
... ...
@@ -0,0 +1,83 @@
1
+/*
2
+ * $Id: xcap_callback.c,v 1.2 2007/02/20 13:40:09 anca_vamanu Exp $
3
+ *
4
+ * xcap_client module - openser xcap client module
5
+ *
6
+ * Copyright (C) 2007 Voice Sistem S.R.L.
7
+ *
8
+ * This file is part of openser, a free SIP server.
9
+ *
10
+ * openser is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version
14
+ *
15
+ * openser is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License 
21
+ * along with this program; if not, write to the Free Software 
22
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
+ *	
24
+ *History:
25
+ *--------
26
+ *  2007-08-30  initial version (anca)
27
+ */
28
+
29
+#include <stdio.h>
30
+#include <stdlib.h>
31
+#include "../../dprint.h"
32
+#include "../../mem/shm_mem.h"
33
+#include "../presence/hash.h"
34
+#include "xcap_callbacks.h"
35
+#include "xcap_client.h"
36
+
37
+void run_xcap_update_cb(int type, str xid, char* stream)
38
+{
39
+	xcap_callback_t* cb;
40
+
41
+	for (cb= xcapcb_list; cb; cb=cb->next)
42
+	{
43
+		if(cb->types & type) 
44
+		{	
45
+			DBG("xcap_client: run_xcap_update_cb: found callback\n");
46
+			cb->callback(type, xid, stream);
47
+		}
48
+	}
49
+}
50
+
51
+int register_xcapcb( int types, xcap_cb f)
52
+{
53
+	xcap_callback_t* xcb;
54
+
55
+	xcb= (xcap_callback_t*)shm_malloc(sizeof(xcap_callback_t));
56
+	if(xcb== NULL)
57
+	{
58
+		ERR_MEM("xcap_client", "register_xcapcb");
59
+	}
60
+	memset(xcb, 0, sizeof(xcap_callback_t));
61
+
62
+	xcb->callback= f;
63
+	xcb->types= types;
64
+	xcb->next= xcapcb_list;
65
+	xcapcb_list= xcb;
66
+	return 0;
67
+
68
+error:
69
+	return -1;
70
+}
71
+
72
+void destroy_xcapcb_list()
73
+{
74
+	xcap_callback_t* xcb, *prev_xcb;
75
+	
76
+	xcb= xcapcb_list;
77
+	while(xcb)
78
+	{
79
+		prev_xcb= xcb;
80
+		xcb= xcb->next;
81
+		shm_free(xcb);
82
+	}
83
+}
0 84
new file mode 100644
... ...
@@ -0,0 +1,62 @@
1
+/*
2
+ * $Id: xcap_callback.h,v 1.2 2007/02/20 13:40:09 anca_vamanu Exp $
3
+ *
4
+ * xcap_client module - openser xcap client module
5
+ *
6
+ * Copyright (C) 2007 Voice Sistem S.R.L.
7
+ *
8
+ * This file is part of openser, a free SIP server.
9
+ *
10
+ * openser is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version
14
+ *
15
+ * openser is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License 
21
+ * along with this program; if not, write to the Free Software 
22
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
+ *	
24
+ *History:
25
+ *--------
26
+ *  2007-08-30  initial version (anca)
27
+ */
28
+
29
+#ifndef XCAP_CBACK
30
+#define XCAP_CBACK
31
+
32
+#include "../../str.h"
33
+
34
+#define PRES_RULES         1<<1
35
+#define RESOURCE_LIST      1<<2
36
+#define RLS_SERVICE        1<<3
37
+#define PIDF_MANIPULATION  1<<4
38
+
39
+
40
+/* callback function prototype */
41
+typedef int (xcap_cb)(int doc_type, str xid, char* doc);
42
+
43
+/* register callback function prototype */
44
+typedef int (*register_xcapcb_t)(int types, xcap_cb f);
45
+
46
+
47
+typedef struct xcap_callback {
48
+	int types;                   /* types of events that trigger the callback*/
49
+	xcap_cb* callback;            /* callback function */
50
+	struct xcap_callback* next;
51
+}xcap_callback_t;
52
+
53
+/* destroy registered callback list */
54
+void destroy_xcapcb_list();
55
+
56
+/* register a callback for several types of events */
57
+int register_xcapcb( int types, xcap_cb f);
58
+
59
+/* run all transaction callbacks for an composed type */
60
+void run_xcap_update_cb(int type, str xid, char* stream);
61
+
62
+#endif
0 63
new file mode 100644
... ...
@@ -0,0 +1,210 @@
1
+/*
2
+ * $Id: xcap_client.c 2230 2007-06-06 07:13:20Z anca_vamanu $
3
+ *
4
+ * xcap_client module - XCAP client for openser
5
+ *
6
+ * Copyright (C) 2007 Voice Sistem S.R.L.
7
+ *
8
+ * This file is part of openser, a free SIP server.
9
+ *
10
+ * openser is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version
14
+ *
15
+ * openser is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License 
21
+ * along with this program; if not, write to the Free Software 
22
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
+ *
24
+ * History:
25
+ * --------
26
+ *  2007-08-20  initial version (anca)
27
+ */
28
+
29
+#include <stdio.h>
30
+#include <string.h>
31
+#include <stdlib.h>
32
+#include <sys/types.h>
33
+#include <sys/ipc.h>
34
+#include <unistd.h>
35
+#include <fcntl.h>
36
+#include <time.h>
37
+#include <curl/curl.h>
38
+
39
+#include "../../pt.h"
40
+#include "../../db/db.h"
41
+#include "../../sr_module.h"
42
+#include "../../dprint.h"
43
+#include "../../error.h"
44
+#include "../../ut.h"
45
+#include "../../mem/mem.h"
46
+#include "../../mem/shm_mem.h"
47
+#include "xcap_functions.h"
48
+#include "xcap_client.h"
49
+
50
+MODULE_VERSION
51
+
52
+static int mod_init(void);
53
+static int child_init(int);
54
+void destroy(void);
55
+struct mi_root* refreshXcapDoc(struct mi_root* cmd, void* param);
56
+int get_auid_flag(str auid);
57
+
58
+xcap_callback_t* xcapcb_list= NULL;
59
+
60
+static cmd_export_t  cmds[]=
61
+{	
62
+	{"bind_xcap",  (cmd_function)bind_xcap,  1,    0,            0},
63
+	{    0,                     0,           0,    0,            0}
64
+};
65
+
66
+static mi_export_t mi_cmds[] = {
67
+	{ "refreshXcapDoc", refreshXcapDoc,      0,  0,  0},
68
+	{ 0,                 0,                  0,  0,  0}
69
+};
70
+
71
+/** module exports */
72
+struct module_exports exports= {
73
+	"xcap_client",				/* module name */
74
+	DEFAULT_DLFLAGS,			/* dlopen flags */
75
+	cmds,  						/* exported functions */
76
+	0,  						/* exported parameters */
77
+	0,      					/* exported statistics */
78
+	mi_cmds,   					/* exported MI functions */
79
+	0,							/* exported pseudo-variables */
80
+	0,							/* extra processes */
81
+	mod_init,					/* module initialization function */
82
+	(response_function) 0,      /* response handling function */
83
+	(destroy_function) destroy, /* destroy function */
84
+	child_init                  /* per-child init function */
85
+};
86
+
87
+/**
88
+ * init module function
89
+ */
90
+static int mod_init(void)
91
+{
92
+	curl_global_init(CURL_GLOBAL_ALL);
93
+	return 0;
94
+}
95
+static int child_init(int rank)
96
+{ 
97
+	return 0;
98
+}
99
+
100
+void destroy(void)
101
+{
102
+	curl_global_cleanup();
103
+}
104
+
105
+
106
+int parse_doc_url(str doc_url, char** serv_addr, xcap_doc_sel_t* doc_sel)
107
+{
108
+	char* sl, *str_type;	
109
+	
110
+	sl= strchr(doc_url.s, '/');
111
+	*sl= '\0';
112
+	*serv_addr= doc_url.s;
113
+	
114
+	sl++;
115
+	doc_sel->auid.s= sl;
116
+	sl= strchr(sl, '/');
117
+	doc_sel->auid.len= sl- doc_sel->auid.s;
118
+	
119
+	sl++;
120
+	str_type= sl;
121
+	sl= strchr(sl, '/');
122
+	*sl= '\0';
123
+
124
+	if(strcasecmp(str_type, "users")== 0)
125
+		doc_sel->type= USERS_TYPE;
126
+	else
127
+	if(strcasecmp(str_type, "group")== 0)
128
+		doc_sel->type= GLOBAL_TYPE;
129
+
130
+	sl++;
131
+
132
+	return 0;
133
+
134
+}
135
+/*
136
+ * mi cmd: refreshXcapDoc
137
+ *			<document url> 
138
+ * */
139
+
140
+struct mi_root* refreshXcapDoc(struct mi_root* cmd, void* param)
141
+{
142
+	struct mi_node* node= NULL;
143
+	str doc_url;
144
+	xcap_doc_sel_t doc_sel;
145
+	char* serv_addr;
146
+	char* stream;
147
+	int type;
148
+
149
+	node = cmd->node.kids;
150
+	if(node == NULL)
151
+		return 0;
152
+
153
+	doc_url = node->value;
154
+	if(doc_url.s == NULL || doc_url.len== 0)
155
+	{
156
+		LOG(L_ERR, "xcap_client:refreshXcapDoc: empty uri\n");
157
+		return init_mi_tree(404, "Empty document URL", 20);
158
+	}
159
+	
160
+	if(node->next!= NULL)
161
+		return 0;
162
+
163
+	/* send GET HTTP request to the server */
164
+	stream=	send_http_get(doc_url.s);
165
+	if(stream== NULL)
166
+	{
167
+		LOG(L_ERR, "xcap_client:refreshXcapDoc: ERROR in http get\n");
168
+		return 0;
169
+	}
170
+	
171
+	/* call registered functions with document argument */
172
+	if(parse_doc_url(doc_url, &serv_addr, &doc_sel)< 0)
173
+	{
174
+		LOG(L_ERR, "xcap_client:refreshXcapDoc: ERROR parsing document url\n");
175
+		return 0;
176
+	}
177
+
178
+	type= get_auid_flag(doc_sel.auid);
179
+	if(type< 0)
180
+	{
181
+		LOG(L_ERR, "xcap_client:refreshXcapDoc: ERROR incorect auid"
182
+				": %.*s\n",doc_sel.auid.len, doc_sel.auid.s);
183
+		goto error;
184
+	}
185
+
186
+	run_xcap_update_cb(type, doc_sel.xid, stream);
187
+
188
+	return init_mi_tree(200, "OK", 2);
189
+
190
+error:
191
+	if(stream)
192
+		pkg_free(stream);
193
+	return 0;
194
+}
195
+
196
+int get_auid_flag(str auid)
197
+{
198
+
199
+	switch (auid.len)
200
+	{
201
+		case strlen("pres-rules"):	if(strncmp(auid.s, "pres-rules",
202
+											strlen("pres-rules"))== 0)
203
+										return PRES_RULES;
204
+
205
+		case strlen("rls-services"):if(strncmp(auid.s, "rls-services",
206
+											strlen("rls-services"))== 0)
207
+										return RESOURCE_LIST;
208
+	}
209
+	return -1;
210
+}
0 211
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+/*
2
+ * $Id: xcap_client.h 2230 2007-06-06 07:13:20Z anca_vamanu $
3
+ *
4
+ * xcap_client module - XCAP client for openser
5
+ *
6
+ * Copyright (C) 2007 Voice Sistem S.R.L.
7
+ *
8
+ * This file is part of openser, a free SIP server.
9
+ *
10
+ * openser is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version
14
+ *
15
+ * openser is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License 
21
+ * along with this program; if not, write to the Free Software 
22
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
+ *
24
+ * History:
25
+ * --------
26
+ *  2007-08-20  initial version (anca)
27
+ */
28
+
29
+#ifndef XCAP_CL_H
30
+#define XCAP_CL_H
31
+
32
+#include "xcap_callbacks.h"
33
+
34
+extern xcap_callback_t* xcapcb_list;
35
+
36
+
37
+#endif
0 38
new file mode 100644
... ...
@@ -0,0 +1,458 @@
1
+/*
2
+ * $Id: xcap_functions.c 2230 2007-06-06 07:13:20Z anca_vamanu $
3
+ *
4
+ * xcap_client module - XCAP client for openser
5
+ *
6
+ * Copyright (C) 2007 Voice Sistem S.R.L.
7
+ *
8
+ * This file is part of openser, a free SIP server.
9
+ *
10
+ * openser is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version
14
+ *
15
+ * openser is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU General Public License 
21
+ * along with this program; if not, write to the Free Software 
22
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
+ *
24
+ * History:
25
+ * --------
26
+ *  2007-08-20  initial version (anca)
27
+ */
28
+
29
+#include <stdio.h>
30
+#include <string.h>
31
+#include <stdlib.h>
32
+#include <sys/types.h>
33
+#include <sys/ipc.h>
34
+#include <unistd.h>
35
+#include <fcntl.h>
36
+#include <time.h>
37
+#include <curl/curl.h>
38
+#include "../../mem/mem.h"
39
+#include "xcap_functions.h"
40
+#include "xcap_client.h"
41
+
42
+size_t write_function( void *ptr, size_t size, size_t nmemb, void *stream);
43
+
44
+int bind_xcap(xcap_api_t* api)
45
+{
46
+	if (!api) {
47
+		LOG(L_ERR, "NOTIFIER:bind_notifier: Invalid parameter value\n");
48
+		return -1;
49
+	}
50
+	api->get_elem= xcapGetElem;
51
+	api->int_node_sel= xcapInitNodeSel;
52
+	api->add_step= xcapNodeSelAddStep;
53
+	api->add_terminal= xcapNodeSelAddTerminal;
54
+	api->free_node_sel= xcapFreeNodeSel;
55
+	api->register_xcb= register_xcapcb;
56
+
57
+	return 0;
58
+}
59
+
60
+void xcapFreeNodeSel(xcap_node_sel_t* node)
61
+{
62
+	step_t* s, *p;
63
+	ns_list_t* n, *m;
64
+
65
+	s= node->steps;
66
+	while(s)
67
+	{
68
+		p= s;
69
+		s= s->next;
70
+		pkg_free(p->val.s);
71
+		pkg_free(p);
72
+	}
73
+
74
+	n= node->ns_list;
75
+	while(n)
76
+	{
77
+		m= n;
78
+		n= n->next;
79
+		pkg_free(n->value.s);
80
+		pkg_free(n);
81
+	}
82
+
83
+	pkg_free(node);
84
+
85
+}
86
+
87
+xcap_node_sel_t* xcapInitNodeSel()
88
+{
89
+	xcap_node_sel_t* nsel= NULL;
90
+
91
+	nsel= (xcap_node_sel_t*)pkg_malloc(sizeof(xcap_node_sel_t));
92
+	if(nsel== NULL)
93
+	{
94
+		LOG(L_ERR, "XCAP_CLIENT: xcapInitNodeSel: ERROR No more memory\n");
95
+		goto error;
96
+	}
97
+	memset(nsel, 0, sizeof(xcap_node_sel_t));
98
+	nsel->steps= (step_t*)pkg_malloc(sizeof(step_t));
99
+	if(nsel->steps== NULL)
100
+	{
101
+		LOG(L_ERR, "XCAP_CLIENT: xcapInitNodeSel: ERROR No more memory\n");
102
+		goto error;
103
+	}
104
+	memset(nsel->steps, 0, sizeof(step_t));
105
+	nsel->last_step= nsel->steps;
106
+
107
+	nsel->ns_list= (ns_list_t*)pkg_malloc(sizeof(ns_list_t));
108
+	if(nsel->ns_list== NULL)
109
+	{
110
+		LOG(L_ERR, "XCAP_CLIENT: xcapInitNodeSel: ERROR No more memory\n");
111
+		goto error;
112
+	}
113
+	memset(nsel->ns_list, 0, sizeof(ns_list_t));
114
+	nsel->last_ns= nsel->ns_list;
115
+
116
+	return nsel;
117
+
118
+error:
119
+	if(nsel)
120
+	{
121
+		if(nsel->steps)
122
+			pkg_free(nsel->steps);
123
+		if(nsel->ns_list)
124
+			pkg_free(nsel->ns_list);
125
+		pkg_free(nsel);
126
+	}
127
+
128
+	return NULL;
129
+}
130
+
131
+xcap_node_sel_t* xcapNodeSelAddStep(xcap_node_sel_t* curr_sel, str* name,
132
+		str* namespace, int pos, attr_test_t*  attr_test, str* extra_sel)
133
+{
134
+	int size= 0;
135
+	str new_step= {NULL, 0};
136
+	step_t* s= NULL;
137
+	char ns_card= 'a';
138
+	ns_list_t* ns= NULL;
139
+
140
+	if(name)
141
+		size+= name->len;
142
+	else
143
+		size+= 1;
144
+
145
+	if(namespace)
146
+		size+= 2;
147
+	if(pos> 0)
148
+		size+= 7;
149
+	if(attr_test)
150
+		size+= 2+ attr_test->name.len+ attr_test->value.len;
151
+	if(extra_sel)
152
+		size+= 2+ extra_sel->len;
153
+	
154
+	new_step.s= (char*)pkg_malloc(size* sizeof(char));
155
+	if(new_step.s== NULL)
156
+	{
157
+		LOG(L_ERR, "XCAP_CLIENT: xcapNodeSelAddStep: ERROR No more memory\n");
158
+		goto error;
159
+	}
160
+	if(name)
161
+	{
162
+		if(namespace)
163
+		{
164
+			ns_card= curr_sel->ns_no+ 'a';
165
+			curr_sel->ns_no++;
166
+
167
+			if(ns_card> 'z')
168
+			{
169
+				LOG(L_ERR, "XCAP_CLIENT: xcapNodeSelAddStep: ERROR Insuficient name cards"
170
+						" for namespaces\n");
171
+				goto error;
172
+			}
173
+			new_step.len= sprintf(new_step.s, "%c:", ns_card);		
174
+		}
175
+		memcpy(new_step.s+new_step.len, name->s, name->len);
176
+		new_step.len+= name->len;
177
+	}
178
+	else
179
+		memcpy(new_step.s+new_step.len, "*", 1);
180
+
181
+	if(attr_test)
182
+	{
183
+		new_step.len+= sprintf(new_step.s+ new_step.len, "[%.*s=%.*s]", attr_test->name.len,
184
+				attr_test->name.s, attr_test->value.len, attr_test->value.s);
185
+	}
186
+	if(pos> 0)
187
+		new_step.len+= sprintf(new_step.s+ new_step.len, "[%d]", pos);
188
+
189
+	if(extra_sel)
190
+	{
191
+		memcpy(new_step.s+ new_step.len, extra_sel->s, extra_sel->len);
192
+		new_step.len= extra_sel->len;
193
+	}
194
+
195
+	s= (step_t*)pkg_malloc(sizeof(step_t));
196
+	if(s== NULL)
197
+	{
198
+		LOG(L_ERR, "XCAP_CLIENT: xcapNodeSelAddStep: ERROR No more memory\n");
199
+		goto error;
200
+	}
201
+	s->val= new_step;
202
+	s->next= NULL;
203
+
204
+	curr_sel->last_step->next= s;
205
+	curr_sel->last_step= s;
206
+
207
+	/* add the namespace binding if present */
208
+	if(namespace)
209
+	{
210
+		ns= (ns_list_t*)pkg_malloc(sizeof(ns_list_t));
211
+		if(ns== NULL)
212
+		{
213
+			LOG(L_ERR, "XCAP_CLIENT: xcapNodeSelAddStep: ERROR No more memory");
214
+			goto error;
215
+		}
216
+		ns->name= ns_card;
217
+		ns->value.s= (char*)pkg_malloc(namespace->len* sizeof(char));
218
+		if(ns->value.s== NULL)
219
+		{
220
+			LOG(L_ERR, "XCAP_CLIENT: xcapNodeSelAddStep: ERROR No more memory");
221
+			goto error;
222
+		}
223
+		memcpy(ns->value.s, namespace->s, namespace->len);
224
+		ns->value.len= namespace->len;
225
+
226
+		curr_sel->last_ns->next= ns;
227
+		curr_sel->last_ns= ns;
228
+	}
229
+
230
+	curr_sel->size+= 1+ new_step.len;
231
+	if(namespace->len)
232
+	{
233
+		curr_sel->size+= namespace->len+ 3;
234
+	}
235
+	
236
+	return curr_sel;
237
+
238
+error:
239
+	if(new_step.s)
240
+		pkg_free(new_step.s);
241
+	if(s)
242
+		pkg_free(s);
243
+	if(ns)
244
+	{
245
+		if(ns->value.s)
246
+			pkg_free(ns->value.s);
247
+		pkg_free(ns);
248
+	}
249
+
250
+	return NULL;
251
+}
252
+
253
+xcap_node_sel_t* xcapNodeSelAddTerminal(xcap_node_sel_t* curr_sel, 
254
+		char* attr_sel, char* namespace_sel, char* extra_sel )
255
+{
256
+
257
+	return NULL;
258
+}
259
+
260
+char* get_node_selector(xcap_node_sel_t* node_sel)
261
+{
262
+	char* buf= NULL;
263
+	step_t* s;
264
+	int len= 0;
265
+	ns_list_t* ns_elem;
266
+
267
+	buf= (char*)pkg_malloc((node_sel->size+ 10)* sizeof(char));
268
+	if(buf== NULL)
269
+	{
270
+		LOG(L_ERR, "XCAP_client: get_node_selector: ERROR No more memory\n");
271
+		return NULL;
272
+	}
273
+
274
+	s= node_sel->steps->next;
275
+
276
+	while(1)
277
+	{
278
+		memcpy(buf+ len, s->val.s, s->val.len);
279
+		len+= s->val.len;
280
+		s= s->next;
281
+		if(s)
282
+			buf[len++]= '/';
283
+		else
284
+			break;
285
+	}
286
+	ns_elem= node_sel->ns_list;
287
+
288
+	if(ns_elem)
289
+		buf[len++]= '?';
290
+	
291
+	while(ns_elem)
292
+	{
293
+		len+= sprintf(buf+ len, "xmlns(%c=%.*s)", ns_elem->name,
294
+				ns_elem->value.len, ns_elem->value.s);
295
+		ns_elem= ns_elem->next;
296
+	}
297
+	
298
+	buf[len]= '\0';
299
+
300
+	return NULL;
301
+}
302
+
303
+/* for testing purposes only
304
+ * function to write data at the xcap server */
305
+int xcapWriteData(char* path, char* file_name)
306
+{
307
+	CURL* curl_handle= NULL;
308
+	FILE* f= NULL;
309
+
310
+	f= fopen(file_name, "rt");
311
+	if(f== NULL)
312
+	{
313
+		LOG(L_ERR, "XCAP_client: xcapWriteData: ERROR while opening"
314
+				" file %s for reading\n", file_name);
315
+		return -1;
316
+	}
317
+	curl_handle = curl_easy_init();
318
+
319
+	curl_easy_setopt(curl_handle, CURLOPT_URL, path);
320
+	curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1);	
321
+	curl_easy_setopt(curl_handle,  CURLOPT_STDERR, stdout);	
322
+	
323
+	/* enable uploading */
324
+	curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1) ;
325
+
326
+	/* HTTP PUT please */
327
+	curl_easy_setopt(curl_handle, CURLOPT_PUT, 1);
328
+
329
+//	curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_function);
330
+	
331
+	curl_easy_setopt(curl_handle, CURLOPT_READDATA, f);
332
+	
333
+	curl_easy_perform(curl_handle);
334
+	
335
+	curl_global_cleanup();
336
+
337
+	return 0;
338
+}
339
+
340
+/* xcap_root must be a NULL terminated string */
341
+
342
+char* xcapGetElem(char* xcap_root, xcap_doc_sel_t* doc_sel, xcap_node_sel_t* node_sel)
343
+{
344
+	int len= 0, size;
345
+	char* path= NULL;
346
+	char* node_selector= NULL;
347
+	char* stream= NULL;
348
+		
349
+	len= (strlen(xcap_root)+ 1+ doc_sel->auid.len+ 5+ doc_sel->xid.len+
350
+		doc_sel->filename.len+ 50)* sizeof(char);
351
+	
352
+	if(node_sel)
353
+		len+= node_sel->size;
354
+
355
+	path= (char*)pkg_malloc(len);
356
+	if(path== NULL)
357
+	{
358
+		LOG(L_ERR, "XCAP_CLIENT: xcapGetElem: ERROR NO more memory\n");
359
+		goto error;
360
+	}
361
+
362
+	if(node_sel)
363
+	{
364
+		node_selector= get_node_selector(node_sel);
365
+		if(node_selector== NULL)
366
+		{
367
+			LOG(L_ERR, "XCAP_CLIENT: xcapGetElem:ERROR while constructing"
368
+					" node selector\n");
369
+			goto error;
370
+		}
371
+	}
372
+	
373
+	size= sprintf(path, "%s/%.*s/", xcap_root,doc_sel->auid.len,doc_sel->auid.s);
374
+
375
+	if(doc_sel->type==USERS_TYPE)
376
+		size+= sprintf(path+ size, "%s/%.*s/", "users", doc_sel->xid.len, doc_sel->xid.s);
377
+	else
378
+		size+= sprintf(path+ size, "%s/", "global");
379
+	size+= sprintf(path+ size, "%.*s", doc_sel->filename.len, doc_sel->filename.s);
380
+	
381
+	if(node_selector)
382
+	{
383
+		size+= sprintf(path+ size, "/~~%s", node_selector);
384
+	}
385
+