c66df27a8cecfc597349ad39ed28770aa768f2bf
[OpenSRF.git] / src / libopensrf / transport_message.c
1 #include <opensrf/transport_message.h>
2
3
4 // ---------------------------------------------------------------------------------
5 // Allocates and initializes a new transport_message
6 // ---------------------------------------------------------------------------------
7 transport_message* message_init( const char* body, const char* subject,
8                 const char* thread, const char* recipient, const char* sender ) {
9
10         transport_message* msg = safe_malloc( sizeof(transport_message) );
11
12         if( body                                == NULL ) { body                = ""; }
13         if( thread                              == NULL ) { thread              = ""; }
14         if( subject                             == NULL ) { subject             = ""; }
15         if( sender                              == NULL ) { sender              = ""; }
16         if( recipient                   == NULL ) { recipient   = ""; }
17
18         msg->body                               = strdup(body);
19         msg->thread                             = strdup(thread);
20         msg->subject                    = strdup(subject);
21         msg->recipient                  = strdup(recipient);
22         msg->sender                             = strdup(sender);
23
24         if(     msg->body               == NULL || msg->thread                          == NULL ||
25                         msg->subject    == NULL || msg->recipient                       == NULL ||
26                         msg->sender             == NULL ) {
27
28                 osrfLogError(OSRF_LOG_MARK,  "message_init(): Out of Memory" );
29                 free( msg->body );
30                 free( msg->thread );
31                 free( msg->subject );
32                 free( msg->recipient );
33                 free( msg->sender );
34                 free( msg );
35                 return NULL;
36         }
37
38         msg->router_from    = NULL;
39         msg->router_to      = NULL;
40         msg->router_class   = NULL;
41         msg->router_command = NULL;
42         msg->osrf_xid       = NULL;
43         msg->is_error       = 0;
44         msg->error_type     = NULL;
45         msg->error_code     = 0;
46         msg->broadcast      = 0;
47         msg->msg_xml        = NULL;
48
49         return msg;
50 }
51
52
53 transport_message* new_message_from_xml( const char* msg_xml ) {
54
55         if( msg_xml == NULL || *msg_xml == '\0' )
56                 return NULL;
57
58         transport_message* new_msg = safe_malloc( sizeof(transport_message) );
59
60         new_msg->body           = NULL;
61         new_msg->subject        = NULL;
62         new_msg->thread         = NULL;
63         new_msg->recipient      = NULL;
64         new_msg->sender         = NULL;
65         new_msg->router_from    = NULL;
66         new_msg->router_to      = NULL;
67         new_msg->router_class   = NULL;
68         new_msg->router_command = NULL;
69         new_msg->osrf_xid       = NULL;
70         new_msg->is_error       = 0;
71         new_msg->error_type     = NULL;
72         new_msg->error_code     = 0;
73         new_msg->broadcast      = 0;
74         new_msg->msg_xml        = NULL;
75
76         xmlKeepBlanksDefault(0);
77         xmlDocPtr msg_doc = xmlReadDoc( BAD_CAST msg_xml, NULL, NULL, 0 );
78         xmlNodePtr root = xmlDocGetRootElement(msg_doc);
79
80         xmlChar* sender = xmlGetProp(root, BAD_CAST "from");
81         xmlChar* recipient      = xmlGetProp(root, BAD_CAST "to");
82         xmlChar* subject                = xmlGetProp(root, BAD_CAST "subject");
83         xmlChar* thread         = xmlGetProp( root, BAD_CAST "thread" );
84         xmlChar* router_from    = xmlGetProp( root, BAD_CAST "router_from" );
85         xmlChar* router_to      = xmlGetProp( root, BAD_CAST "router_to" );
86         xmlChar* router_class= xmlGetProp( root, BAD_CAST "router_class" );
87         xmlChar* broadcast      = xmlGetProp( root, BAD_CAST "broadcast" );
88         xmlChar* osrf_xid    = xmlGetProp( root, BAD_CAST "osrf_xid" );
89
90    if( osrf_xid ) {
91       message_set_osrf_xid( new_msg, (char*) osrf_xid);
92       xmlFree(osrf_xid);
93    }
94
95         if( router_from ) {
96                 new_msg->sender         = strdup((const char*)router_from);
97         } else {
98                 if( sender ) {
99                         new_msg->sender         = strdup((const char*)sender);
100                         xmlFree(sender);
101                 }
102         }
103
104         if( recipient ) {
105                 new_msg->recipient      = strdup((const char*)recipient);
106                 xmlFree(recipient);
107         }
108         if(subject){
109                 new_msg->subject                = strdup((const char*)subject);
110                 xmlFree(subject);
111         }
112         if(thread) {
113                 new_msg->thread         = strdup((const char*)thread);
114                 xmlFree(thread);
115         }
116         if(router_from) {
117                 new_msg->router_from    = strdup((const char*)router_from);
118                 xmlFree(router_from);
119         }
120         if(router_to) {
121                 new_msg->router_to      = strdup((const char*)router_to);
122                 xmlFree(router_to);
123         }
124         if(router_class) {
125                 new_msg->router_class = strdup((const char*)router_class);
126                 xmlFree(router_class);
127         }
128         if(broadcast) {
129                 if(strcmp((const char*) broadcast,"0") )
130                         new_msg->broadcast      = 1;
131                 xmlFree(broadcast);
132         }
133
134         xmlNodePtr search_node = root->children;
135         while( search_node != NULL ) {
136
137                 if( ! strcmp( (const char*) search_node->name, "thread" ) ) {
138                         if( search_node->children && search_node->children->content ) 
139                                 new_msg->thread = strdup( (const char*) search_node->children->content );
140                 }
141
142                 if( ! strcmp( (const char*) search_node->name, "subject" ) ) {
143                         if( search_node->children && search_node->children->content )
144                                 new_msg->subject = strdup( (const char*) search_node->children->content );
145                 }
146
147                 if( ! strcmp( (const char*) search_node->name, "body" ) ) {
148                         if( search_node->children && search_node->children->content )
149                                 new_msg->body = strdup((const char*) search_node->children->content );
150                 }
151
152                 search_node = search_node->next;
153         }
154
155         if( new_msg->thread == NULL ) 
156                 new_msg->thread = strdup("");
157         if( new_msg->subject == NULL )
158                 new_msg->subject = strdup("");
159         if( new_msg->body == NULL )
160                 new_msg->body = strdup("");
161
162         new_msg->msg_xml = xmlDocToString(msg_doc, 0);
163    xmlFreeDoc(msg_doc);
164    xmlCleanupParser();
165
166         return new_msg;
167 }
168
169 void message_set_osrf_xid( transport_message* msg, const char* osrf_xid ) {
170    if(!msg) return;
171    if( osrf_xid )
172       msg->osrf_xid = strdup(osrf_xid);
173    else msg->osrf_xid = strdup("");
174 }
175
176 void message_set_router_info( transport_message* msg, const char* router_from,
177                 const char* router_to, const char* router_class, const char* router_command,
178                 int broadcast_enabled ) {
179
180         if( !msg ) return;
181         
182         if(router_from)
183                 msg->router_from                = strdup(router_from);
184         else
185                 msg->router_from                = strdup("");
186
187         if(router_to)
188                 msg->router_to                  = strdup(router_to);
189         else
190                 msg->router_to                  = strdup("");
191
192         if(router_class)
193                 msg->router_class               = strdup(router_class);
194         else 
195                 msg->router_class               = strdup("");
196         
197         if(router_command)
198                 msg->router_command     = strdup(router_command);
199         else
200                 msg->router_command     = strdup("");
201
202         msg->broadcast = broadcast_enabled;
203
204         if( msg->router_from == NULL || msg->router_to == NULL ||
205                         msg->router_class == NULL || msg->router_command == NULL ) 
206                 osrfLogError(OSRF_LOG_MARK,  "message_set_router_info(): Out of Memory" );
207
208         return;
209 }
210
211
212
213 /* encodes the message for traversal */
214 int message_prepare_xml( transport_message* msg ) {
215         if( !msg ) return 0;
216         if( msg->msg_xml == NULL )
217                 msg->msg_xml = message_to_xml( msg );
218         return 1;
219 }
220
221
222 // ---------------------------------------------------------------------------------
223 //
224 // ---------------------------------------------------------------------------------
225 int message_free( transport_message* msg ){
226         if( msg == NULL ) { return 0; }
227
228         free(msg->body); 
229         free(msg->thread);
230         free(msg->subject);
231         free(msg->recipient);
232         free(msg->sender);
233         free(msg->router_from);
234         free(msg->router_to);
235         free(msg->router_class);
236         free(msg->router_command);
237         free(msg->osrf_xid);
238         if( msg->error_type != NULL ) free(msg->error_type);
239         if( msg->msg_xml != NULL ) free(msg->msg_xml);
240         free(msg);
241         return 1;
242 }
243         
244 // ---------------------------------------------------------------------------------
245 // Allocates a char* holding the XML representation of this jabber message
246 // ---------------------------------------------------------------------------------
247 char* message_to_xml( const transport_message* msg ) {
248
249         //int                   bufsize;
250         //xmlChar*              xmlbuf;
251         //char*                 encoded_body;
252
253         xmlNodePtr      message_node;
254         xmlNodePtr      body_node;
255         xmlNodePtr      thread_node;
256         xmlNodePtr      subject_node;
257         xmlNodePtr      error_node;
258         
259         xmlDocPtr       doc;
260
261         xmlKeepBlanksDefault(0);
262
263         if( ! msg ) { 
264                 osrfLogWarning(OSRF_LOG_MARK,  "Passing NULL message to message_to_xml()"); 
265                 return NULL; 
266         }
267
268         doc = xmlReadDoc( BAD_CAST "<message/>", NULL, NULL, XML_PARSE_NSCLEAN );
269         message_node = xmlDocGetRootElement(doc);
270
271         if( msg->is_error ) {
272                 error_node = xmlNewChild(message_node, NULL, BAD_CAST "error" , NULL );
273                 xmlAddChild( message_node, error_node );
274                 xmlNewProp( error_node, BAD_CAST "type", BAD_CAST msg->error_type );
275                 char code_buf[16];
276                 osrf_clearbuf( code_buf, sizeof(code_buf));
277                 sprintf(code_buf, "%d", msg->error_code );
278                 xmlNewProp( error_node, BAD_CAST "code", BAD_CAST code_buf  );
279         }
280
281         /* set from and to */
282         xmlNewProp( message_node, BAD_CAST "to", BAD_CAST msg->recipient );
283         xmlNewProp( message_node, BAD_CAST "from", BAD_CAST msg->sender );
284         xmlNewProp( message_node, BAD_CAST "router_from", BAD_CAST msg->router_from );
285         xmlNewProp( message_node, BAD_CAST "router_to", BAD_CAST msg->router_to );
286         xmlNewProp( message_node, BAD_CAST "router_class", BAD_CAST msg->router_class );
287         xmlNewProp( message_node, BAD_CAST "router_command", BAD_CAST msg->router_command );
288         xmlNewProp( message_node, BAD_CAST "osrf_xid", BAD_CAST msg->osrf_xid );
289
290         if( msg->broadcast )
291                 xmlNewProp( message_node, BAD_CAST "broadcast", BAD_CAST "1" );
292
293         /* Now add nodes where appropriate */
294         char* body                              = msg->body;
295         char* subject                   = msg->subject;
296         char* thread                    = msg->thread; 
297
298         if( thread && *thread ) {
299                 thread_node = xmlNewChild(message_node, NULL, (xmlChar*) "thread", NULL );
300                 xmlNodePtr txt = xmlNewText((xmlChar*) thread);
301                 xmlAddChild(thread_node, txt);
302                 xmlAddChild(message_node, thread_node); 
303         }
304
305         if( subject && *subject ) {
306                 subject_node = xmlNewChild(message_node, NULL, (xmlChar*) "subject", NULL );
307                 xmlNodePtr txt = xmlNewText((xmlChar*) subject);
308                 xmlAddChild(subject_node, txt);
309                 xmlAddChild( message_node, subject_node ); 
310         }
311
312         if( body && *body ) {
313                 body_node = xmlNewChild(message_node, NULL, (xmlChar*) "body", NULL);
314                 xmlNodePtr txt = xmlNewText((xmlChar*) body);
315                 xmlAddChild(body_node, txt);
316                 xmlAddChild( message_node, body_node ); 
317         }
318
319         xmlBufferPtr xmlbuf = xmlBufferCreate();
320         xmlNodeDump( xmlbuf, doc, xmlDocGetRootElement(doc), 0, 0);
321         char* xml = strdup((const char*) (xmlBufferContent(xmlbuf)));
322         xmlBufferFree(xmlbuf);
323         xmlFreeDoc( doc );               
324         xmlCleanupParser();
325         return xml;
326 }
327
328
329
330 void jid_get_username( const char* jid, char buf[], int size ) {
331
332         if( jid == NULL || buf == NULL || size <= 0 ) { return; }
333
334         /* find the @ and return whatever is in front of it */
335         int len = strlen( jid );
336         int i;
337         for( i = 0; i != len; i++ ) {
338                 if( jid[i] == '@' ) {
339                         if(i > size)  i = size;
340                         memcpy( buf, jid, i );
341                         buf[i] = '\0';
342                         return;
343                 }
344         }
345 }
346
347
348 void jid_get_resource( const char* jid, char buf[], int size)  {
349         if( jid == NULL || buf == NULL || size <= 0 ) { return; }
350
351         // Find the last slash, if any
352         
353         const char* start = strrchr( jid, '/' );
354         if( start ) {
355
356                 // Copy the text beyond the slash, up to a maximum size
357
358                 size_t len = strlen( ++start );
359                 if( len > size ) len = size;
360                 memcpy( buf, start, len );
361                 buf[ len ] = '\0';
362         }
363 }
364
365 void jid_get_domain( const char* jid, char buf[], int size ) {
366
367         if(jid == NULL) return;
368
369         int len = strlen(jid);
370         int i;
371         int index1 = 0; 
372         int index2 = 0;
373
374         for( i = 0; i!= len; i++ ) {
375                 if(jid[i] == '@')
376                         index1 = i + 1;
377                 else if(jid[i] == '/' && index1 != 0)
378                         index2 = i;
379         }
380
381         if( index1 > 0 && index2 > 0 && index2 > index1 ) {
382                 int dlen = index2 - index1;
383                 if(dlen > size) dlen = size;
384                 memcpy( buf, jid + index1, dlen );
385                 buf[dlen] = '\0'; // memcpy doesn't provide the nul
386         }
387 }
388
389 void set_msg_error( transport_message* msg, const char* type, int err_code ) {
390
391         if( !msg ) return;
392         
393         if( type != NULL && *type ) {
394                 msg->error_type = safe_malloc( strlen(type)+1); 
395                 strcpy( msg->error_type, type );
396                 msg->error_code = err_code;
397         }
398         msg->is_error = 1;
399 }