x400_msrcv.c
1 /* Copyright (c) 2003-2014, Isode Limited, London, England.
2  * All rights reserved.
3  *
4  * Acquisition and use of this software and related materials for any
5  * purpose requires a written licence agreement from Isode Limited,
6  * or a written licence from an organisation licenced by Isode Limited
7  * to grant such a licence.
8  *
9  */
10 
11 /*
12  *
13  * Simple example program for receiving a message from a store.
14  */
15 #include <stdio.h>
16 #include <stdlib.h>
17 #ifndef _WIN32
18 #include <unistd.h>
19 #endif
20 #include <x400_msapi.h>
21 #include <amhs_att.h>
22 #include <seclabel_api.h> /* For security labels */
23 #include "example.h"
24 #include "ms_example.h"
25 
26 static char *optstr = "u371m:d:p:w:M:D:P:W:";
27 
28 static void usage(void);
29 
30 static int get_msg (
31  struct X400msSession *sp
32 );
33 
37 int
38 main(
39  int argc,
40  char **argv)
41 {
42  char buffer[BUFSIZ];
43  char pa[BUFSIZ];
44  char orn[BUFSIZ];
45  int status;
46  int nummsg;
47  int nummsg_ready;
48  struct X400msSession *sp;
49  int contype;
50  char *def_oraddr;
51  char *def_dn;
52  char *def_pa;
53  /* period to pass into X400msWait() */
54  int ms_timeout_period = 10;
55  /* number of timeouts from X400msWait() before exiting */
56  # define NUM_MSWAIT_TIMEOUTS 10
57  int max_timeouts = NUM_MSWAIT_TIMEOUTS;
58 
59  /* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
60  status = X400InitializeLogging(argv[0], "x400api.xml");
61  if (status != X400_E_NOERROR) {
62  fprintf(stderr, "Failed to initialize logging, %s\n", X400msError(status));
63  } else {
64  printf("Initialized logging from file x400api.xml\n");
65  }
66 
67  if (get_args(argc, argv, optstr)) {
68  usage();
69  exit(-1);
70  }
71 
72  printf("Connection type (0 = P7, 1 = P3 submit only, 2 = P3 both directions) [%d]: ", x400_contype);
73  contype = ic_fgetc(x400_contype, stdin);
74  if (contype != 10)
75  ic_fgetc(x400_contype, stdin);
76 
77  if ( contype < '0' || '2' < contype )
78  contype = x400_contype;
79  else
80  contype -= '0';
81 
82  if (contype == 0) {
83  def_oraddr = x400_ms_user_addr;
84  def_dn = x400_ms_user_dn;
85  def_pa = x400_ms_presentation_address;
86  }
87  else {
88  def_oraddr = x400_mta_user_addr;
89  def_dn = x400_mta_user_dn;
90  def_pa = x400_mta_presentation_address;
91  }
92 
93  printf("Your ORAddress [%s] > ", def_oraddr);
94  ic_fgets(orn, sizeof orn, stdin);
95 
96  if (orn[strlen(orn) - 1] == '\n')
97  orn[strlen(orn) - 1] = '\0';
98 
99  if (orn[0] == '\0')
100  strcpy(orn, def_oraddr);
101 
102  /* Prompt for password; note: reflected. */
103  printf("Password [%s]: ",
104  contype == 0 ? x400_p7_password : x400_p3_password);
105  if (ic_fgets(buffer, sizeof buffer, stdin) == NULL)
106  exit(1);
107 
108  if (buffer[strlen(buffer) - 1] == '\n')
109  buffer[strlen(buffer) - 1] = '\0';
110  if (buffer[0] == '\0')
111  strcpy(buffer, contype == 0 ? x400_p7_password : x400_p3_password);
112 
113  printf("Presentation Address [%s] > ", def_pa);
114  ic_fgets(pa, sizeof pa, stdin);
115 
116  if (pa[strlen(pa) - 1] == '\n')
117  pa[strlen(pa) - 1] = '\0';
118 
119  if (pa[0] == '\0')
120  strcpy(pa, def_pa);
121 
122  if (talking_to_marben_ms)
124 
125  status = X400msOpen(contype, orn, def_dn, buffer, pa, &nummsg, &sp);
126  if (status != X400_E_NOERROR) {
127  fprintf(stderr, "Error in Open: %s\n", X400msError(status));
128  exit(status);
129  }
130 
131  if (talking_to_marben_ms)
133 
134 #ifdef USING_ALERTS
135  /* If we register the alert auto-action, we will get an alert indication
136  when a message is delivered. So there is no need to poll at
137  short intervals within X400ms_Wait - we can do a slow background
138  poll and rely on the Alert indication to wake the code up instead */
140 #endif
141 
142 #ifdef WANT_SESSION_SPECIFIC_LOGGING
143  /* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
144  X400msSetStrDefault(sp, X400_S_LOG_CONFIGURATION_FILE, "x400api.xml", 0);
145 #endif
146 
148 
149  if (contype == 0) {
150 #ifdef WANT_AUTOFORWARDING
151  struct X400msAutoActionParameter *aa_param;
152 
153  /* Register an Autoforwarding Autoaction. */
154  aa_param = X400msNewAutoActionParameter();
155 
156  /* Add mandatory things to AutoAction parameter for auto-forwarding:
157  i.e. recipient address */
158  X400RecipNew(0, &rp);
159 
160  X400RecipAddStrParam(rp, X400_S_OR_ADDRESS, def_oraddr,
161  strlen(def_oraddr));
162 
164 
167  "AF contentid", -1);
168 
170 
173  1);
174 
177  1);
178 
181  1);
182 
184 
187  "This message was autoforwarded",
188  -1);
189 
192  "This is a cover note", -1);
193 
196  "AutoForwarded:", -1);
197 
199  4, aa_param);
200  if (status != X400_E_NOERROR) {
201  fprintf(stderr,
202  "Error in RegisterAutoAction: %s\n", X400msError(status));
203  /* tidily close the session */
204  (void) X400msClose(sp);
205  exit(status);
206  }
207  printf("Registered AutoForwarding autoaction (id = 4) OK\n");
209 #endif
210 
211 #ifdef USING_ALERTS
212  /* No parameter needed for Alert autoaction - we do not support
213  configuration of requested-attributes in this API yet. */
214  status = X400msRegisterAutoAction(sp, X400_AUTO_ALERT, 9, NULL);
215  if (status != X400_E_NOERROR) {
216  fprintf(stderr, "Error in RegisterAutoAction: %s\n",
217  X400msError(status));
218  /* tidily close the session */
219  (void) X400msClose(sp);
220  exit(status);
221  }
222  printf("Registered AutoAlert autoaction (id = 9) OK\n");
223 #endif
224 
225  /* Just test the register and deregister functions */
226  status = X400msRegisterAutoAction(sp, X400_AUTO_ALERT, 10, NULL);
227  if (status != X400_E_NOERROR) {
228  fprintf(stderr, "Error in RegisterAutoAction: %s\n",
229  X400msError(status));
230  /* tidily close the session */
231  (void) X400msClose(sp);
232  exit(status);
233  }
234  printf("Registered AutoAlert autoaction (id = 10) OK\n");
235 
236  /* Lets do a deregistration of the action we just registered */
238  if (status != X400_E_NOERROR) {
239  fprintf(stderr, "Error in DeregisterAutoAction: %s\n",
240  X400msError(status));
241  /* tidily close the session */
242  (void) X400msClose(sp);
243  exit(status);
244  }
245  printf("Deregistered AutoAlert autoaction (id = 10) OK\n");
246  }
247 
248  ms_timeout_period = 20;
249 
250  if (nummsg == 0) {
251  if (ms_timeout_period == 0) {
252  printf ("\n\nno messages - looping in msWait(%d) .....\n",
253  ms_timeout_period);
254  } else {
255  printf ("\n\nno messages - calling msWait(%d) .....\n",
256  ms_timeout_period);
257  }
258  } else {
259  printf("%d messages waiting\n", nummsg);
260  }
261 
262  while (1) {
263  /* Using P3
264  * - if ms_timeout_period > 0, wait once then break
265  * - if ms_timeout_period == 0, loop through NUM_MSWAIT_TIMEOUTS
266  * times, then break.
267  */
268  status = X400msWait(sp, ms_timeout_period, &nummsg_ready);
269  if (status == X400_E_NOERROR) {
270  printf("====== Getting next msg ======= (%d)\n", nummsg_ready);
271  (void) get_msg(sp);
272  max_timeouts = NUM_MSWAIT_TIMEOUTS;
273  } else {
274  if (status != X400_E_TIMED_OUT) {
275  /* tidily close the session */
276  fprintf(stderr, "X400msWait returned error: %s\n",
277  X400msError(status));
278  status = X400msClose(sp);
279  exit(status);
280  }
281  /* printf("X400msWait returned timeout\n"); */
282  sleep(1);
283  if (max_timeouts-- == 0)
284  break;
285  }
286  if (ms_timeout_period != 0)
287  break;
288  }
289 
290  status = X400msClose(sp);
291  return(status);
292 }
293 
294 static int get_msg (
295  struct X400msSession *sp
296 )
297 {
298  int type;
299  int seqn;
300  int status;
301  struct X400msMessage *mp;
302  char c;
303  size_t retlen;
304  char *buf = NULL;
305  char *databuf = &c;
306 
307  printf("Getting message\n");
308  status = X400msMsgGet(sp, 0, &mp, &type, &seqn);
309  switch (status) {
310  case X400_E_NOERROR:
311  fprintf(stderr, "MsgGet successfully got message\n");
312  break;
313  default :
314  fprintf(stderr, "Error from MsgGet: %s\n", X400msError(status));
315  /* tidily close the session */
316  status = X400msClose(sp);
317  exit(status);
318  break;
319  }
320 
321  status = print_msg(mp, type);
322  if (status != X400_E_NOERROR) {
323  (void) X400msMsgDelete(mp, 0);
324  X400msClose(sp);
325  exit(status);
326  }
327 
328  /* Get binary representation and store to file */
329 
330  /* First pass to find out how big it needs to be */
331  status = X400msMsgGetRaw(sp, mp, databuf, 0, &retlen);
332  if (status != X400_E_NOSPACE) {
333  fprintf(stderr, "Failed to get raw message length: error %d\n", status);
334  } else {
335  struct X400msMessage *newmsg;
336  int newtype;
337 
338  databuf = buf = (char *)malloc(retlen);
339  printf("Data buffer length required = %d\n", (int)retlen);
340  status = X400msMsgGetRaw(sp, mp, databuf, retlen, &retlen);
341  if (status != X400_E_NOERROR) {
342  fprintf(stderr, "Failed to get raw message: error %d\n", status);
343  } else {
344  /* Dump to file */
345  FILE *fd = fopen("message.dump", "w");
346  if (fd == NULL) {
347  fprintf(stderr, "Failed to open file message.dump\n");
348  } else {
349  if (fwrite(databuf, 1, retlen, fd) < retlen) {
350  fprintf(stderr, "Failed to write message to file message.dump\n");
351  } else {
352  fprintf(stdout, "Dumped message to file message.dump\n");
353  }
354  fclose(fd);
355  }
356  }
357 
358  /* And try to reconstruct message from bytes */
359  status = X400msMsgFromRaw(sp, databuf, retlen, &newmsg, &newtype);
360  if (status != X400_E_NOERROR) {
361  fprintf(stderr, "Failed to create message from bytes: error %d\n", status);
362  }
363 
364  printf("************************** Printing cached message ************************\n");
365  print_msg(newmsg, newtype);
366  if (buf != NULL)
367  free(buf);
368 
369  X400msMsgDelete(newmsg, 0);
370  }
371 
372  /* Deletes message in message store as well as internal copy */
373  printf("\n+++ got message - deleting it and returning+++\n");
374  status = X400msMsgDelete(mp, 0);
375 
376  return status;
377 }
378 
379 
380 
381 static void usage(void) {
382  printf("usage: %s\n", optstr);
383  printf("\t where:\n");
384  printf("\t -u : Don't prompt to override defaults \n");
385  printf("\t -3 : Use P3 connection \n");
386  printf("\t -7 : Use P7 connection \n");
387  printf("\t -m : OR Address in P7 bind arg \n");
388  printf("\t -d : DN in P7 bind arg \n");
389  printf("\t -p : Presentation Address of P7 Store \n");
390  printf("\t -w : P7 password of P7 user \n");
391  printf("\t -M : OR Address in P3 bind arg \n");
392  printf("\t -D : DN in P3 bind arg \n");
393  printf("\t -P : Presentation Address of P3 server\n");
394  printf("\t -W : P3 password of P3 user \n");
395  return;
396 }
397 
void X400msFreeAutoActionParameter(struct X400msAutoActionParameter *aa_param)
Free an autoaction parameter.
#define X400_S_COVER_NOTE
Definition: x400_att.h:1241
struct X400msAutoActionParameter * X400msNewAutoActionParameter(void)
Create a new (empty) autoaction parameter structure.
#define X400_N_IMPLICIT_CONVERSION_PROHIBITED
Definition: x400_att.h:430
int X400msRegisterAutoAction(struct X400msSession *sp, int type, int id, struct X400msAutoActionParameter *aa_param)
Register an autoaction with the Message Store.
#define X400_S_LOG_CONFIGURATION_FILE
Definition: x400_att.h:1091
int X400msSetStrDefault(struct X400msSession *sp, int paramtype, const char *value, size_t length)
Set a default string parameter value in a session.
int X400msAutoActionParameterAddStrParam(struct X400msAutoActionParameter *aap, int paramtype, const char *value, size_t length)
Add string-valued parameter to the autoaction parameter.
#define X400_S_CONTENT_IDENTIFIER
Definition: x400_att.h:414
#define X400_AUTO_ALERT
Definition: x400_att.h:1324
void X400msSetConfigRequest(int val)
Disable and enable configuration requests in MS Bind operations.
int X400msMsgGet(struct X400msSession *sp, int number, struct X400msMessage **mpp, int *typep, int *seqp)
Get message object for transfer out from MS or MTA via P3.
#define X400_N_STRICT_P7_1988
Definition: x400_att.h:1268
int X400RecipAddStrParam(struct X400Recipient *rp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the recipient.
const char * X400msError(int error)
Obtain a string describing the meaning of the given error code.
int X400msClose(struct X400msSession *sp)
Close a X400 Session.
#define X400_AUTO_FORWARDING
Definition: x400_att.h:1327
#define X400_S_AUTO_FORWARDING_COMMENT
Definition: x400_att.h:1237
int X400msDeregisterAutoAction(struct X400msSession *sp, int type, int id)
Deregister an autoaction from the Message Store.
#define X400_N_OR_CANONICAL
Definition: x400_att.h:1135
#define X400_E_NOERROR
Definition: x400_att.h:46
int X400msOpen(int type, const char *oraddr, const char *dirname, const char *credentials, const char *pa, int *messages, struct X400msSession **spp)
Open a session to a Message Store (P7) or MTA (P3) in synchronous mode.
int X400RecipNew(int type, struct X400Recipient **rpp)
Create a new recipient object.
#define X400_S_OR_ADDRESS
Definition: x400_att.h:349
#define X400_RECIP_STANDARD
Definition: x400_att.h:341
#define X400_E_TIMED_OUT
Definition: x400_att.h:106
#define X400_N_DISCLOSURE
Definition: x400_att.h:427
int X400msAutoActionParameterAddRecip(struct X400msAutoActionParameter *aap, int reciptype, struct X400Recipient *recip)
Add a receipient to the autoaction parameter.
int X400msMsgFromRaw(struct X400msSession *sp, char *buffer, size_t buflen, struct X400msMessage **mpp, int *typep)
Reconstruct a message from a binary representation.
#define X400_S_THIS_IPM_PREFIX
Definition: x400_att.h:1244
#define X400_N_WAIT_INTERVAL
Definition: x400_att.h:1084
X400 MA/MS (P3/P7) Interface.
int X400msMsgGetRaw(struct X400msSession *sp, struct X400msMessage *mp, char *buffer, size_t buflen, size_t *buflenp)
Get a binary representation of a message which can be subsequently be used to reconstruct the message...
#define X400_N_PRIORITY
Definition: x400_att.h:422
int X400msSetIntDefault(struct X400msSession *sp, int paramtype, int value)
Set a default integer parameter value in a session.
AMHS Symbolic Constants.
#define X400_N_ALTERNATE_RECIPIENT_ALLOWED
Definition: x400_att.h:433
int X400msWait(struct X400msSession *sp, int seconds, int *count)
Wait for messages to be ready to be read.
#define X400_E_NOSPACE
Definition: x400_att.h:112
#define X400_N_CONTENT_RETURN_REQUEST
Definition: x400_att.h:436
int X400msAutoActionParameterAddIntParam(struct X400msAutoActionParameter *aap, int paramtype, int value)
Add integer-valued parameter to the autoaction parameter.
int X400msMsgDelete(struct X400msMessage *mp, int retain)
Delete message object.
int X400InitializeLogging(const char *myname, const char *xmlfile)
Initialize X.400 API logging. If just the name of the logging configuration file is provided...