]> code.citadel.org Git - citadel.git/blob - libCxClient/src/messages.c
6250157f1c0bf2768661377c4cb475479a662766
[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(int id, 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(id, buf);
35                 rc = CxClRecv(id, buf);
36                 if( CHECKRC(rc, RC_LISTING)) {
37                         from = date = subject = 0;
38                         do {
39
40                                 rc = CxClRecv(id, 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(int id, int list_type, int number_messages) {
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         switch( list_type ) {
85                 case(2):
86                         // MSGS LAST|%d
87                         break;
88
89                 case(1):
90                         CxClSend( id, "MSGS NEW");
91                         break;
92
93                 default:
94                         CxClSend( id, "MSGS");
95                         break;
96         }
97         rc = CxClRecv( id, buf );
98
99         if( CHECKRC(rc, RC_LISTING) ) {
100
101                 do {
102                         rc = CxClRecv(id, buf);
103
104                         if(rc) {
105                                 malleable = (char *)CxMalloc(strlen(buf) + 1);
106                                 strcpy(malleable,buf);
107                                 DPF((DFA,"%s",malleable));
108
109                                 msgs = (CXLIST) CxLlInsert(msgs,malleable);
110                                 CxFree(malleable);
111                         }
112                 } while(rc < 0);
113
114                 return(msgs);
115         } else {
116                 return(NULL);
117         }
118 }
119
120 /**
121  ** CxMsLoad(): Retrieve a message from the server.  Expects a MESSAGE_ID, 
122  ** returns 0 on success, [err] on failure.
123  **
124  ** Argument:
125  **     preserve_newlines: Preserve newline delimiters in body text?
126  **
127  ** CLIENT MUST free(toret.body) MANUALLY!!!!
128  **/
129 int             CxMsLoad(int id, unsigned long int mid, int preserve_newlines, MESGINFO *toret) {
130 char            buf[255], *newline="\n";
131 int             rc, message_contents = 0, line_width;
132
133         DPF((DFA,"Loading message \"%ld\"",mid));
134         toret->message_id = 0;
135         toret->author[0] = 0;
136         toret->rcpt[0] = 0;
137         toret->room[0] = 0;
138         toret->subject[0] = 0;
139
140         sprintf(buf,"MSG2 %ld",mid);
141         CxClSend(id, buf);
142         rc = CxClRecv(id, buf);
143         if(CHECKRC(rc, RC_LISTING) ) {
144                 DPF((DFA,"RC_LISTING"));
145                 do {
146                         rc = CxClRecv(id, buf);
147                         if( rc ) {
148                                 if(buf[strlen(buf)-1]=='\r') 
149                                         buf[strlen(buf)-1]=0;
150
151                                 DPF((DFA,"[%d] buf: %s", rc, buf));
152
153                                 if(strstr(buf,"From:") && 
154                                         !message_contents) {
155                                         strcpy(toret->author, buf+5);
156
157                                 } else if((strstr(buf,"To:") == (char *)&buf) && 
158                                         !message_contents) {
159                                         strcpy(toret->rcpt, buf+3);
160
161                                 } else if(strstr(buf,"X-UIDL:")
162                                         && !message_contents) {
163                                         DPF((DFA,"Message ID: %s",buf+7));
164                                         toret->message_id = atoi(buf+7);
165
166                                 } else if(strstr(buf,"X-Citadel-Room:")
167                                         && !message_contents) {
168                                         DPF((DFA,"Room: %s",buf+15));
169                                         strcpy(toret->room, buf+15);
170                                         toret->room[
171                                                 strlen(toret->room)-1
172                                         ] = 0;
173
174                                 } else if(strstr(buf,"Subject:") 
175                                         && !message_contents) {
176                                         strcpy(toret->subject, buf+8);
177
178                                 } else if(strstr(buf,"Path:") 
179                                         && !message_contents) {
180                                         strcpy(toret->path, buf+5);
181
182                                 } else if(strstr(buf,"Node:") 
183                                         && !message_contents) {
184                                         strcpy(toret->node, buf+5);
185
186                                 } else if((strstr(buf,"Date:") == (char *)&buf) 
187                                         && !message_contents) {
188                                         strcpy(toret->date, buf+5);
189
190                                 } else if((buf[0] == 0) || (buf[0] == '\r') || 
191                                         message_contents) {
192                                         message_contents = 1;
193
194                                         /**
195                                          ** ugliness.  Load entire message.  Ick.
196                                          **/
197
198                                         do {
199                                                 rc = CxClRecv(id, buf);
200                                                 if(rc) {
201                                                         DPF((DFA,"%s",buf));
202
203                                                         line_width = strlen(buf);
204
205                                                         /**
206                                                          ** Start by stripping out the CR.
207                                                          **/
208                                                         *(strchr(buf,'\r')) = 0;
209                                                         if(preserve_newlines)
210                                                                 line_width+=strlen(newline);
211                                                         line_width++; /** Count NULL. **/
212
213                                                         if(!toret->body) {
214                                                                 toret->body = (char *)CxMalloc(
215                                                                         line_width
216                                                                 );
217
218                                                                 strcpy(toret->body, buf);
219
220                                                         } else {
221                                                                 toret->body = (char *) realloc(
222                                                                         toret->body, 
223                                                                         strlen(toret->body)
224                                                                         + line_width 
225                                                                 );
226
227                                                                 strcat(toret->body, buf);
228                                                         }
229
230                                                         /**
231                                                          ** If we are to preserve the newlines
232                                                          ** present in the message, then append
233                                                          ** a newline to the end of each line.
234                                                          **/
235                                                         if(preserve_newlines)
236                                                                 strcat(toret->body, newline);
237                                                 }
238                                         } while(rc<0);
239
240                                 }
241
242                         }
243                 } while(rc<0);
244                 DPF((DFA,"RC_LISTING completed."));
245         }
246
247         DPF((DFA,"[Return Data]"));
248         DPF((DFA,"toret->message_id: %d\n",toret->message_id));
249         DPF((DFA,"toret->author: %s\n",toret->author));
250         DPF((DFA,"toret->room: %s\n",toret->room));
251         DPF((DFA,"..."));
252
253         /**
254          ** If this message has been loaded, we succeeded.
255          **/
256         if(toret->message_id) {
257                 DPF((DFA,"Returning [SUCCESS]"));
258                 return(0);
259
260         /**
261          ** Otherwise, we failed.
262          **/
263         } else {
264                 DPF((DFA,"Returning [ENOMSG]"));
265                 return(1);
266         }
267 }
268
269 /**
270  ** CxMsSaveOk(): Verify that users can post to this room.  Returns 1 if posting is
271  ** allowed, 0 if posting is not allowed.
272  **/
273 int             CxMsSaveOk(int id, const char *username) {
274 int             rc;
275 char            buf[255];
276
277         DPF((DFA,"Checking room for post permissions..."));
278         sprintf(buf,"ENT0 0|%s|0|0",username);
279         CxClSend(id, buf);
280         rc = CxClRecv(id, buf);
281         if(CHECKRC(rc, RC_OK) ) {
282                 DPF((DFA,"Ok for posting"));
283                 return(1);
284
285         } else {
286                 DPF((DFA,"Not Ok for posting [%d]",rc));
287                 return(0);
288         }
289
290         return(999);
291 }
292
293 /**
294  ** CxMsSave(): Save (post/send) a message to the server.  Expects a fully quantified
295  ** MESGINFO struct.  Returns 0 on success, [err] on failure.
296  ** [err]:
297  **  1: No room specified
298  **  2: Posting not allowed in this room.
299  **  3: Message rejected for unknown reasons.
300  **  ... tba
301  **/
302 int             CxMsSave(int id, MESGINFO msg) {
303 int             rc;
304 char            buf[255];
305
306         DPF((DFA,"Preparing to save message to server..."));
307
308         if(!msg.room) {
309                 DPF((DFA,"Returning [ENOROOM]"));
310                 return(1);
311         }
312
313         DPF((DFA,"Checking for access..."));
314         sprintf(buf,"ENT0 0|%s|0|0",msg.rcpt);
315         CxClSend(id, buf);
316         rc = CxClRecv(id, buf);
317         DPF((DFA,"Server said [%s]",buf));
318
319         if( CHECKRC(rc, RC_OK)) {
320                 DPF((DFA,"Permission to save"));
321
322                 sprintf(buf,"ENT0 1|%s|0|4|",msg.rcpt);
323                 CxClSend(id, buf);
324
325                 rc = CxClRecv(id, buf);
326                 if( CHECKRC(rc, RC_SENDLIST)) {
327                         DPF((DFA,"Sending message to server..."));
328                         sprintf(buf, "From: %s", msg.author);
329                         CxClSend(id, buf);
330                         sprintf(buf, "To: %s", msg.rcpt);
331                         CxClSend(id, buf);
332                         sprintf(buf, "X-Mailer: libCxClient %s", CXREVISION);
333                         CxClSend(id, buf);
334                         sprintf(buf, "Subject: %s", msg.subject);
335                         CxClSend(id, buf);
336                         CxClSend(id, "");
337                         CxClSend(id, msg.body);
338
339                         CxClSend(id, "000");
340                         DPF((DFA,"Done!"));
341
342                         DPF((DFA,"Server accepted message"));
343                         return(0);
344                 }
345
346         } else {
347                 DPF((DFA,"No permission to save!"));
348                 return(2);
349         }
350
351         return(999);
352 }
353
354 /**
355  ** CxMsMark(): Mark message(s) as read.
356  **/
357 void            CxMsMark( int id, long unsigned int msgid ) {
358 char            buf[1024];
359 int             rc;
360
361         DPF((DFA, "Marking message %s read.", msgid));
362
363         if( msgid == MSGS_ALL ) {
364                 sprintf( buf, "SLRP highest" );
365
366         } else {
367                 sprintf( buf, "SLRP %ld", msgid );
368         }
369
370         CxClSend( id, buf );
371         rc = CxClRecv( id, buf );
372
373         if( rc == RC_OK ) {
374                 DPF((DFA, "Done."));
375
376         } else {
377                 DPF((DFA, "Failed."));
378         }
379 }