]> code.citadel.org Git - citadel.git/blob - libCxClient/src/messages.c
Initial revision
[citadel.git] / libCxClient / src / messages.c
1 /**
2  ** libCxClient - Citadel/UX Extensible Client API
3  ** Copyright (c) 2000, Flaming Sword Productions
4  ** Copyright (c) 2001, The Citadel/UX Consortium
5  ** All Rights Reserved
6  **
7  ** Module: messages.o
8  ** Date: 2000-10-15
9  ** Last Revision: 2000-10-15
10  ** Description: Functions which manipulate (build) message lists.
11  ** CVS: $Id$
12  **/
13 #include        <stdio.h>
14 #include        <stdlib.h>
15 #include        <string.h>
16 #include        <stdarg.h>
17 #include        <CxClient.h>
18 #include        "autoconf.h"
19
20 /**
21  ** CxMsInfo(): Retrieve message information for all of the message id's listed inside
22  ** of a Message List.
23  **/
24 CXLIST          CxMsInfo(CXLIST msg_list) {
25 CXLIST          mp, messages = NULL;
26 char            buf[255], *from, *date, *subject;
27 int             rc;
28
29         DPF((DFA,"Retreiving information for all messages in 0x%08x",msg_list));
30
31         mp = msg_list;
32         while ( mp ) {
33                 sprintf(buf,"MSG0 %s|1",mp->data);
34                 CxClSend(buf);
35                 rc = CxClRecv(buf);
36                 if( CHECKRC(rc, RC_LISTING)) {
37                         from = date = subject = 0;
38                         do {
39
40                                 rc = CxClRecv(buf);
41                                 if(rc && strstr(buf,"from=")) {
42                                         DPF((DFA, "from: %s",buf));
43
44                                         from = (char *)CxMalloc(strlen(buf+5)+1);
45                                         strcpy(from, buf+5);
46
47                                 } else if(rc && strstr(buf,"time=")) {
48
49                                         DPF((DFA, "time: %s",buf));
50                                         date = (char *)CxMalloc(strlen(buf+5)+1);
51                                         strcpy(date, buf+5);
52                                 }
53
54                         } while(rc<0);
55
56                         if((from && *from) && (date && *date)) {
57                                 sprintf(buf,"%s|%s|%s",from,date,subject);
58                                 DPF((DFA, "insert-> %s",buf));
59
60                                 messages = (CXLIST) CxLlInsert(messages,buf);
61                                 DPF((DFA, "Freeing memory (temp vars)"));
62                                 if(subject) CxFree(subject);
63                                 if(from) CxFree(from);
64                                 if(date) CxFree(date);
65                         }
66                 }
67
68                 mp = mp->next;
69         }
70
71         return(messages);
72 }
73
74 /**
75  ** CxMsList(): Retrieve a list of messages in the current room.
76  **/
77 CXLIST          CxMsList() {
78 int             rc;
79 char            buf[255], *malleable;
80 CXLIST          msgs = NULL;
81
82         DPF((DFA,"Retrieving list of messages from the server."));
83
84         CxClSend("MSGS");
85         rc = CxClRecv( buf );
86
87         if( CHECKRC(rc, RC_LISTING) ) {
88
89                 do {
90                         rc = CxClRecv(buf);
91
92                         if(rc) {
93                                 malleable = (char *)CxMalloc(strlen(buf) + 1);
94                                 strcpy(malleable,buf);
95                                 DPF((DFA,"%s",malleable));
96
97                                 msgs = (CXLIST) CxLlInsert(msgs,malleable);
98                                 CxFree(malleable);
99                         }
100                 } while(rc < 0);
101
102                 return(msgs);
103         } else {
104                 return(NULL);
105         }
106 }
107
108 /**
109  ** CxMsLoad(): Retrieve a message from the server.  Expects a MESSAGE_ID, 
110  ** returns 0 on success, [err] on failure.
111  **
112  ** Argument:
113  **     preserve_newlines: Preserve newline delimiters in body text?
114  **
115  ** CLIENT MUST free(toret.body) MANUALLY!!!!
116  **/
117 int             CxMsLoad(const char *mid, int preserve_newlines, MESGINFO *toret) {
118 char            buf[255], *newline="\n";
119 int             rc, message_contents = 0, line_width;
120
121         DPF((DFA,"Loading message \"%s\"",mid));
122         toret->message_id = 0;
123         toret->author[0] = 0;
124         toret->rcpt[0] = 0;
125         toret->room[0] = 0;
126         toret->subject[0] = 0;
127
128         sprintf(buf,"MSG2 %s",mid);
129         CxClSend(buf);
130         rc = CxClRecv(buf);
131         if(CHECKRC(rc, RC_LISTING) ) {
132                 DPF((DFA,"RC_LISTING"));
133                 do {
134                         rc = CxClRecv(buf);
135                         if( rc ) {
136                                 if(buf[strlen(buf)-1]=='\r') 
137                                         buf[strlen(buf)-1]=0;
138
139                                 DPF((DFA,"[%d] buf: %s", rc, buf));
140
141                                 if(strstr(buf,"From:") && 
142                                         !message_contents) {
143                                         strcpy(toret->author, buf+5);
144
145                                 } else if((strstr(buf,"To:") == (char *)&buf) && 
146                                         !message_contents) {
147                                         strcpy(toret->rcpt, buf+3);
148
149                                 } else if(strstr(buf,"X-UIDL:")
150                                         && !message_contents) {
151                                         DPF((DFA,"Message ID: %s",buf+7));
152                                         toret->message_id = atoi(buf+7);
153
154                                 } else if(strstr(buf,"X-Citadel-Room:")
155                                         && !message_contents) {
156                                         DPF((DFA,"Room: %s",buf+15));
157                                         strcpy(toret->room, buf+15);
158                                         toret->room[
159                                                 strlen(toret->room)-1
160                                         ] = 0;
161
162                                 } else if(strstr(buf,"Subject:") 
163                                         && !message_contents) {
164                                         strcpy(toret->subject, buf+8);
165
166                                 } else if(strstr(buf,"Path:") 
167                                         && !message_contents) {
168                                         strcpy(toret->path, buf+5);
169
170                                 } else if(strstr(buf,"Node:") 
171                                         && !message_contents) {
172                                         strcpy(toret->node, buf+5);
173
174                                 } else if((strstr(buf,"Date:") == (char *)&buf) 
175                                         && !message_contents) {
176                                         strcpy(toret->date, buf+5);
177
178                                 } else if((buf[0] == 0) || (buf[0] == '\r') || 
179                                         message_contents) {
180                                         message_contents = 1;
181
182                                         /**
183                                          ** ugliness.  Load entire message.  Ick.
184                                          **/
185
186                                         do {
187                                                 rc = CxClRecv(buf);
188                                                 if(rc) {
189                                                         DPF((DFA,"%s",buf));
190
191                                                         line_width = strlen(buf);
192
193                                                         /**
194                                                          ** Start by stripping out the CR.
195                                                          **/
196                                                         *(strchr(buf,'\r')) = 0;
197                                                         if(preserve_newlines)
198                                                                 line_width+=strlen(newline);
199                                                         line_width++; /** Count NULL. **/
200
201                                                         if(!toret->body) {
202                                                                 toret->body = (char *)CxMalloc(
203                                                                         line_width
204                                                                 );
205
206                                                                 strcpy(toret->body, buf);
207
208                                                         } else {
209                                                                 toret->body = (char *) realloc(
210                                                                         toret->body, 
211                                                                         strlen(toret->body)
212                                                                         + line_width 
213                                                                 );
214
215                                                                 strcat(toret->body, buf);
216                                                         }
217
218                                                         /**
219                                                          ** If we are to preserve the newlines
220                                                          ** present in the message, then append
221                                                          ** a newline to the end of each line.
222                                                          **/
223                                                         if(preserve_newlines)
224                                                                 strcat(toret->body, newline);
225                                                 }
226                                         } while(rc<0);
227
228                                 }
229
230                         }
231                 } while(rc<0);
232                 DPF((DFA,"RC_LISTING completed."));
233         }
234
235         DPF((DFA,"[Return Data]"));
236         DPF((DFA,"toret->message_id: %d\n",toret->message_id));
237         DPF((DFA,"toret->author: %s\n",toret->author));
238         DPF((DFA,"toret->room: %s\n",toret->room));
239         DPF((DFA,"..."));
240
241         /**
242          ** If this message has been loaded, we succeeded.
243          **/
244         if(toret->message_id) {
245                 DPF((DFA,"Returning [SUCCESS]"));
246                 return(0);
247
248         /**
249          ** Otherwise, we failed.
250          **/
251         } else {
252                 DPF((DFA,"Returning [ENOMSG]"));
253                 return(1);
254         }
255 }
256
257 /**
258  ** CxMsSaveOk(): Verify that users can post to this room.  Returns 1 if posting is
259  ** allowed, 0 if posting is not allowed.
260  **/
261 int             CxMsSaveOk(const char *username) {
262 int             rc;
263 char            buf[255];
264
265         DPF((DFA,"Checking room for post permissions..."));
266         sprintf(buf,"ENT0 0|%s|0|0",username);
267         CxClSend(buf);
268         rc = CxClRecv(buf);
269         if(CHECKRC(rc, RC_OK) ) {
270                 DPF((DFA,"Ok for posting"));
271                 return(1);
272
273         } else {
274                 DPF((DFA,"Not Ok for posting [%d]",rc));
275                 return(0);
276         }
277
278         return(999);
279 }
280
281 /**
282  ** CxMsSave(): Save (post/send) a message to the server.  Expects a fully quantified
283  ** MESGINFO struct.  Returns 0 on success, [err] on failure.
284  ** [err]:
285  **  1: No room specified
286  **  2: Posting not allowed in this room.
287  **  3: Message rejected for unknown reasons.
288  **  ... tba
289  **/
290 int             CxMsSave(MESGINFO msg) {
291 int             rc;
292 char            buf[255];
293
294         DPF((DFA,"Preparing to save message to server..."));
295
296         if(!msg.room) {
297                 DPF((DFA,"Returning [ENOROOM]"));
298                 return(1);
299         }
300
301         DPF((DFA,"Checking for access..."));
302         sprintf(buf,"ENT0 0|%s|0|0",msg.rcpt);
303         CxClSend(buf);
304         rc = CxClRecv(buf);
305         DPF((DFA,"Server said [%s]",buf));
306
307         if( CHECKRC(rc, RC_OK)) {
308                 DPF((DFA,"Permission to save"));
309
310                 sprintf(buf,"ENT0 1|%s|0|4|",msg.rcpt);
311                 CxClSend(buf);
312
313                 rc = CxClRecv(buf);
314                 if( CHECKRC(rc, RC_SENDLIST)) {
315                         DPF((DFA,"Sending message to server..."));
316                         sprintf(buf, "From: %s", msg.author);
317                         CxClSend(buf);
318                         sprintf(buf, "To: %s", msg.rcpt);
319                         CxClSend(buf);
320                         sprintf(buf, "X-Mailer: libCxClient %s", CXREVISION);
321                         CxClSend(buf);
322                         sprintf(buf, "Subject: %s", msg.subject);
323                         CxClSend(buf);
324                         CxClSend("");
325                         CxClSend(msg.body);
326
327                         CxClSend("000");
328                         DPF((DFA,"Done!"));
329
330                         DPF((DFA,"Server accepted message"));
331                         return(0);
332                 }
333
334         } else {
335                 DPF((DFA,"No permission to save!"));
336                 return(2);
337         }
338
339         return(999);
340 }