1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           xtmMsgBase
4 --
5 --  Project:          Xdiary
6 --  System:           xtm - X Desktop Calendar
7 --    Subsystem:      <>
8 --    Function block: <>
9 --
10 --  Description:
11 --    Basic XDiary message routines.
12 --
13 --  Filename:         xtmMsgBase.c
14 --
15 --  Authors:          Roger Larsson, Ulrika Bornetun
16 --  Creation date:    1991-04-01
17 --
18 --
19 --  (C) Copyright Ulrika Bornetun, Roger Larsson (1995)
20 --      All rights reserved
21 --
22 --  Permission to use, copy, modify, and distribute this software and its
23 --  documentation for any purpose and without fee is hereby granted,
24 --  provided that the above copyright notice appear in all copies. Ulrika
25 --  Bornetun and Roger Larsson make no representations about the usability
26 --  of this software for any purpose. It is provided "as is" without express
27 --  or implied warranty.
28 ----------------------------------------------------------------------------*/
29 
30 /* SCCS module identifier. */
31 static char SCCSID[] = "@(#) Module: xtmMsgBase.c, Version: 1.1, Date: 95/02/18 15:52:32";
32 
33 
34 /*----------------------------------------------------------------------------
35 --  Include files
36 ----------------------------------------------------------------------------*/
37 
38 #include <pwd.h>
39 #include <string.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <ctype.h>
43 #include <unistd.h>
44 
45 #include <X11/Intrinsic.h>
46 
47 #include <Xm/Xm.h>
48 
49 #include "System.h"
50 #include "DirList.h"
51 #include "Message.h"
52 #include "TimDate.h"
53 
54 #include "msgXdiary.h"
55 #include "xtmGlobal.h"
56 #include "xtmCalDb.h"
57 #include "xtmCustBase.h"
58 #include "xtmDbTools.h"
59 #include "xtmFormat.h"
60 #include "xtmGroupDb.h"
61 #include "xitError.h"
62 #include "xitTools.h"
63 #include "xtmMsgBase.h"
64 #include "xtmLocate.h"
65 
66 /*----------------------------------------------------------------------------
67 --  Macro definitions
68 ----------------------------------------------------------------------------*/
69 
70 #define max( a, b )  (a < b ? b : a )
71 
72 /* Alloc memory size in bytes. */
73 #define SEGMENT_SIZE          1000
74 
75 
76 /*----------------------------------------------------------------------------
77 --  Type declarations
78 ----------------------------------------------------------------------------*/
79 
80 
81 /*----------------------------------------------------------------------------
82 --  Global definitions
83 ----------------------------------------------------------------------------*/
84 
85 /* Name of module. */
86 static char  *module_name = "xtmMsgBase";
87 
88 
89 /*----------------------------------------------------------------------------
90 --  Function prototypes
91 ----------------------------------------------------------------------------*/
92 
93 static Boolean
94   sendInternalMessage( XTM_GL_BASE_DATA_REF  appl_data_ref,
95                        Widget                mainW,
96                        char                  *user_ref,
97                        char                  *directory,
98                        TIM_TIME_REF          entry_date,
99                        TIM_TIME_REF          entry_time,
100                        int                   duration,
101                        char                  *message,
102                        char                  *text );
103 
104 static Boolean
105   sendMailMessage( XTM_GL_BASE_DATA_REF  appl_data_ref,
106                    Widget                mainW,
107                    char                  *mail_address,
108                    TIM_TIME_REF          entry_date,
109                    TIM_TIME_REF          entry_time,
110                    int                   duration,
111                    char                  *message,
112                    char                  *text );
113 
114 
115 
116 /*----------------------------------------------------------------------------
117 --  Functions
118 ----------------------------------------------------------------------------*/
119 
120 Boolean
xtmMbSendMessage(XTM_GL_BASE_DATA_REF appl_data_ref,Widget mainW,int msg_to_count,XmStringTable msg_to,Boolean only_mail,Boolean mail_fail,TIM_TIME_REF entry_date,TIM_TIME_REF entry_time,int duration,char * message,char * text)121   xtmMbSendMessage( XTM_GL_BASE_DATA_REF  appl_data_ref,
122                     Widget                mainW,
123                     int                   msg_to_count,
124                     XmStringTable         msg_to,
125                     Boolean               only_mail,
126                     Boolean               mail_fail,
127                     TIM_TIME_REF          entry_date,
128                     TIM_TIME_REF          entry_time,
129                     int                   duration,
130                     char                  *message,
131                     char                  *text )
132 {
133 
134   /* Type definitions. */
135   typedef enum { MESSAGE, MAIL } MESSAGE_TYPE;
136   typedef enum { NONE, CALENDAR, GROUP } RECIPIENT_TYPE;
137 
138   /* Variables. */
139   Boolean         ok;
140   int             alloc_size;
141   int             index;
142   char            recipient_buffer[ 250 ];
143   char            *char_ref;
144   char            *recipients;
145   char            *recipient_ref;
146   MESSAGE_TYPE    message_type;
147   RECIPIENT_TYPE  recipient_type;
148   TIM_TIME_REF    default_date;
149   TIM_TIME_REF    default_time;
150   XTM_GD_ENTRY    group_info;
151 
152 
153   /* Code. */
154 
155   default_time = TimMakeTime( 1970, 1, 1, 12, 0, 0 );
156   default_date = TimLocalTime( TimMakeTimeNow() );
157   default_date = TimMakeTime(  TimIndexOfYear(  default_date ),
158                                TimIndexOfMonth( default_date ),
159                                TimIndexOfDay(   default_date ),
160                                0, 0, 0 );
161 
162   if( entry_date <= 0 )
163     entry_date = default_date;
164 
165   if( entry_time <= 0 )
166     entry_time = default_time;
167 
168 
169   /* Buffer for recipients. */
170   recipients  = (char *) SysMalloc( SEGMENT_SIZE );
171   alloc_size  = SEGMENT_SIZE;
172   *recipients = '\0';
173 
174 
175   /* Expand databases, groups and mail addresses. */
176   index = 0;
177 
178   while( index < msg_to_count ) {
179 
180     char_ref = xitStringGetString( *(msg_to + index), CS );
181 
182     sscanf( char_ref, "%s", recipient_buffer );
183     SysFree( char_ref );
184 
185     recipient_ref = recipient_buffer;
186 
187 
188     /* Find the type of recipient. */
189     recipient_type = CALENDAR;
190 
191     /* A group? */
192     ok = xtmGdFetchNamedGroup( appl_data_ref -> custom_data -> group_db_handle,
193                                recipient_ref, &group_info );
194 
195     if( ok ) {
196       recipient_type = GROUP;
197 
198       if( group_info.members != NULL )
199         recipient_ref = group_info.members;
200       else
201         recipient_type = NONE;
202     }
203 
204 
205     /* Save the recipient(s). */
206     if( recipient_type != NONE ) {
207 
208       int  append_size;
209       int  extend_size;
210 
211       append_size = strlen( recipient_ref ) + 5;
212 
213       /* Any space left? */
214       if( strlen( recipients ) + append_size >= alloc_size ) {
215         extend_size = max( append_size, SEGMENT_SIZE );
216 
217         alloc_size = alloc_size + extend_size + 5;
218         recipients = (char *) SysRealloc( recipients, alloc_size );
219       }
220 
221       strcat( recipients, recipient_ref );
222       strcat( recipients, " " );
223 
224       if( recipient_type == GROUP )
225         SysFree( recipient_ref );
226 
227     } /* if */
228 
229     index++;
230 
231   } /* while */
232 
233 
234   /* Start to send messages/mails. */
235   recipient_ref = recipients;
236 
237   do {
238 
239     int              char_read;
240     char             location[ XTM_GL_MAX_DIR + 1 ];
241     char             *directory_ref;
242     char             *mail_address;
243     XTM_CD_CAL_INFO  db_info;
244 
245     while( isspace( *recipient_ref ) )
246       recipient_ref++;
247 
248     if( *recipient_ref == '\0' )
249       break;
250 
251     char_read = strlen( recipient_ref );
252     sscanf( recipient_ref, "%s%n", recipient_buffer, &char_read );
253     recipient_ref = recipient_ref + char_read;
254 
255 
256     /* Where do we send the message? */
257     mail_address  = recipient_buffer;
258     directory_ref = NULL;
259 
260     /* Fetch user diary DB directory. */
261     ok = xtmCdFetchNamedDb( appl_data_ref -> custom_data -> cal_db_handle,
262                             recipient_buffer,
263                             &db_info, NULL );
264 
265     /* A 'real' calendar. */
266     if( ok ) {
267       directory_ref = db_info.directory;
268 
269       if( strlen( db_info.mail_address ) > 0 )
270           mail_address = db_info.mail_address;
271 
272     /* Try to locate the calendar. */
273     } else {
274       ok = xtmLcLocateCalendar(
275              mainW, recipient_buffer,
276              appl_data_ref -> custom_data -> find_location_script,
277              location, sizeof( location ) );
278 
279       if( ok )
280         directory_ref = location;
281 
282     } /* if */
283 
284 
285     /* What kind of message do we send? */
286     if( only_mail )
287       message_type = MAIL;
288     else
289       message_type = MESSAGE;
290 
291 
292     /* Try internal message. */
293     if( message_type == MESSAGE ) {
294 
295       ok = sendInternalMessage( appl_data_ref, mainW,
296                                 recipient_buffer, directory_ref,
297                                 entry_date, entry_time, duration,
298                                 message, text );
299 
300       /* If we failed, try normal mail message? */
301       if( ! ok && mail_fail )
302         message_type = MAIL;
303 
304     } /* if */
305 
306 
307     /* Try mail message. */
308     if( message_type == MAIL )
309       ok = sendMailMessage( appl_data_ref, mainW,
310                             mail_address,
311                             entry_date, entry_time, duration,
312                             message, text );
313 
314   } while( True );
315 
316 
317   /* Free occupied memory. */
318   SysFree( recipients );
319 
320 
321   return( True );
322 
323 } /* xtmMbSendMessage */
324 
325 
326 /*----------------------------------------------------------------------*/
327 
328 static Boolean
sendInternalMessage(XTM_GL_BASE_DATA_REF appl_data_ref,Widget mainW,char * user_ref,char * directory,TIM_TIME_REF entry_date,TIM_TIME_REF entry_time,int duration,char * message,char * text)329   sendInternalMessage( XTM_GL_BASE_DATA_REF  appl_data_ref,
330                        Widget                mainW,
331                        char                  *user_ref,
332                        char                  *directory,
333                        TIM_TIME_REF          entry_date,
334                        TIM_TIME_REF          entry_time,
335                        int                   duration,
336                        char                  *message,
337                        char                  *text )
338 {
339 
340   /* Variables. */
341   UINT32             operations;
342   XTM_DB_MESSAGE_DEF msg;
343   XTM_DB_STATUS      db_status;
344   struct passwd      *password_ref;
345 
346 
347   /* Code. */
348 
349   if( directory == NULL || strlen( directory ) == 0 )
350     return( False );
351 
352   /* Fetch the database permissions. */
353   xtmDbCheckDbOperations( directory, True, &operations );
354   if( ! flagIsSet( operations, XTM_DB_FLAG_MODE_MSG ) )
355     return( False );
356 
357 
358   /* Construct the message record. */
359   msg.version        = XTM_DB_MESSAGE_VERSION;
360   msg.flags          = 0;
361   msg.date           = (UINT32) entry_date;
362   msg.time           = (UINT32) entry_time;
363   msg.duration       = (UINT16) duration;
364   msg.message_length = (UINT16) strlen( message );
365   msg.text_length    = (UINT16) strlen( text );
366 
367 
368   /* Name of sender. */
369   password_ref = getpwuid( getuid() );
370   if( password_ref != NULL )
371     strncpy( msg.from, password_ref -> pw_name, 20 );
372   else
373     strcpy( msg.from, "---" );
374   msg.from[ 20 ] = '\0';
375 
376 
377   /* Send the message. */
378   db_status = xtmDbInsertMessage( directory, &msg, message, text );
379   if( db_status != XTM_DB_OK )
380     return( False );
381 
382 
383   return( True);
384 
385 } /* sendInternalMessage */
386 
387 
388 /*----------------------------------------------------------------------*/
389 
390 static Boolean
sendMailMessage(XTM_GL_BASE_DATA_REF appl_data_ref,Widget mainW,char * mail_address,TIM_TIME_REF entry_date,TIM_TIME_REF entry_time,int duration,char * message,char * text)391   sendMailMessage( XTM_GL_BASE_DATA_REF  appl_data_ref,
392                    Widget                mainW,
393                    char                  *mail_address,
394                    TIM_TIME_REF          entry_date,
395                    TIM_TIME_REF          entry_time,
396                    int                   duration,
397                    char                  *message,
398                    char                  *text )
399 {
400 
401   /* Variables. */
402   char  buffer1[ 41 ];
403   char  buffer2[ 41 ];
404   char  command[ 100 ];
405   char  duration_buffer[ 20 ];
406   char  time_buffer[ 40 ];
407   char  *char_ref;
408   FILE  *file_ref;
409 
410 
411   /* Code. */
412 
413   /* The subject is the first 40 characters in the first line. */
414   strncpy( buffer1, message, 40 );
415   buffer1[ 40 ] = '\0';
416 
417   char_ref = strchr( buffer1, '\n' );
418   if( char_ref != NULL )
419     *char_ref = '\0';
420 
421   if( strlen( buffer1 ) == 0 )
422     strcpy( buffer1, "---" );
423 
424   /* Construct command. */
425   sprintf( command, "mail -s '%s' %s", buffer1, mail_address );
426 
427 
428   /* Make the entry time field. */
429   xtmFoFormatDate( entry_date, buffer1, sizeof( buffer1 ) );
430   xtmFoFormatTime( entry_time, buffer2, sizeof( buffer2 ) );
431 
432   sprintf( time_buffer, "%s %s", buffer1, buffer2 );
433 
434 
435   /* Make the duration field. */
436   sprintf( duration_buffer, "%2d:%02d", duration / 60, duration % 60 );
437 
438 
439   /* Open pipe to send mail. */
440   file_ref = (FILE *) popen( command, "w" );
441   if( file_ref == NULL )
442     return( False );
443 
444 
445   /* Send the mail. */
446   if( entry_date == 0 )
447     fprintf( file_ref, "%s\n\n%s", message, text );
448   else
449     fprintf( file_ref, msgGetText( MXDI_ENTRY_MAIL_MESSAGE ),
450              message, time_buffer, duration_buffer, text );
451 
452 
453   /* That's it. */
454 #ifdef XD_HAS_NO_WAITPID
455   fclose( file_ref );
456 #else
457   pclose( file_ref );
458 #endif
459 
460   return( True );
461 
462 } /* sendMailMessage */
463 
464 
465 
466 
467