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