Fix building with libxml2-2.12.0
[shigofumi.git] / src / data.c
blob2668810adbd70e6a6c9dc88e6490b2858c01e13c
1 #define _XOPEN_SOURCE 500
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <time.h>
5 #include <string.h>
6 #include <stdint.h>
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <isds.h>
12 #include <readline/readline.h>
14 #include "shigofumi.h"
15 #include "ui.h"
17 void print_DbState(const long int state) {
18 switch(state) {
19 case DBSTATE_ACCESSIBLE: oprintf("ACCESSIBLE\n"); break;
20 case DBSTATE_TEMP_UNACCESSIBLE: oprintf("TEMP_UNACCESSIBLE\n"); break;
21 case DBSTATE_NOT_YET_ACCESSIBLE: oprintf("NOT_YET_ACCESSIBLE\n"); break;
22 case DBSTATE_PERM_UNACCESSIBLE: oprintf("PERM_UNACCESSIBLE\n"); break;
23 case DBSTATE_REMOVED: oprintf("REMOVED\n"); break;
24 default: oprintf("<unknown state %ld>\n", state);
28 void print_DbType(const long int *type) {
29 if (!type) oprintf("NULL\n");
30 else
31 switch(*type) {
32 case DBTYPE_SYSTEM: oprintf("SYSTEM\n"); break;
33 case DBTYPE_FO: oprintf("FO\n"); break;
34 case DBTYPE_PFO: oprintf("PFO\n"); break;
35 case DBTYPE_PFO_ADVOK: oprintf("PFO_ADVOK\n"); break;
36 case DBTYPE_PFO_AUDITOR: oprintf("PFO_AUDITOR\n"); break;
37 case DBTYPE_PFO_DANPOR: oprintf("PFO_DAPOR\n"); break;
38 case DBTYPE_PFO_INSSPR: oprintf("PFO_INSSPR\n"); break;
39 case DBTYPE_PO: oprintf("PO\n"); break;
40 case DBTYPE_PO_ZAK: oprintf("PO_ZAK\n"); break;
41 case DBTYPE_PO_REQ: oprintf("PO_REQ\n"); break;
42 case DBTYPE_OVM: oprintf("OVM\n"); break;
43 case DBTYPE_OVM_EXEKUT: oprintf("OVM_EXEKUT\n"); break;
44 case DBTYPE_OVM_FO: oprintf("OVM_FO\n"); break;
45 case DBTYPE_OVM_NOTAR: oprintf("OVM_NOTAR\n"); break;
46 case DBTYPE_OVM_PFO: oprintf("OVM_PFO\n"); break;
47 case DBTYPE_OVM_PO: oprintf("OVM_PO\n"); break;
48 case DBTYPE_OVM_REQ: oprintf("OVM_REQ\n"); break;
49 default: oprintf("<unknown type %ld>\n", *type);
54 void print_UserType(const long int *type) {
55 if (!type) oprintf("NULL\n");
56 else
57 switch(*type) {
58 case USERTYPE_PRIMARY: oprintf("PRIMARY\n"); break;
59 case USERTYPE_ENTRUSTED: oprintf("ENTRUSTED\n"); break;
60 case USERTYPE_ADMINISTRATOR: oprintf("ADMINISTRATOR\n"); break;
61 case USERTYPE_OFFICIAL: oprintf("OFFICIAL\n"); break;
62 default: oprintf("<unknown type %ld>\n", *type);
67 void print_UserPrivils(const long int *privils) {
69 const char *priviledges[] = {
70 "READ_NON_PERSONAL",
71 "READ_ALL",
72 "CREATE_DM",
73 "VIEW_INFO",
74 "SEARCH_DB",
75 "OWNER_ADM",
76 "READ_VAULT",
77 "ERASE_VAULT"
79 const int priviledges_count = sizeof(priviledges)/sizeof(priviledges[0]);
81 if (!privils) oprintf("NULL\n");
82 else {
83 oprintf("%ld (", *privils);
85 for (int i = 0; i < priviledges_count; i++) {
86 if (*privils & (1<<i)) {
87 oprintf(
88 ((i + 1) == priviledges_count) ? "%s" : "%s|",
89 priviledges[i]);
93 oprintf(")\n");
98 void print_hash(const struct isds_hash *hash) {
99 if (!hash) {
100 oprintf("NULL\n");
101 return;
104 switch(hash->algorithm) {
105 case HASH_ALGORITHM_MD5: oprintf("MD5 "); break;
106 case HASH_ALGORITHM_SHA_1: oprintf("SHA-1 "); break;
107 case HASH_ALGORITHM_SHA_256: oprintf("SHA-256 "); break;
108 case HASH_ALGORITHM_SHA_512: oprintf("SHA-512 "); break;
109 default: oprintf("<Unknown hash algorithm %d> ", hash->algorithm);
110 break;
113 if (!hash->value) oprintf("<NULL>");
114 else
115 for (int i = 0; i < hash->length; i++) {
116 if (i > 0) oprintf(":");
117 oprintf("%02x", ((uint8_t *)(hash->value))[i]);
120 oprintf("\n");
124 void print_raw_type(const isds_raw_type type) {
125 switch(type) {
126 case RAWTYPE_INCOMING_MESSAGE:
127 oprintf("INCOMING_MESSAGE\n"); break;
128 case RAWTYPE_PLAIN_SIGNED_INCOMING_MESSAGE:
129 oprintf("PLAIN_SIGNED_INCOMING_MESSAGE\n"); break;
130 case RAWTYPE_CMS_SIGNED_INCOMING_MESSAGE:
131 oprintf("CMS_SIGNED_INCOMING_MESSAGE\n"); break;
132 case RAWTYPE_PLAIN_SIGNED_OUTGOING_MESSAGE:
133 oprintf("PLAIN_SIGNED_OUTGOING_MESSAGE\n"); break;
134 case RAWTYPE_CMS_SIGNED_OUTGOING_MESSAGE:
135 oprintf("CMS_SIGNED_OUTGOING_MESSAGE\n"); break;
136 case RAWTYPE_DELIVERYINFO:
137 oprintf("DELIVERYINFO\n"); break;
138 case RAWTYPE_PLAIN_SIGNED_DELIVERYINFO:
139 oprintf("PLAIN_SIGNED_DELIVERYINFO\n"); break;
140 case RAWTYPE_CMS_SIGNED_DELIVERYINFO:
141 oprintf("CMS_SIGNED_DELIVERYINFO\n"); break;
142 default:
143 oprintf("<Unknown raw type %d> ", type);
144 break;
149 void print_bool(const _Bool *boolean) {
150 oprintf("%s\n", (!boolean) ? "NULL" : ((*boolean)? "true" : "false") );
154 void print_longint(const long int *number) {
155 if (!number) oprintf("NULL\n");
156 else oprintf("%ld\n", *number);
160 void print_PersonName(const struct isds_PersonName *personName) {
161 oprintf("\tpersonName = ");
162 if (!personName) oprintf("NULL\n");
163 else {
164 oprintf("{\n");
165 oprintf("\t\tpnFirstName = %s\n", personName->pnFirstName);
166 oprintf("\t\tpnMiddleName = %s\n", personName->pnMiddleName);
167 oprintf("\t\tpnLastName = %s\n", personName->pnLastName);
168 oprintf("\t\tpnLastNameAtBirth = %s\n", personName->pnLastNameAtBirth);
169 oprintf("\t}\n");
174 void print_Address(const struct isds_Address *address) {
175 oprintf("\taddress = ");
176 if (!address) oprintf("NULL\n");
177 else {
178 oprintf("{\n");
179 oprintf("\t\tadCity = %s\n", address->adCity);
180 oprintf("\t\tadStreet = %s\n", address->adStreet);
181 oprintf("\t\tadNumberInStreet = %s\n", address->adNumberInStreet);
182 oprintf("\t\tadNumberInMunicipality = %s\n",
183 address->adNumberInMunicipality);
184 oprintf("\t\tadZipCode = %s\n", address->adZipCode);
185 oprintf("\t\tadState = %s\n", address->adState);
186 oprintf("\t}\n");
191 void print_date(const struct tm *date) {
192 if (!date) oprintf("NULL\n");
193 else oprintf("%s", asctime(date));
197 void print_DbOwnerInfo(const struct isds_DbOwnerInfo *info) {
198 oprintf("dbOwnerInfo = ");
200 if (!info) {
201 oprintf("NULL\n");
202 return;
205 oprintf("{\n");
206 oprintf("\tdbID = %s\n", info->dbID);
208 oprintf("\tdbType = ");
209 print_DbType((long int *) (info->dbType));
210 oprintf("\tic = %s\n", info->ic);
212 print_PersonName(info->personName);
214 oprintf("\tfirmName = %s\n", info->firmName);
216 oprintf("\tbirthInfo = ");
217 if (!info->birthInfo) oprintf("NULL\n");
218 else {
219 oprintf("{\n");
221 oprintf("\t\tbiDate = ");
222 print_date(info->birthInfo->biDate);
224 oprintf("\t\tbiCity = %s\n", info->birthInfo->biCity);
225 oprintf("\t\tbiCounty = %s\n", info->birthInfo->biCounty);
226 oprintf("\t\tbiState = %s\n", info->birthInfo->biState);
227 oprintf("\t}\n");
230 print_Address(info->address);
232 oprintf("\tnationality = %s\n", info->nationality);
233 oprintf("\temail = %s\n", info->email);
234 oprintf("\ttelNumber = %s\n", info->telNumber);
235 oprintf("\tidentifier = %s\n", info->identifier);
236 oprintf("\tregistryCode = %s\n", info->registryCode);
238 oprintf("\tdbState = ");
239 if (!info->dbState) oprintf("NULL\n");
240 else print_DbState(*(info->dbState));
242 oprintf("\tdbEffectiveOVM = ");
243 print_bool(info->dbEffectiveOVM);
245 oprintf("\tdbOpenAddressing = ");
246 print_bool(info->dbOpenAddressing);
248 oprintf("}\n");
253 void print_DbUserInfo(const struct isds_DbUserInfo *info) {
254 oprintf("dbUserInfo = ");
256 if (!info) {
257 oprintf("NULL\n");
258 return;
261 oprintf("{\n");
262 oprintf("\tuserID = %s\n", info->userID);
264 oprintf("\tuserType = ");
265 print_UserType((long int *) (info->userType));
267 oprintf("\tuserPrivils = ");
268 print_UserPrivils(info->userPrivils);
270 print_PersonName(info->personName);
271 print_Address(info->address);
273 oprintf("\tbiDate = ");
274 print_date(info->biDate);
276 oprintf("\tic = %s\n", info->ic);
277 oprintf("\tfirmName = %s\n", info->firmName);
279 oprintf("\tcaStreet = %s\n", info->caStreet);
280 oprintf("\tcaCity = %s\n", info->caCity);
281 oprintf("\tcaZipCode = %s\n", info->caZipCode);
283 oprintf("}\n");
287 void print_timeval(const struct timeval *time) {
288 struct tm broken;
289 char buffer[128];
291 if (!time) {
292 oprintf("NULL\n");
293 return;
296 if (!localtime_r(&(time->tv_sec), &broken)) goto error;
297 if (!strftime(buffer, sizeof(buffer)/sizeof(char), "%c", &broken))
298 goto error;
299 oprintf("%s, %jd us\n", buffer, (intmax_t)time->tv_usec);
300 return;
302 error:
303 oprintf("<Error while formatting>\n>");
304 return;
308 void print_event_type(const isds_event_type *type) {
309 if (!type) {
310 oprintf("NULL");
311 return;
313 switch (*type) {
314 case EVENT_UKNOWN: oprintf("UNKNOWN\n"); break;
315 case EVENT_ENTERED_SYSTEM: printf("ENTERED_SYSTEM\n"); break;
316 case EVENT_ACCEPTED_BY_RECIPIENT:
317 oprintf("ACCEPTED_BY_RECIPIENT\n"); break;
318 case EVENT_ACCEPTED_BY_FICTION:
319 oprintf("DELIVERED_BY_FICTION\n"); break;
320 case EVENT_UNDELIVERABLE:
321 oprintf("UNDELIVERABLE\n"); break;
322 case EVENT_COMMERCIAL_ACCEPTED:
323 oprintf("COMMERCIAL_ACCEPTED\n"); break;
324 case EVENT_DELIVERED:
325 oprintf("DELIVERED\n"); break;
326 case EVENT_PRIMARY_LOGIN:
327 oprintf("PRIMARY_LOGIN\n"); break;
328 case EVENT_ENTRUSTED_LOGIN:
329 oprintf("ENTRUSTED_LOGIN\n"); break;
330 case EVENT_SYSCERT_LOGIN:
331 oprintf("SYSCERT_LOGIN\n"); break;
332 default: oprintf("<unknown type %d>\n", *type);
337 void print_events(const struct isds_list *events) {
338 const struct isds_list *item;
339 const struct isds_event *event;
341 if (!events) {
342 oprintf("NULL\n");
343 return;
346 oprintf("{\n");
348 for (item = events; item; item = item->next) {
349 event = (struct isds_event *) item->data;
350 oprintf("\t\t\tevent = ");
351 if (!event) oprintf("NULL");
352 else {
353 oprintf("{\n");
355 oprintf("\t\t\t\ttype = ");
356 print_event_type(event->type);
358 oprintf("\t\t\t\tdescription = %s\n", event->description);
360 oprintf("\t\t\t\ttime = ");
361 print_timeval(event->time);
363 oprintf("\t\t\t}\n");
367 oprintf("\t\t}\n");
371 void print_envelope(const struct isds_envelope *envelope) {
372 oprintf("\tenvelope = ");
374 if (!envelope) {
375 oprintf("NULL\n");
376 return;
378 oprintf("{\n");
380 oprintf("\t\tdmID = %s\n", envelope->dmID);
381 oprintf("\t\tdbIDSender = %s\n", envelope->dbIDSender);
382 oprintf("\t\tdmSender = %s\n", envelope->dmSender);
383 oprintf("\t\tdmSenderAddress = %s\n", envelope->dmSenderAddress);
384 oprintf("\t\tdmSenderType = ");
385 print_DbType(envelope->dmSenderType);
386 oprintf("\t\tdmRecipient = %s\n", envelope->dmRecipient);
387 oprintf("\t\tdmRecipientAddress = %s\n", envelope->dmRecipientAddress);
388 oprintf("\t\tdmAmbiguousRecipient = ");
389 print_bool(envelope->dmAmbiguousRecipient);
390 oprintf("\t\tdmType = %s\n", envelope->dmType);
392 oprintf("\t\tdmSenderOrgUnit = %s\n", envelope->dmSenderOrgUnit);
393 oprintf("\t\tdmSenderOrgUnitNum = ");
394 print_longint(envelope->dmSenderOrgUnitNum);
395 oprintf("\t\tdbIDRecipient = %s\n", envelope->dbIDRecipient);
396 oprintf("\t\tdmRecipientOrgUnit = %s\n", envelope->dmRecipientOrgUnit);
397 oprintf("\t\tdmRecipientOrgUnitNum = ");
398 print_longint(envelope->dmRecipientOrgUnitNum);
399 oprintf("\t\tdmToHands = %s\n", envelope->dmToHands);
400 oprintf("\t\tdmAnnotation = %s\n", envelope->dmAnnotation);
401 oprintf("\t\tdmRecipientRefNumber = %s\n", envelope->dmRecipientRefNumber);
402 oprintf("\t\tdmSenderRefNumber = %s\n", envelope->dmSenderRefNumber);
403 oprintf("\t\tdmRecipientIdent = %s\n", envelope->dmRecipientIdent);
404 oprintf("\t\tdmSenderIdent = %s\n", envelope->dmSenderIdent);
406 oprintf("\t\tdmLegalTitleLaw = ");
407 print_longint(envelope->dmLegalTitleLaw);
408 oprintf("\t\tdmLegalTitleYear = ");
409 print_longint(envelope->dmLegalTitleYear);
410 oprintf("\t\tdmLegalTitleSect = %s\n", envelope->dmLegalTitleSect);
411 oprintf("\t\tdmLegalTitlePar = %s\n", envelope->dmLegalTitlePar);
412 oprintf("\t\tdmLegalTitlePoint = %s\n", envelope->dmLegalTitlePoint);
414 oprintf("\t\tdmPersonalDelivery = ");
415 print_bool(envelope->dmPersonalDelivery);
416 oprintf("\t\tdmAllowSubstDelivery = ");
417 print_bool(envelope->dmAllowSubstDelivery);
418 oprintf("\t\tdmOVM = ");
419 print_bool(envelope->dmOVM);
420 oprintf("\t\tdmPublishOwnID = ");
421 print_bool(envelope->dmPublishOwnID);
423 oprintf("\t\tdmOrdinal = ");
424 if (!envelope->dmOrdinal) oprintf("NULL\n");
425 else oprintf("%lu\n", *(envelope->dmOrdinal));
427 oprintf("\t\tdmMessageStatus = ");
428 if (!envelope->dmMessageStatus) oprintf("NULL\n");
429 else
430 switch(*(envelope->dmMessageStatus)) {
431 case MESSAGESTATE_SENT: oprintf("SENT\n"); break;
432 case MESSAGESTATE_STAMPED: oprintf("STAMPED\n"); break;
433 case MESSAGESTATE_INFECTED: oprintf("INFECTED\n"); break;
434 case MESSAGESTATE_DELIVERED: oprintf("DELIVERED\n"); break;
435 case MESSAGESTATE_SUBSTITUTED: oprintf("SUBSTITUTED\n"); break;
436 case MESSAGESTATE_RECEIVED: oprintf("RECEIVED\n"); break;
437 case MESSAGESTATE_READ: oprintf("READ\n"); break;
438 case MESSAGESTATE_UNDELIVERABLE: oprintf("UNDELIVERABLE\n"); break;
439 case MESSAGESTATE_REMOVED: oprintf("REMOVED\n"); break;
440 case MESSAGESTATE_IN_SAFE: oprintf("IN_SAFE\n"); break;
441 default: oprintf("<unknown type %d>\n",
442 *(envelope->dmMessageStatus));
445 oprintf("\t\tdmAttachmentSize = ");
446 if (!envelope->dmAttachmentSize) oprintf("NULL\n");
447 else oprintf("%lu kB\n", *(envelope->dmAttachmentSize));
449 oprintf("\t\tdmDeliveryTime = ");
450 print_timeval(envelope->dmDeliveryTime);
452 oprintf("\t\tdmAcceptanceTime = ");
453 print_timeval(envelope->dmAcceptanceTime);
455 oprintf("\t\thash = ");
456 print_hash(envelope->hash);
458 oprintf("\t\ttimestamp = %p\n", envelope->timestamp);
459 oprintf("\t\ttimestamp_length = %zu\n", envelope->timestamp_length);
461 oprintf("\t\tevents = ");
462 print_events(envelope->events);
464 oprintf("\t}\n");
468 void print_document(const struct isds_document *document) {
469 oprintf("\t\tdocument = ");
471 if (!document) {
472 oprintf("NULL\n");
473 return;
475 oprintf("\{\n");
477 oprintf("\t\t\tis_xml = %u\n", !!document->is_xml);
478 oprintf("\t\t\txml_node_list = %p\n", document->xml_node_list);
480 oprintf("\t\t\tdata = %p\n", document->data);
481 oprintf("\t\t\tdata_length = %zu\n", document->data_length);
482 oprintf("\t\t\tdmMimeType = %s\n", document->dmMimeType);
484 oprintf("\t\t\tdmFileMetaType = ");
485 switch(document->dmFileMetaType) {
486 case FILEMETATYPE_MAIN: oprintf("MAIN\n"); break;
487 case FILEMETATYPE_ENCLOSURE: oprintf("ENCLOSURE\n"); break;
488 case FILEMETATYPE_SIGNATURE: oprintf("SIGNATURE\n"); break;
489 case FILEMETATYPE_META: oprintf("META\n"); break;
490 default: oprintf("<unknown type %d>\n", document->dmFileMetaType);
493 oprintf("\t\t\tdmFileGuid = %s\n", document->dmFileGuid);
494 oprintf("\t\t\tdmUpFileGuid = %s\n", document->dmUpFileGuid);
495 oprintf("\t\t\tdmFileDescr = %s\n", document->dmFileDescr);
496 oprintf("\t\t\tdmFormat = %s\n", document->dmFormat);
497 oprintf("\t\t}\n");
501 void print_documents(const struct isds_list *documents) {
502 const struct isds_list *item;
504 oprintf("\tdocuments = ");
506 if (!documents) {
507 oprintf("NULL\n");
508 return;
510 oprintf("{\n");
512 for (item = documents; item; item = item->next) {
513 print_document((struct isds_document *) (item->data));
516 oprintf("\t}\n");
520 void print_message(const struct isds_message *message) {
521 oprintf("message = ");
523 if (!message) {
524 oprintf("NULL\n");
525 return;
528 oprintf("{\n");
530 oprintf("\traw = %p\n", message->raw);
531 oprintf("\traw_length = %zu\n", message->raw_length);
532 oprintf("\traw_type = ");
533 print_raw_type(message->raw_type);
534 print_envelope(message->envelope);
535 print_documents(message->documents);
537 oprintf("}\n");
540 void print_copies(const struct isds_list *copies) {
541 const struct isds_list *item;
542 struct isds_message_copy *copy;
544 oprintf("Copies = ");
545 if (!copies) {
546 oprintf("<NULL>\n");
547 return;
550 oprintf("{\n");
551 for (item = copies; item; item = item->next) {
552 copy = (struct isds_message_copy *) item->data;
553 oprintf("\tCopy = ");
555 if (!copy)
556 oprintf("<NULL>\n");
557 else {
558 oprintf("{\n");
559 oprintf("\t\tdbIDRecipient = %s\n", copy->dbIDRecipient);
560 oprintf("\t\tdmRecipientOrgUnit = %s\n", copy->dmRecipientOrgUnit);
562 oprintf("\t\tdmRecipientOrgUnitNum = ");
563 if (copy->dmRecipientOrgUnitNum)
564 oprintf("%ld\n", *copy->dmRecipientOrgUnitNum);
565 else
566 oprintf("<NULL>\n");
567 oprintf("\t\tdmToHands = %s\n", copy->dmToHands);
569 oprintf("\t\terror = %s\n", isds_strerror(copy->error));
570 oprintf("\t\tdmStatus = %s\n", copy->dmStatus);
571 oprintf("\t\tdmID = %s\n", copy->dmID);
572 oprintf("\t}\n");
575 oprintf("}\n");
579 void compare_hashes(const struct isds_hash *hash1,
580 const struct isds_hash *hash2) {
581 isds_error err;
583 oprintf("Comparing hashes... ");
584 err = isds_hash_cmp(hash1, hash2);
585 if (err == IE_SUCCESS)
586 oprintf("Hashes equal\n");
587 else if
588 (err == IE_NOTEQUAL) oprintf("Hashes differ\n");
589 else
590 oprintf("isds_hash_cmp() failed: %s\n", isds_strerror(err));
594 int progressbar(double upload_total, double upload_current,
595 double download_total, double download_current,
596 void *data) {
598 oprintf("Progress: upload %0f/%0f, download %0f/%0f, data=%p\n",
599 upload_current, upload_total, download_current, download_total,
600 data);
601 return 0;
605 /* Print formatted header if locale-encoded value is defined.
606 * @header is locale encoded header name
607 * @value is locale encoded header value */
608 void print_header(const char *header, const char *value) {
609 if (value && *value) oprintf(_("%s: %s\n"), header, value);
613 /* Print formatted header if boolean value is defined.
614 * @header is locale encoded header name */
615 void print_header_bool(const char *header, const _Bool *value) {
616 if (value) print_header(header, (*value) ? _("Yes") : _("No"));
620 /* Print formatted header if long int value is defined.
621 * @header is locale encoded header name */
622 void print_header_longint(const char *header, const long int *value) {
623 if (value) oprintf(_("%s: %ld\n"), header, *value);
627 /* Print formatted header if unsigned long int value is defined.
628 * @header is locale encoded header name */
629 void print_header_ulongint(const char *header, const unsigned long int *value) {
630 if (value) oprintf(_("%s: %lu\n"), header, *value);
634 /* Print formatted header if time value is defined.
635 * @header is locale encoded header name */
636 void print_header_timeval(const char *header, const struct timeval *time) {
637 struct tm broken;
638 char buffer[128];
640 if (!time) return;
642 if (!localtime_r(&(time->tv_sec), &broken)) goto error;
643 if (!strftime(buffer, sizeof(buffer)/sizeof(char), "%c", &broken))
644 goto error;
646 if (!time->tv_usec)
647 oprintf(_("%s: %s\n"), header, buffer);
648 else if ((time->tv_usec % 1000) == 0)
649 oprintf(_("%s: %s, %jd ms\n"), header, buffer, (intmax_t)time->tv_usec/1000);
650 else
651 oprintf(_("%s: %s, %jd us\n"), header, buffer, (intmax_t)time->tv_usec);
653 return;
655 error:
656 oprintf(_("%s: <Error while formatting time>\n"), header);
657 return;
661 /* Return formatted date as mallocated string. NULL or special error string can
662 * be returned. Application must free even the error string. */
663 char *tm2string(const struct tm *date) {
664 char *buffer;
665 size_t buffer_length = 128;
667 if (!date) return NULL;
669 buffer = malloc(buffer_length);
670 if (!buffer) return strdup(_("<Error while formatting date>"));
672 if (0 == strftime(buffer, buffer_length, "%x", date)) {
673 free(buffer);
674 return strdup(_("<Error while formatting date>"));
677 return buffer;
681 /* Convert string representation of full ISO 8601 or locale date to tm structure.
682 * Return NULL if error occurs
683 * XXX: Not all ISO formats are supported */
684 struct tm *datestring2tm(const char *string) {
685 struct tm *date = NULL;
686 char *offset;
687 if (!string) return NULL;
689 date = calloc(1, sizeof(*date));
690 if (!date) return NULL;
692 /* xsd:date is ISO 8601 string, thus ASCII */
693 offset = strptime(string, "%Y-%m-%d", date);
694 if (offset && *offset == '\0')
695 return date;
697 offset = strptime(string, "%x", date);
698 if (offset && *offset == '\0')
699 return date;
701 free(date);
702 return NULL;
706 /* Convert string representation of box type to isds_DbType. Return false
707 * if the string was not recognized. Otherwise returns true. */
708 int string2isds_DbType(isds_DbType *type, const char *string) {
709 if (!strcmp(string, "FO"))
710 *type = DBTYPE_FO;
711 else if (!strcmp(string, "PFO"))
712 *type = DBTYPE_PFO;
713 else if (!strcmp(string, "PFO_ADVOK"))
714 *type = DBTYPE_PFO_ADVOK;
715 else if (!strcmp(string, "PFO_AUDITOR"))
716 *type = DBTYPE_PFO_AUDITOR;
717 else if (!strcmp(string, "PFO_DANPOR"))
718 *type = DBTYPE_PFO_DANPOR;
719 else if (!strcmp(string, "PFO_INSSPR"))
720 *type = DBTYPE_PFO_INSSPR;
721 else if (!strcmp(string, "PO"))
722 *type = DBTYPE_PO;
723 else if (!strcmp(string, "PO_ZAK"))
724 *type = DBTYPE_PO_ZAK;
725 else if (!strcmp(string, "PO_REQ"))
726 *type = DBTYPE_PO_REQ;
727 else if (!strcmp(string, "OVM"))
728 *type = DBTYPE_OVM;
729 else if (!strcmp(string, "OVM_NOTAR"))
730 *type = DBTYPE_OVM_NOTAR;
731 else if (!strcmp(string, "OVM_EXEKUT"))
732 *type = DBTYPE_OVM_EXEKUT;
733 else if (!strcmp(string, "OVM_REQ"))
734 *type = DBTYPE_OVM_REQ;
735 else if (!strcmp(string, "OVM_FO"))
736 *type = DBTYPE_OVM_FO;
737 else if (!strcmp(string, "OVM_PFO"))
738 *type = DBTYPE_OVM_PFO;
739 else if (!strcmp(string, "OVM_PO"))
740 *type = DBTYPE_OVM_PO;
741 else
742 return 0;
743 return 1;
747 /* Print formatted header if date value is defined.
748 * @header is locale encoded header name */
749 void print_header_tm(const char *header, const struct tm *date) {
750 char *string;
752 if (NULL == date) return;
753 string = tm2string(date);
755 if (NULL == string)
756 oprintf(_("%s: <Error while formatting date>\n"), header);
757 else
758 print_header(header, string);
760 free(string);
764 /* Print formatted header if UTF-8 value is defined.
765 * @header is locale encoded header name
766 * @value is UTF-8 encoded header value */
767 void print_header_utf8(const char *header, const char *value) {
768 char *value_locale;
770 if (!value) return;
772 value_locale = utf82locale(value);
773 print_header(header,
774 (value_locale) ?
775 value_locale :
776 _("<Error while converting value>"));
777 free(value_locale);
781 /* Print formatted header and byte size.
782 * @header is locale encoded header name */
783 void print_header_size(const char *header, size_t size) {
784 char *buffer = NULL;
786 if (size < (1<<10))
787 shi_asprintf(&buffer, _("%zu B"), size);
788 else if (size < (1<<20))
789 shi_asprintf(&buffer, _("%0.2f KiB"), (float) size/(1<<10));
790 else
791 shi_asprintf(&buffer, _("%0.2f MiB"), (float) size/(1<<20));
793 print_header(header, buffer);
794 free(buffer);
798 /* Print formatted header if long int KB size is defined.
799 * @header is locale encoded header name */
800 void print_header_kbsize(const char *header, const long int *size) {
801 char *buffer = NULL;
802 if (!size) return;
804 if (*size < 0)
805 shi_asprintf(&buffer, _("<Negative size>"));
806 else if (*size < (1000))
807 shi_asprintf(&buffer, _("%lu kB"), *size);
808 else
809 shi_asprintf(&buffer, _("%0.2f MB"), *size/1000.0);
811 print_header(header, buffer);
812 free(buffer);
816 /* Print formatted header if long int CZK/100 currency value is defined.
817 * @header is locale encoded header name
818 * @value is pointer to value in hundredths of CZK */
819 void print_header_currency(const char *header, const long int *value) {
820 char *buffer = NULL;
821 unsigned long int integer;
822 unsigned long int fraction;
824 if (NULL == value) return;
826 /* labs(3) and % with negative values are ISO C99 specific. Did I say this
827 * code did not support older compilers? */
828 integer = labs(*value / 100);
829 fraction = labs(*value % 100);
831 /* XXX: We could use strfmon(3) only if it was standardized and if it
832 * supported arbitrary precision fraction (no float point types).
833 * We could reimplement strfmon(3) to use locale defintion, but that would
834 * be overkill. Direct localization is simpler. */
835 shi_asprintf(&buffer,
836 (*value < 0) ?
837 _("CZK -%lu.%02lu") :
838 _("CZK %lu.%02lu"),
839 integer, fraction);
841 print_header(header, buffer);
843 free(buffer);
847 static const char *DbType2string(const long int *type) {
848 if (!type) return NULL;
849 switch(*type) {
850 case DBTYPE_SYSTEM: return(_("System"));
851 case DBTYPE_FO: return(_("Private individual"));
852 case DBTYPE_PFO: return(_("Self-employed individual"));
853 case DBTYPE_PFO_ADVOK: return(_("Lawyer"));
854 case DBTYPE_PFO_AUDITOR: return(_("Statutory auditor"));
855 case DBTYPE_PFO_DANPOR: return(_("Tax advisor"));
856 case DBTYPE_PFO_INSSPR: return(_("Insolvency administrator"));
857 case DBTYPE_PO: return(_("Organisation"));
858 case DBTYPE_PO_ZAK: return(_("Organization based by law"));
859 case DBTYPE_PO_REQ: return(_("Organization based on request"));
860 case DBTYPE_OVM: return(_("Public authority"));
861 case DBTYPE_OVM_EXEKUT: return(_("Executor"));
862 case DBTYPE_OVM_FO: return(_("Private individual listed in the public authority index"));
863 case DBTYPE_OVM_NOTAR: return(_("Notary"));
864 case DBTYPE_OVM_PFO: return(_("Self-employed individual listed in the public authority index"));
865 case DBTYPE_OVM_PO: return(_("Organisation listed in the public authority index"));
866 case DBTYPE_OVM_REQ: return(_("Public authority based on request"));
867 default: return(_("<Unknown type>"));
872 static const char *UserType2string(const long int *type) {
873 if (!type) return NULL;
874 switch(*type) {
875 case USERTYPE_PRIMARY: return(_("Primary"));
876 case USERTYPE_ENTRUSTED: return(_("Entrusted"));
877 case USERTYPE_ADMINISTRATOR: return(_("Administrator"));
878 case USERTYPE_OFFICIAL: return(_("Official"));
879 default: return(_("<Unknown type>"));
884 static const char *isds_sender_type2string(const isds_sender_type *type) {
885 if (!type) return NULL;
886 switch(*type) {
887 case SENDERTYPE_PRIMARY: return(_("Primary"));
888 case SENDERTYPE_ENTRUSTED: return(_("Entrusted"));
889 case SENDERTYPE_ADMINISTRATOR: return(_("Administrator"));
890 case SENDERTYPE_OFFICIAL: return(_("Official"));
891 case SENDERTYPE_VIRTUAL: return(_("Virtual"));
892 default: return(_("<unknown type>"));
897 /* Return formatted user privileges. Caller must free the string */
898 static char *UserPrivils2string(const long int *privils) {
900 const char *priviledges[] = {
901 N_("Read non-personal"),
902 N_("Read all"),
903 N_("Send and read sent"),
904 N_("List messages and read delivery details"),
905 N_("Search boxes"),
906 N_("Administer her box"),
907 N_("Read from safe"),
908 N_("Delete from safe")
910 const int priviledges_count = sizeof(priviledges)/sizeof(priviledges[0]);
911 char *buffer = NULL, *new_buffer = NULL;
913 if (!privils) return NULL;
915 /*oprintf("%ld (", *privils);*/
917 for (int i = 0; i < priviledges_count; i++) {
918 if (*privils & (1<<i)) {
919 if ((*privils % (1<<i)))
920 shi_asprintf(&new_buffer, _("%s, %s"),
921 buffer, _(priviledges[i]));
922 else
923 shi_asprintf(&new_buffer, "%s", _(priviledges[i]));
925 if (!new_buffer) {
926 free(buffer);
927 return(strdup(_("<Error while formatting privileges>")));
930 free(buffer);
931 buffer = new_buffer;
932 new_buffer = NULL;
936 if (*privils >= (1<<priviledges_count)) {
937 if ((*privils % (1<<priviledges_count)))
938 shi_asprintf(&new_buffer, _("%s, %s"),
939 buffer, _("<Unknown privilege>"));
940 else
941 shi_asprintf(&new_buffer, "%s", _("<Unknown privilege>"));
943 if (!new_buffer) {
944 free(buffer);
945 return(strdup(_("<Error while formatting privileges>")));
948 free(buffer);
949 buffer = new_buffer;
950 new_buffer = NULL;
953 return buffer;
957 static const char *DmType2string(const char *type) {
958 if (!type) return NULL;
959 if (!strcmp(type, "V"))
960 return(_("Public"));
961 else if (!strcmp(type, "K"))
962 return(_("Commercial"));
963 else if (!strcmp(type, "A"))
964 return(_("Commercial (initiatory, unused, subsidized)"));
965 else if (!strcmp(type, "B"))
966 return(_("Commercial (initiatory, used, subsidized)"));
967 else if (!strcmp(type, "C"))
968 return(_("Commercial (initiatory, expired, subsidized)"));
969 else if (!strcmp(type, "D"))
970 return(_("Commercial (externally subsidized)"));
971 else if (!strcmp(type, "E"))
972 return(_("Commercial (prepaid by a stamp)"));
973 else if (!strcmp(type, "G"))
974 return(_("Commercial (sponsored)"));
975 else if (!strcmp(type, "I"))
976 return(_("Commercial (initiatory, unused, paid by sender)"));
977 else if (!strcmp(type, "O"))
978 return(_("Commercial (response paid by recipient)"));
979 else if (!strcmp(type, "X"))
980 return(_("Commercial (initiatory, expired, paid by sender)"));
981 else if (!strcmp(type, "Y"))
982 return(_("Commercial (initiatory, used, paid by sender)"));
983 else if (!strcmp(type, "Z"))
984 return(_("Commercial (limitedly subsidized)"));
985 else return(_("<Unknown type>"));
989 /* Simplified commercial status printed on message listing.
990 * 'P' is a public message sent by a government
991 * 'C' is a commercial message
992 * 'I' is a commercial message offering to pay response instead of the
993 * responder
994 * 'i' is a commercial message that offered to pay reposne, but it does not
995 * anymore.
996 * 'R' is a commercial response message paid by sender of the I message. */
997 static const char DmType2flag(const char *type) {
998 if (!type) return ' ';
999 if (!strcmp(type, "V")) return('P');
1000 else if (!strcmp(type, "K")) return('C');
1001 else if (!strcmp(type, "A")) return('I');
1002 else if (!strcmp(type, "B")) return('i');
1003 else if (!strcmp(type, "C")) return('i');
1004 else if (!strcmp(type, "D")) return('C');
1005 else if (!strcmp(type, "E")) return('C');
1006 else if (!strcmp(type, "G")) return('C');
1007 else if (!strcmp(type, "I")) return('I');
1008 else if (!strcmp(type, "O")) return('R');
1009 else if (!strcmp(type, "X")) return('i');
1010 else if (!strcmp(type, "Y")) return('i');
1011 else if (!strcmp(type, "Z")) return('C');
1012 else return('?');
1016 static const char *DmMessageStatus2string(const isds_message_status *status) {
1017 if (!status) return NULL;
1018 switch(*status) {
1019 case MESSAGESTATE_SENT: return(_("Sent"));
1020 case MESSAGESTATE_STAMPED: return(_("Stamped"));
1021 case MESSAGESTATE_INFECTED: return(_("Infected"));
1022 case MESSAGESTATE_DELIVERED: return(_("Delivered ordinary"));
1023 case MESSAGESTATE_SUBSTITUTED: return(_("Delivered substitutably"));
1024 case MESSAGESTATE_RECEIVED: return(_("Accepted"));
1025 case MESSAGESTATE_READ: return(_("Read"));
1026 case MESSAGESTATE_UNDELIVERABLE: return(_("Undeliverable"));
1027 case MESSAGESTATE_REMOVED: return(_("Deleted"));
1028 case MESSAGESTATE_IN_SAFE: return(_("Stored in safe"));
1029 default: return(_("<Unknown state>"));
1034 static const char DmMessageStatus2flag(const isds_message_status *status) {
1035 if (!status) return ' ';
1036 switch(*status) {
1037 case MESSAGESTATE_SENT: return('>');
1038 case MESSAGESTATE_STAMPED: return('t');
1039 case MESSAGESTATE_INFECTED: return('I');
1040 case MESSAGESTATE_DELIVERED: return('N');
1041 case MESSAGESTATE_SUBSTITUTED: return('n');
1042 case MESSAGESTATE_RECEIVED: return('O');
1043 case MESSAGESTATE_READ: return(' ');
1044 case MESSAGESTATE_UNDELIVERABLE: return('!');
1045 case MESSAGESTATE_REMOVED: return('D');
1046 case MESSAGESTATE_IN_SAFE: return('S');
1047 default: return('?');
1052 /* Return timeval time formatted into shortest string with respect to current
1053 * time. Caller must free the string. */
1054 static char *timeval2shortstring(const struct timeval *timeval) {
1055 struct tm broken, current_broken;
1056 time_t current_time;
1057 char *buffer = NULL;
1058 const size_t buffer_size = 16;
1060 if (!timeval) return NULL;
1062 buffer = malloc(buffer_size);
1063 if (!buffer) goto error;
1065 /* Get current time */
1066 current_time = time(NULL);
1067 if (current_time == (time_t) -1) goto error;
1068 if (!localtime_r(&current_time, &current_broken)) goto error;
1070 /* Get broken time */
1071 if (!localtime_r(&(timeval->tv_sec), &broken)) goto error;
1073 /* Select proper abbreviated string representation */
1074 if (broken.tm_year == current_broken.tm_year &&
1075 broken.tm_yday == current_broken.tm_yday) {
1076 /* Minute resolution in the same day */
1077 if (!strftime(buffer, buffer_size, _("%k:%M"), &broken))
1078 goto error;
1079 } else {
1080 /* Otherwise month and day */
1081 if (!strftime(buffer, buffer_size, _("%b %d"), &broken))
1082 goto error;
1085 return buffer;
1087 error:
1088 free(buffer);
1089 return strdup(_("<Error>"));
1093 /* Formatted Law Authorization if defined. You must free it. */
1094 static char *envelope_law2string(const struct isds_envelope *envelope) {
1095 char *output = NULL;
1096 char *year_locale = NULL, *law_locale = NULL;
1097 char *sect_locale = NULL, *par_locale = NULL, *point_locale = NULL;
1099 if (!envelope ||
1100 !(envelope->dmLegalTitleYear || envelope->dmLegalTitleLaw ||
1101 envelope->dmLegalTitleSect || envelope->dmLegalTitlePar ||
1102 envelope->dmLegalTitlePoint)
1103 ) return NULL;
1105 if (envelope->dmLegalTitleYear)
1106 shi_asprintf(&year_locale, "%ld", *envelope->dmLegalTitleYear);
1107 else
1108 year_locale = strdup(_("?"));
1110 if (envelope->dmLegalTitleLaw)
1111 shi_asprintf(&law_locale, "%ld", *envelope->dmLegalTitleLaw);
1112 else
1113 law_locale = strdup(_("?"));
1115 sect_locale = utf82locale(envelope->dmLegalTitleSect);
1116 par_locale = utf82locale(envelope->dmLegalTitlePar);
1117 point_locale = utf82locale(envelope->dmLegalTitlePoint);
1119 if (point_locale)
1120 shi_asprintf(&output, _("point %s, par. %s, sect. %s, %s/%s Coll."),
1121 point_locale, par_locale, sect_locale,
1122 law_locale, year_locale);
1123 else if (par_locale)
1124 shi_asprintf(&output, _("par. %s, sect. %s, %s/%s Coll."),
1125 par_locale, sect_locale, law_locale, year_locale);
1126 else if (sect_locale)
1127 shi_asprintf(&output, _("sect. %s, %s/%s Coll."),
1128 sect_locale, law_locale, year_locale);
1129 else
1130 shi_asprintf(&output, _("%s/%s Coll."),
1131 law_locale, year_locale);
1133 free(year_locale);
1134 free(law_locale);
1135 free(sect_locale);
1136 free(par_locale);
1137 free(point_locale);
1138 return output;
1142 static const char *isds_payment_type2string(const isds_payment_type *type) {
1143 if (!type) return NULL;
1144 switch(*type) {
1145 case PAYMENT_SENDER: return(_("Payed by sender"));
1146 case PAYMENT_STAMP: return(_("Stamp pre-paid by sender"));
1147 case PAYMENT_SPONSOR: return(_("Sponsor pays all messages"));
1148 case PAYMENT_RESPONSE: return(_("Recipient pays a response"));
1149 case PAYMENT_SPONSOR_LIMITED: return(_("Limitedly subsidized"));
1150 case PAYMENT_SPONSOR_EXTERNAL: return(_("Externally subsidized"));
1151 default: return(_("<unknown type>"));
1156 /* Print formatted header if time any of message ID.
1157 * @header is locale encoded header name */
1158 static void print_header_messages_ids(const char *header,
1159 const char *ref_number, const char *ident) {
1160 if (ref_number || ident) {
1161 oprintf(_("%s:\n"), header);
1162 print_header_utf8(_("\tReference number"), ref_number);
1163 print_header_utf8(_("\tFile ID"), ident);
1168 /* Return formatted hash value */
1169 char *hash2string(const struct isds_hash *hash) {
1170 const char *algorithm_string = NULL;
1171 char *buffer = NULL, *octet = NULL, *new_buffer = NULL;
1173 if (!hash || !hash->value) return NULL;
1175 switch(hash->algorithm) {
1176 case HASH_ALGORITHM_MD5: algorithm_string = (_("MD5")); break;
1177 case HASH_ALGORITHM_SHA_1: algorithm_string = (_("SHA-1")); break;
1178 case HASH_ALGORITHM_SHA_224: algorithm_string = (_("SHA-224")); break;
1179 case HASH_ALGORITHM_SHA_256: algorithm_string = (_("SHA-256")); break;
1180 case HASH_ALGORITHM_SHA_384: algorithm_string = (_("SHA-384")); break;
1181 case HASH_ALGORITHM_SHA_512: algorithm_string = (_("SHA-512")); break;
1182 default: algorithm_string = (_("<Unknown hash algorithm>")); break;
1185 for (int i = 0; i < hash->length; i++) {
1186 shi_asprintf(&octet, "%02x", ((uint8_t *)(hash->value))[i]);
1187 if (!octet) {
1188 free(buffer); free(octet); return NULL;
1191 if (i > 0)
1192 shi_asprintf(&new_buffer, _("%s:%s"), buffer, octet);
1193 else
1194 shi_asprintf(&new_buffer, "%s", octet);
1195 if (!new_buffer) {
1196 free(buffer); free(octet); return NULL;
1199 buffer = new_buffer; new_buffer = NULL;
1202 shi_asprintf(&new_buffer, _("%s %s"), algorithm_string, buffer);
1203 free(buffer);
1205 return new_buffer;
1209 /* Print if any message delivery info exists. */
1210 void print_message_delivery_info(const struct isds_envelope *envelope) {
1211 char *hash_string = NULL;
1213 if (envelope && (envelope->dmType || envelope->dmMessageStatus ||
1214 envelope->dmDeliveryTime ||
1215 envelope->dmAcceptanceTime || envelope->dmPersonalDelivery ||
1216 envelope->dmAllowSubstDelivery || envelope->hash ||
1217 envelope->dmOrdinal)) {
1218 oprintf(_("Delivery data:\n"));
1219 print_header(_("\tMessage type"), DmType2string(envelope->dmType));
1220 print_header(_("\tMessage status"),
1221 DmMessageStatus2string(envelope->dmMessageStatus));
1222 print_header_timeval(_("\tDelivered"), envelope->dmDeliveryTime);
1223 print_header_timeval(_("\tAccepted"), envelope->dmAcceptanceTime);
1224 print_header_bool(_("\tPersonal delivery required"),
1225 envelope->dmPersonalDelivery);
1226 print_header_bool(_("\tAllow substitutable delivery"),
1227 envelope->dmAllowSubstDelivery);
1229 hash_string = hash2string(envelope->hash);
1230 print_header(_("\tHash"), hash_string);
1231 free(hash_string);
1233 print_header_ulongint(_("\tOrdinal number"), envelope->dmOrdinal);
1238 static const char *event_type2string(const isds_event_type *type) {
1239 if (!type) return (_("<Undefined>"));
1241 switch (*type) {
1242 case EVENT_UKNOWN: return(_("Unknown"));
1243 case EVENT_ENTERED_SYSTEM:
1244 return(_("Entered system"));
1245 case EVENT_ACCEPTED_BY_RECIPIENT:
1246 return(_("Accepted by recipient"));
1247 case EVENT_ACCEPTED_BY_FICTION:
1248 return(_("Delivered substitutably"));
1249 case EVENT_UNDELIVERABLE:
1250 return(_("Undeliverable"));
1251 case EVENT_COMMERCIAL_ACCEPTED:
1252 return(_("Commerical message accepted by "
1253 "recipient")); break;
1254 case EVENT_DELIVERED:
1255 return(_("Delivered into box")); break;
1256 case EVENT_PRIMARY_LOGIN:
1257 return(_("Primary user logged in")); break;
1258 case EVENT_ENTRUSTED_LOGIN:
1259 return(_("Entrusted user logged in")); break;
1260 case EVENT_SYSCERT_LOGIN:
1261 return(_("Application logged in by system "
1262 "certificate")); break;
1263 default: return(_("<Unknown event type>"));
1268 /* Print if any delivery event exists. */
1269 void print_delivery_events(const struct isds_list *events) {
1270 int counter_width = 3;
1271 int order = 0;
1272 const struct isds_list *item;
1273 struct isds_event *event;
1275 if (!events) return;
1277 oprintf(_("Delivery events:\n"));
1279 for (item = events; item; item = item->next) {
1280 event = (struct isds_event *) item->data;
1281 if (!event) continue;
1282 order++;
1284 oprintf(_("%*d %s\n"), counter_width, order,
1285 event_type2string(event->type));
1286 print_header_utf8(_("\tDescription"), event->description);
1287 print_header_timeval(_("\tWhen"), event->time);
1292 /* Print formatted message envelope */
1293 void format_envelope(const struct isds_envelope *envelope) {
1294 char *law_string = NULL;
1296 if (!envelope) {
1297 oprintf(_("<Missing envelope>\n"));
1298 return;
1301 print_header_utf8(_("Message ID"), envelope->dmID);
1303 if (envelope->dbIDSender || envelope->dmSender ||
1304 envelope->dmSenderOrgUnit || envelope->dmSenderOrgUnitNum ||
1305 envelope->dmSenderAddress || envelope->dmSenderType ||
1306 envelope->dmOVM || envelope->dmPublishOwnID) {
1307 oprintf(_("Sender:\n"));
1308 print_header_utf8(_("\tID"), envelope->dbIDSender);
1309 print_header_utf8(_("\tName"), envelope->dmSender);
1310 print_header_utf8(_("\tUnit"), envelope->dmSenderOrgUnit);
1311 print_header_longint(_("\tUnit number"), envelope->dmSenderOrgUnitNum);
1312 print_header_utf8(_("\tAddress"), envelope->dmSenderAddress);
1313 print_header(_("\tType"), DbType2string(envelope->dmSenderType));
1314 print_header_bool(_("\tAs public authority"), envelope->dmOVM);
1315 print_header_bool(_("\tPublish user's identity"),
1316 envelope->dmPublishOwnID);
1319 if (envelope->dbIDRecipient || envelope->dmRecipient ||
1320 envelope->dmRecipientOrgUnit || envelope->dmRecipientOrgUnitNum ||
1321 envelope->dmToHands || envelope->dmRecipientAddress ||
1322 envelope->dmAmbiguousRecipient) {
1323 oprintf(_("Recipient:\n"));
1324 print_header_utf8(_("\tID"), envelope->dbIDRecipient);
1325 print_header_utf8(_("\tName"), envelope->dmRecipient);
1326 print_header_utf8(_("\tUnit"), envelope->dmRecipientOrgUnit);
1327 print_header_longint(_("\tUnit number"),
1328 envelope->dmRecipientOrgUnitNum);
1329 print_header_utf8(_("To hands"), envelope->dmToHands);
1330 print_header_utf8(_("\tAddress"), envelope->dmRecipientAddress);
1331 print_header_bool(_("\tAs public authority"),
1332 envelope->dmAmbiguousRecipient);
1335 print_header_utf8(_("Subject"), envelope->dmAnnotation);
1337 print_header_messages_ids(_("Sender message IDs"),
1338 envelope->dmSenderRefNumber, envelope->dmSenderIdent);
1339 print_header_messages_ids(_("Recipient message IDs"),
1340 envelope->dmRecipientRefNumber, envelope->dmRecipientIdent);
1342 law_string = envelope_law2string(envelope);
1343 print_header(_("Law authorization"), law_string);
1344 free(law_string);
1346 print_message_delivery_info(envelope);
1348 print_header_kbsize(_("Document total size"), envelope->dmAttachmentSize);
1350 /*oprintf("\t\ttimestamp = %p\n", envelope->timestamp);
1351 oprintf("\t\ttimestamp_length = %zu\n", envelope->timestamp_length);*/
1352 print_delivery_events(envelope->events);
1356 const char *DmFileMetaType2string(isds_FileMetaType type) {
1357 switch(type) {
1358 case FILEMETATYPE_MAIN: return(_("Main document"));
1359 case FILEMETATYPE_ENCLOSURE: return(_("Enclosure"));
1360 case FILEMETATYPE_SIGNATURE: return(_("Signature"));
1361 case FILEMETATYPE_META: return(_("Meta document"));
1362 default: return(_("<unknown document type>"));
1367 /* Computes ordinal number of document identified by GUID
1368 * @documents is list of documents where to search
1369 * @id is UTF-8 encoded document ID reference
1370 * Return allocated array of ordinal numbers terminated by -1. Normally only
1371 * one document with @id exists. However ISDS does not check this higher
1372 * requirements and can transport message with duplicate document identifiers.
1373 * Therefore this function returns array of ordinals. Return NULL if error
1374 * occurs (e.g. memory insufficiency). */
1375 static int *dmFileGuid2ordinar(const struct isds_list *documents,
1376 const char *id) {
1377 const struct isds_list *item;
1378 struct isds_document *document;
1379 size_t ordinars_length = 64, offset = 0;
1380 int *ordinars = NULL, *new_ordinars;
1381 int ordinar = 0;
1383 if (!documents || !id || !*id) return NULL;
1384 ordinars = malloc(ordinars_length * sizeof(*ordinars));
1385 if (!ordinars) return NULL;
1387 for (item = documents; item; item = item->next) {
1388 if (!item->data) continue;
1389 ordinar++;
1390 document = (struct isds_document *) (item->data);
1392 if (document->dmFileGuid && !strcmp(document->dmFileGuid, id)) {
1393 if (offset == ordinars_length) {
1394 /* Grow ordinals array */
1395 ordinars_length *= 2;
1396 new_ordinars = realloc(ordinars,
1397 ordinars_length * sizeof(*ordinars));
1398 if (!new_ordinars) {
1399 free(ordinars);
1400 return NULL;
1402 ordinars = new_ordinars;
1405 ordinars[offset++] = ordinar;
1409 ordinars[offset] = -1;
1410 return ordinars;
1414 /* @id is UTF-8 encoded GUID of referred document
1415 * @refernces is array of ordinal numbers if exist terminated by -1. Can be
1416 * NULL to signal error. */
1417 static void format_document_reference(char *id, int *references) {
1418 char *buffer = NULL, *new_buffer = NULL;
1419 if (!id) return;
1421 if (references && *references != -1) {
1422 for (; *references > 0; references++) {
1423 if (!buffer) {
1424 shi_asprintf(&new_buffer, _("%d"), *references);
1425 } else {
1426 shi_asprintf(&new_buffer, _("%s, %d"), buffer, *references);
1428 if (!new_buffer) {
1429 zfree(buffer);
1430 break;
1432 buffer = new_buffer;
1433 new_buffer = NULL;
1435 } else {
1436 char *id_locale = utf82locale(id);
1437 shi_asprintf(&buffer,
1438 _("<Reference to non-existing document ID `%s'>"), id_locale);
1439 free(id_locale);
1442 if (buffer)
1443 print_header(_("\tRefers to"), buffer);
1444 else
1445 print_header(_("\tRefers to"), _("<Error while formatting reference>"));
1446 free(buffer);
1450 /* Print formatted document
1451 * @references is ordinal number of referred document. Formally it's array
1452 * terminated by -1 because non-well-formed message can have more documents
1453 * with equal IDs */
1454 void format_document(const struct isds_document *document, int order,
1455 int *references) {
1456 int counter_width = 3;
1457 char *filename_locale = NULL;
1459 if (!document) return;
1461 oprintf(_("%*d "), counter_width, order);
1463 if (document->dmFileDescr) {
1464 filename_locale = utf82locale(document->dmFileDescr);
1465 oprintf("%s\n", filename_locale);
1466 free(filename_locale);
1467 } else {
1468 oprintf(_("<Unknown file name>\n"));
1471 if (document->is_xml) {
1472 char *message =NULL;
1473 int nodes = 0;
1475 for (xmlNodePtr node = document->xml_node_list; node;
1476 node = node->next) nodes++;
1477 shi_asprintf(&message, ngettext("%d node", "%d nodes", nodes), nodes);
1478 if (message) {
1479 print_header(_("\tXML document"), message);
1480 free(message);
1482 } else {
1483 print_header_size(_("\tSize"), document->data_length);
1485 print_header(_("\tMIME type"), document->dmMimeType);
1487 print_header(_("\tType"), DmFileMetaType2string(document->dmFileMetaType));
1488 print_header_utf8(_("\tMeta format"), document->dmFormat);
1490 print_header_utf8(_("\tID"), document->dmFileGuid);
1491 format_document_reference(document->dmUpFileGuid, references);
1495 /* Print formatted message documents */
1496 void format_documents(const struct isds_list *documents) {
1497 const struct isds_list *item;
1498 const struct isds_document *document;
1499 int i = 0;
1500 int *references;
1501 if (!documents) return;
1503 oprintf(_("Documents:\n"));
1505 for (item = documents; item; item = item->next) {
1506 if (!item->data) continue;
1507 document = (struct isds_document *) item->data;
1508 references = dmFileGuid2ordinar(documents, document->dmUpFileGuid);
1509 format_document(document, ++i, references);
1510 free(references);
1515 /* Print formatted message */
1516 void format_message(const struct isds_message *message) {
1517 if (!message) return;
1518 format_envelope(message->envelope);
1519 format_documents(message->documents);
1523 /* Print formatted list of message copies */
1524 void format_copies(const struct isds_list *copies) {
1525 const struct isds_list *item;
1526 const struct isds_message_copy *copy;
1527 int i = 0;
1528 int counter_width = 3;
1529 if (!copies) return;
1531 for (item = copies; item; item = item->next) {
1532 if (!item->data) continue;
1533 copy = (struct isds_message_copy *) item->data;
1534 i++;
1536 oprintf(_("%*d Recipient:\n"), counter_width, i);
1537 print_header_utf8(_("\tID"), copy->dbIDRecipient);
1538 print_header_utf8(_("\tUnit"), copy->dmRecipientOrgUnit);
1539 print_header_longint(_("\tUnit number"), copy->dmRecipientOrgUnitNum);
1540 print_header_utf8(_("\tTo hands"), copy->dmToHands);
1545 void print_message_list(const struct isds_list *messages, _Bool outgoing) {
1546 const struct isds_list *item;
1547 struct isds_envelope *envelope;
1548 unsigned long int counter = 0;
1550 int counter_max, id_max = 0, name_max = 0, subject_max = 0;
1551 int counter_width, id_width = 0, flags_width = 2, time_width = 6,
1552 name_width = 0, subject_width = 0;
1554 char *id_locale = NULL, flags_locale[3], *time_locale = NULL,
1555 *name_locale = NULL, *subject_locale = NULL;
1556 int screen_cols;
1557 int width;
1560 /* Compute column widths */
1561 rl_get_screen_size(NULL, &screen_cols);
1563 /* Get real maximal widths */
1564 for (counter = 0, item = messages; item; item = item->next) {
1565 if (!item->data || !((struct isds_message *)item->data)->envelope)
1566 continue;
1567 envelope = ((struct isds_message *) item->data)->envelope;
1568 counter++;
1570 width = utf8width(envelope->dmID);
1571 if (width > id_max) id_max = width;
1573 width = utf8width((outgoing) ?
1574 envelope->dmRecipient : envelope->dmSender);
1575 if (width > name_max) name_max = width;
1577 width = utf8width(envelope->dmAnnotation);
1578 if (width > subject_max) subject_max = width;
1580 counter_max = numberwidth(counter);
1582 /* Correct widths to fit into window */
1583 if (counter_max < 0) counter_width = -3; else counter_width = counter_max;
1584 if (id_max < 0) id_width = -6; else id_width = id_max;
1585 if (name_max < 0) name_width = -20; else name_width = name_max;
1586 if (subject_max < 0) subject_width = -32; else subject_width = subject_max;
1588 width = abs(counter_width) + 1 + abs(id_width) + 1 + abs(flags_width) + 1 +
1589 abs(time_width) + 1 + abs(name_width) + 1 + abs(subject_width);
1590 if (width > screen_cols) {
1591 width -= abs(name_width) + abs(subject_width);
1593 name_width = subject_width = 0;
1594 while (width + name_width + subject_width < screen_cols) {
1595 if (name_width < abs(name_max)) name_width++;
1596 if (subject_width < abs(subject_max)) subject_width++;
1598 if (width + name_width + subject_width > screen_cols) subject_width--;
1601 /* Print header */
1602 /* TRANSLATORS: "No" is abbreviation for "Number" in listing header. */
1603 onprint(pgettext("list header", "No"), counter_width);
1604 oprintf(" ");
1605 onprint(_("ID"), id_width);
1606 oprintf(" ");
1607 onprint(_("Flags"), flags_width);
1608 oprintf(" ");
1609 onprint(_("Delivered"), time_width);
1610 oprintf(" ");
1611 onprint((outgoing) ? _("To") : _("From"), name_width);
1612 oprintf(" ");
1613 onprint(_("Subject"), subject_width);
1614 oprintf("\n");
1615 for (int i = 0; i < screen_cols; i++) oprintf(_("-"));
1616 oprintf("\n");
1618 /* Print the list */
1619 for (counter = 0, item = messages; item; item = item->next) {
1620 envelope = ((struct isds_message *) item->data)->envelope;
1621 counter++;
1623 oprintf(_("%*lu "), counter_width, counter);
1625 if (!envelope) {
1626 oprintf(_("<Missing envelope>\n"));
1627 continue;
1630 id_locale = utf82locale(envelope->dmID);
1631 name_locale = utf82locale((outgoing) ?
1632 envelope->dmRecipient: envelope->dmSender);
1633 flags_locale[0] = DmType2flag(envelope->dmType);
1634 flags_locale[1] = DmMessageStatus2flag(envelope->dmMessageStatus);
1635 flags_locale[2] = '\0';
1636 time_locale = timeval2shortstring(envelope->dmDeliveryTime);
1637 subject_locale = utf82locale(envelope->dmAnnotation);
1639 onprint(id_locale, id_width);
1640 oprintf(" ");
1641 onprint(flags_locale, flags_width);
1642 oprintf(" ");
1643 onprint(time_locale, time_width);
1644 oprintf(" ");
1645 onprint(name_locale, name_width);
1646 oprintf(" ");
1647 onprint(subject_locale, subject_width);
1648 oprintf("\n");
1650 zfree(id_locale);
1651 zfree(time_locale);
1652 zfree(name_locale);
1653 zfree(subject_locale);
1658 static void format_PersonName(const struct isds_PersonName *personName) {
1659 if (!personName) return;
1661 oprintf(_("Person name:\n"));
1662 print_header_utf8(_("\tFirst"), personName->pnFirstName);
1663 print_header_utf8(_("\tMiddle"), personName->pnMiddleName);
1664 print_header_utf8(_("\tLast"), personName->pnLastName);
1665 print_header_utf8(_("\tLast at birth"),
1666 personName->pnLastNameAtBirth);
1670 static void format_BirthInfo(const struct isds_BirthInfo *birth) {
1671 if (!birth || !(birth->biDate || birth->biCity || birth->biCounty
1672 || birth->biState)) return;
1674 oprintf(_("Birth details:\n"));
1676 print_header_tm(_("\tDate"), birth->biDate);
1677 print_header_utf8(_("\tCity"), birth->biCity);
1678 print_header_utf8(_("\tCounty"), birth->biCounty);
1679 print_header_utf8(_("\tState"), birth->biState);
1683 static void format_Address(const struct isds_Address *address) {
1684 if (!address || !(address->adCity || address->adStreet ||
1685 address->adNumberInStreet || address->adNumberInMunicipality ||
1686 address->adZipCode || address->adState)) return;
1688 oprintf(_("Address:\n"));
1689 print_header_utf8(_("\tCity"), address->adCity);
1690 print_header_utf8(_("\tStreet"), address->adStreet);
1691 print_header_utf8(_("\tNumber in street"), address->adNumberInStreet);
1692 print_header_utf8(_("\tNumber in municipality"),
1693 address->adNumberInMunicipality);
1694 print_header_utf8(_("\tZIP code"), address->adZipCode);
1695 print_header_utf8(_("\tState"), address->adState);
1699 /* Return static box state string or NULL if undefined */
1700 const char *DbState2string(const long int *state) {
1701 if (!state) return NULL;
1703 switch(*state) {
1704 case DBSTATE_ACCESSIBLE: return(_("Accessible"));
1705 case DBSTATE_TEMP_UNACCESSIBLE: return(_("Temporary inaccessible"));
1706 case DBSTATE_NOT_YET_ACCESSIBLE: return(_("Not yet accessible"));
1707 case DBSTATE_PERM_UNACCESSIBLE: return(_("Permanently inaccessible"));
1708 case DBSTATE_REMOVED: return(_("Deleted"));
1709 default: return(_("<unknown state>"));
1714 void format_DbOwnerInfo(const struct isds_DbOwnerInfo *info) {
1715 if (!info) return;
1717 print_header_utf8(_("Box ID"), info->dbID);
1718 print_header(_("Type"), DbType2string((long int *) (info->dbType)));
1719 print_header_utf8(_("Subject name"), info->firmName);
1720 print_header_utf8(_("Identity number"), info->ic);
1722 format_PersonName(info->personName);
1723 format_BirthInfo(info->birthInfo);
1725 format_Address(info->address);
1727 print_header_utf8(_("Nationality"), info->nationality);
1728 print_header_utf8(_("E-mail"), info->email);
1729 print_header_utf8(_("Phone"), info->telNumber);
1731 print_header_utf8(_("Identifier"), info->identifier);
1732 print_header_utf8(_("Registry code"), info->registryCode);
1734 print_header(_("State"), DbState2string(info->dbState));
1735 print_header_bool(_("Act as public authority"), info->dbEffectiveOVM);
1736 print_header_bool(_("Receive commercial messages"),
1737 info->dbOpenAddressing);
1741 /* Print formated details about a box found by a full-text */
1742 void format_isds_fulltext_result(const struct isds_fulltext_result *info) {
1743 if (NULL == info) return;
1745 print_header_utf8(_("Box ID"), info->dbID);
1746 print_header(_("Type"), DbType2string((long int *)&(info->dbType)));
1747 print_header_utf8(_("Subject name"), info->name);
1748 print_header_utf8(_("Identity number"), info->ic);
1749 print_header_utf8(_("Address"), info->address);
1750 print_header_tm(_("Birth date"), info->biDate);
1752 print_header_bool(_("Act as public authority"), &info->dbEffectiveOVM);
1753 print_header_bool(_("Active"), &info->active);
1754 print_header_bool(_("Non-commercial message can be sent"),
1755 &info->public_sending);
1756 print_header_bool(_("Commercial message can be sent"),
1757 &info->commercial_sending);
1762 static void format_supervising_firm(const char *ic, const char *firmName) {
1763 if (!ic && !firmName) return;
1765 oprintf(_("Supervising subject:\n"));
1766 print_header_utf8(_("\tIdentity number"), ic);
1767 print_header_utf8(_("\tName"), firmName);
1771 static void format_contact_address(const char *caStreet, const char *caCity,
1772 const char *caZipCode, const char *caState) {
1773 if (!caStreet && !caCity && !caZipCode) return;
1775 oprintf(_("Contact address:\n"));
1776 print_header_utf8(_("\tStreet"), caStreet);
1777 print_header_utf8(_("\tCity"), caCity);
1778 print_header_utf8(_("\tZIP code"), caZipCode);
1779 print_header_utf8(_("\tState"), caState);
1783 void format_DbUserInfo(const struct isds_DbUserInfo *info) {
1784 char *buffer;
1786 if (!info) return;
1788 print_header_utf8(_("User ID"), info->userID);
1789 print_header(_("Type"), UserType2string((long int *) (info->userType)));
1791 buffer = UserPrivils2string(info->userPrivils);
1792 print_header(_("Privileges"), buffer);
1793 zfree(buffer);
1795 format_PersonName(info->personName);
1796 format_Address(info->address);
1798 print_header_tm(_("Birth date"), info->biDate);
1800 format_supervising_firm(info->ic, info->firmName);
1801 format_contact_address(info->caStreet, info->caCity, info->caZipCode,
1802 info->caState);
1806 /* Print formated details about message sender */
1807 void format_sender_info(const char *dbID, const isds_sender_type *type,
1808 const char *raw_type, const char *name) {
1809 const char *type_string;
1811 if (!dbID && !type && !raw_type && !name) return;
1813 oprintf(_("Message sender:\n"));
1814 print_header_utf8(_("\tMessage ID"), dbID);
1816 type_string = isds_sender_type2string(type);
1817 if (type_string)
1818 print_header(_("\tType"), type_string);
1819 else
1820 print_header_utf8(_("\tRaw type"), raw_type);
1822 print_header_utf8(_("\tName"), name);
1826 static const char *credit_event_type2string(
1827 const isds_credit_event_type type) {
1828 switch (type) {
1829 case ISDS_CREDIT_CHARGED: return(_("Credit charged"));
1830 case ISDS_CREDIT_DISCHARGED: return(_("Credit discharged"));
1831 case ISDS_CREDIT_MESSAGE_SENT: return(_("Message sent"));
1832 case ISDS_CREDIT_STORAGE_SET: return(_("Long-term storage set"));
1833 case ISDS_CREDIT_EXPIRED: return(_("Credit expired"));
1834 default: return(_("<Unknown credit event type>"));
1839 /* Print formated details about credit change event */
1840 void format_credit_event(const struct isds_credit_event *event) {
1841 if (NULL == event) return;
1843 print_header_timeval(_("When"), event->time);
1844 print_header_currency(_("Credit change"), &event->credit_change);
1845 print_header_currency(_("Total credit"), &event->new_credit);
1846 print_header(_("Type"), credit_event_type2string(event->type));
1848 switch (event->type) {
1849 case ISDS_CREDIT_CHARGED:
1850 print_header(_("Transation ID"),
1851 event->details.charged.transaction);
1852 break;
1853 case ISDS_CREDIT_DISCHARGED:
1854 print_header(_("Transation ID"),
1855 event->details.discharged.transaction);
1856 break;
1857 case ISDS_CREDIT_MESSAGE_SENT:
1858 print_header(_("Message ID"),
1859 event->details.message_sent.message_id);
1860 print_header(_("Message recipient"),
1861 event->details.message_sent.recipient);
1862 break;
1863 case ISDS_CREDIT_STORAGE_SET:
1864 if (NULL != event->details.storage_set.old_capacity) {
1865 oprintf(_("Old setting:\n"));
1866 oprintf(ngettext("%s: %ld message\n", "%s: %ld messages\n",
1867 *event->details.storage_set.old_capacity),
1868 _("\tCapacity"),
1869 *event->details.storage_set.old_capacity);
1870 print_header_tm(_("\tValid from"),
1871 event->details.storage_set.old_valid_from);
1872 print_header_tm(_("\tValid to"),
1873 event->details.storage_set.old_valid_to);
1875 oprintf(_("New setting:\n"));
1876 oprintf(ngettext("%s: %ld message\n", "%s: %ld messages",
1877 event->details.storage_set.new_capacity),
1878 _("\tCapacity"),
1879 event->details.storage_set.new_capacity);
1880 print_header_tm(_("\tValid from"),
1881 event->details.storage_set.new_valid_from);
1882 print_header_tm(_("\tValid to"),
1883 event->details.storage_set.new_valid_to);
1884 print_header_utf8(_("Initiator"),
1885 event->details.storage_set.initiator);
1886 break;
1887 case ISDS_CREDIT_EXPIRED:
1888 break;
1889 default:
1890 oprintf(_("Details can be missing due to unkown type.\n"));
1895 void format_commercial_permission(
1896 const struct isds_commercial_permission *permission) {
1897 if (NULL == permission) return;
1899 print_header(_("Payment type"),
1900 isds_payment_type2string(&permission->type));
1901 print_header_utf8(_("Allowed recipient box ID"), permission->recipient);
1902 print_header_utf8(_("Payed by owner of box ID"), permission->payer);
1903 print_header_timeval(_("Permission expires"), permission->expiration);
1904 print_header_ulongint(_("Remaining messages"), permission->count);
1905 print_header_utf8(_("Reference to request"), permission->reply_identifier);