Initial revision
[OpenSRF.git] / 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 void message_set_router_info( transport_message* msg, char* router_from,
37                 char* router_to, char* router_class, char* router_command, int broadcast_enabled ) {
38
39         msg->router_from                = strdup(router_from);
40         msg->router_to                  = strdup(router_to);
41         msg->router_class               = strdup(router_class);
42         msg->router_command     = strdup(router_command);
43         msg->broadcast = broadcast_enabled;
44
45         if( msg->router_from == NULL || msg->router_to == NULL ||
46                         msg->router_class == NULL || msg->router_command == NULL ) 
47                 fatal_handler( "message_set_router_info(): Out of Memory" );
48
49         return;
50 }
51
52
53
54 /* encodes the message for traversal */
55 int message_prepare_xml( transport_message* msg ) {
56         if( msg->msg_xml != NULL ) { return 1; }
57         msg->msg_xml = message_to_xml( msg );
58         return 1;
59 }
60
61
62 // ---------------------------------------------------------------------------------
63 //
64 // ---------------------------------------------------------------------------------
65 int message_free( transport_message* msg ){
66         if( msg == NULL ) { return 0; }
67
68         free(msg->body); 
69         free(msg->thread);
70         free(msg->subject);
71         free(msg->recipient);
72         free(msg->sender);
73         free(msg->router_from);
74         free(msg->router_to);
75         free(msg->router_class);
76         free(msg->router_command);
77         if( msg->error_type != NULL ) free(msg->error_type);
78         if( msg->msg_xml != NULL ) free(msg->msg_xml);
79         free(msg);
80         return 1;
81 }
82         
83 // ---------------------------------------------------------------------------------
84 // Allocates a char* holding the XML representation of this jabber message
85 // ---------------------------------------------------------------------------------
86 char* message_to_xml( const transport_message* msg ) {
87
88         int                     bufsize;
89         xmlChar*                xmlbuf;
90         char*                   encoded_body;
91
92         xmlNodePtr      message_node;
93         xmlNodePtr      body_node;
94         xmlNodePtr      thread_node;
95         xmlNodePtr      subject_node;
96         xmlNodePtr      error_node;
97         
98         xmlDocPtr       doc;
99
100         xmlKeepBlanksDefault(0);
101
102         if( ! msg ) { 
103                 warning_handler( "Passing NULL message to message_to_xml()"); 
104                 return 0; 
105         }
106
107         doc = xmlReadDoc( BAD_CAST "<message/>", NULL, NULL, XML_PARSE_NSCLEAN );
108         message_node = xmlDocGetRootElement(doc);
109
110         if( msg->is_error ) {
111                 error_node = xmlNewChild(message_node, NULL, BAD_CAST "error" , NULL );
112                 xmlAddChild( message_node, error_node );
113                 xmlNewProp( error_node, BAD_CAST "type", BAD_CAST msg->error_type );
114                 char code_buf[16];
115                 memset( code_buf, 0, 16);
116                 sprintf(code_buf, "%d", msg->error_code );
117                 xmlNewProp( error_node, BAD_CAST "code", BAD_CAST code_buf  );
118         }
119         
120
121         /* set from and to */
122         xmlNewProp( message_node, BAD_CAST "to", BAD_CAST msg->recipient );
123         xmlNewProp( message_node, BAD_CAST "from", BAD_CAST msg->sender );
124         xmlNewProp( message_node, BAD_CAST "router_from", BAD_CAST msg->router_from );
125         xmlNewProp( message_node, BAD_CAST "router_to", BAD_CAST msg->router_to );
126         xmlNewProp( message_node, BAD_CAST "router_class", BAD_CAST msg->router_class );
127         xmlNewProp( message_node, BAD_CAST "router_command", BAD_CAST msg->router_command );
128
129         if( msg->broadcast )
130                 xmlNewProp( message_node, BAD_CAST "broadcast", BAD_CAST "1" );
131
132         /* Now add nodes where appropriate */
133         char* body                              = msg->body;
134         char* subject                   = msg->subject;
135         char* thread                    = msg->thread; 
136
137         if( thread && strlen(thread) > 0 ) {
138                 thread_node = xmlNewChild(message_node, NULL, (xmlChar*) "thread", (xmlChar*) thread );
139                 xmlAddChild( message_node, thread_node ); 
140         }
141
142         if( subject && strlen(subject) > 0 ) {
143                 subject_node = xmlNewChild(message_node, NULL, (xmlChar*) "subject", (xmlChar*) subject );
144                 xmlAddChild( message_node, subject_node ); 
145         }
146
147         if( body && strlen(body) > 0 ) {
148                 body_node = xmlNewChild(message_node, NULL, (xmlChar*) "body", (xmlChar*) body );
149                 xmlAddChild( message_node, body_node ); 
150         }
151
152
153         xmlDocDumpFormatMemory( doc, &xmlbuf, &bufsize, 0 );
154         encoded_body = strdup( (char*) xmlbuf );
155
156         if( encoded_body == NULL ) 
157                 fatal_handler("message_to_xml(): Out of Memory");
158
159         xmlFree(xmlbuf);
160         xmlFreeDoc( doc );
161         xmlCleanupParser();
162
163
164         /*** remove the XML declaration */
165
166         int len = strlen(encoded_body);
167         char tmp[len];
168         memset( tmp, 0, len );
169         int i;
170         int found_at = 0;
171
172         /* when we reach the first >, take everything after it */
173         for( i = 0; i!= len; i++ ) {
174                 if( encoded_body[i] == 62) { /* ascii > */
175
176                         /* found_at holds the starting index of the rest of the doc*/
177                         found_at = i + 1; 
178                         break;
179                 }
180         }
181
182         if( found_at ) {
183                 /* move the shortened doc into the tmp buffer */
184                 strncpy( tmp, encoded_body + found_at, len - found_at );
185                 /* move the tmp buffer back into the allocated space */
186                 memset( encoded_body, 0, len );
187                 strcpy( encoded_body, tmp );
188         }
189
190         return encoded_body;
191 }
192
193
194
195 void jid_get_username( const char* jid, char buf[] ) {
196
197         if( jid == NULL ) { return; }
198
199         /* find the @ and return whatever is in front of it */
200         int len = strlen( jid );
201         int i;
202         for( i = 0; i != len; i++ ) {
203                 if( jid[i] == 64 ) { /*ascii @*/
204                         strncpy( buf, jid, i );
205                         return;
206                 }
207         }
208 }
209
210
211 void jid_get_resource( const char* jid, char buf[])  {
212         if( jid == NULL ) { return; }
213         int len = strlen( jid );
214         int i;
215         for( i = 0; i!= len; i++ ) {
216                 if( jid[i] == 47 ) { /* ascii / */
217                         strncpy( buf, jid + i + 1, len - (i+1) );
218                 }
219         }
220 }
221
222 void set_msg_error( transport_message* msg, char* type, int err_code ) {
223
224         if( type != NULL && strlen( type ) > 0 ) {
225                 msg->error_type = safe_malloc( strlen(type)+1); 
226                 strcpy( msg->error_type, type );
227                 msg->error_code = err_code;
228         }
229         msg->is_error = 1;
230 }