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