Add commercialcredit command
[shigofumi.git] / src / data.c
blob92f4971277ae0a0d21093d39c37f40ec3da243ef
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_DANPOR: oprintf("PFO_DAPOR\n"); break;
37 case DBTYPE_PFO_INSSPR: oprintf("PFO_INSSPR\n"); break;
38 case DBTYPE_PO: oprintf("PO\n"); break;
39 case DBTYPE_PO_ZAK: oprintf("PO_ZAK\n"); break;
40 case DBTYPE_PO_REQ: oprintf("PO_REQ\n"); break;
41 case DBTYPE_OVM: oprintf("OVM\n"); break;
42 case DBTYPE_OVM_NOTAR: oprintf("OVM_NOTAR\n"); break;
43 case DBTYPE_OVM_EXEKUT: oprintf("OVM_EXEKUT\n"); break;
44 case DBTYPE_OVM_REQ: oprintf("OVM_REQ\n"); break;
45 default: oprintf("<unknown type %ld>\n", *type);
50 void print_UserType(const long int *type) {
51 if (!type) oprintf("NULL\n");
52 else
53 switch(*type) {
54 case USERTYPE_PRIMARY: oprintf("PRIMARY\n"); break;
55 case USERTYPE_ENTRUSTED: oprintf("ENTRUSTED\n"); break;
56 case USERTYPE_ADMINISTRATOR: oprintf("ADMINISTRATOR\n"); break;
57 case USERTYPE_OFFICIAL: oprintf("OFFICIAL\n"); break;
58 default: oprintf("<unknown type %ld>\n", *type);
63 void print_UserPrivils(const long int *privils) {
65 const char *priviledges[] = {
66 "READ_NON_PERSONAL",
67 "READ_ALL",
68 "CREATE_DM",
69 "VIEW_INFO",
70 "SEARCH_DB",
71 "OWNER_ADM",
72 "READ_VAULT",
73 "ERASE_VAULT"
75 const int priviledges_count = sizeof(priviledges)/sizeof(priviledges[0]);
77 if (!privils) oprintf("NULL\n");
78 else {
79 oprintf("%ld (", *privils);
81 for (int i = 0; i < priviledges_count; i++) {
82 if (*privils & (1<<i)) {
83 oprintf(
84 ((i + 1) == priviledges_count) ? "%s" : "%s|",
85 priviledges[i]);
89 oprintf(")\n");
94 void print_hash(const struct isds_hash *hash) {
95 if (!hash) {
96 oprintf("NULL\n");
97 return;
100 switch(hash->algorithm) {
101 case HASH_ALGORITHM_MD5: oprintf("MD5 "); break;
102 case HASH_ALGORITHM_SHA_1: oprintf("SHA-1 "); break;
103 case HASH_ALGORITHM_SHA_256: oprintf("SHA-256 "); break;
104 case HASH_ALGORITHM_SHA_512: oprintf("SHA-512 "); break;
105 default: oprintf("<Unknown hash algorithm %d> ", hash->algorithm);
106 break;
109 if (!hash->value) oprintf("<NULL>");
110 else
111 for (int i = 0; i < hash->length; i++) {
112 if (i > 0) oprintf(":");
113 oprintf("%02x", ((uint8_t *)(hash->value))[i]);
116 oprintf("\n");
120 void print_raw_type(const isds_raw_type type) {
121 switch(type) {
122 case RAWTYPE_INCOMING_MESSAGE:
123 oprintf("INCOMING_MESSAGE\n"); break;
124 case RAWTYPE_PLAIN_SIGNED_INCOMING_MESSAGE:
125 oprintf("PLAIN_SIGNED_INCOMING_MESSAGE\n"); break;
126 case RAWTYPE_CMS_SIGNED_INCOMING_MESSAGE:
127 oprintf("CMS_SIGNED_INCOMING_MESSAGE\n"); break;
128 case RAWTYPE_PLAIN_SIGNED_OUTGOING_MESSAGE:
129 oprintf("PLAIN_SIGNED_OUTGOING_MESSAGE\n"); break;
130 case RAWTYPE_CMS_SIGNED_OUTGOING_MESSAGE:
131 oprintf("CMS_SIGNED_OUTGOING_MESSAGE\n"); break;
132 case RAWTYPE_DELIVERYINFO:
133 oprintf("DELIVERYINFO\n"); break;
134 case RAWTYPE_PLAIN_SIGNED_DELIVERYINFO:
135 oprintf("PLAIN_SIGNED_DELIVERYINFO\n"); break;
136 case RAWTYPE_CMS_SIGNED_DELIVERYINFO:
137 oprintf("CMS_SIGNED_DELIVERYINFO\n"); break;
138 default:
139 oprintf("<Unknown raw type %d> ", type);
140 break;
145 void print_bool(const _Bool *boolean) {
146 oprintf("%s\n", (!boolean) ? "NULL" : ((*boolean)? "true" : "false") );
150 void print_longint(const long int *number) {
151 if (!number) oprintf("NULL\n");
152 else oprintf("%ld\n", *number);
156 void print_PersonName(const struct isds_PersonName *personName) {
157 oprintf("\tpersonName = ");
158 if (!personName) oprintf("NULL\n");
159 else {
160 oprintf("{\n");
161 oprintf("\t\tpnFirstName = %s\n", personName->pnFirstName);
162 oprintf("\t\tpnMiddleName = %s\n", personName->pnMiddleName);
163 oprintf("\t\tpnLastName = %s\n", personName->pnLastName);
164 oprintf("\t\tpnLastNameAtBirth = %s\n", personName->pnLastNameAtBirth);
165 oprintf("\t}\n");
170 void print_Address(const struct isds_Address *address) {
171 oprintf("\taddress = ");
172 if (!address) oprintf("NULL\n");
173 else {
174 oprintf("{\n");
175 oprintf("\t\tadCity = %s\n", address->adCity);
176 oprintf("\t\tadStreet = %s\n", address->adStreet);
177 oprintf("\t\tadNumberInStreet = %s\n", address->adNumberInStreet);
178 oprintf("\t\tadNumberInMunicipality = %s\n",
179 address->adNumberInMunicipality);
180 oprintf("\t\tadZipCode = %s\n", address->adZipCode);
181 oprintf("\t\tadState = %s\n", address->adState);
182 oprintf("\t}\n");
187 void print_date(const struct tm *date) {
188 if (!date) oprintf("NULL\n");
189 else oprintf("%s", asctime(date));
193 void print_DbOwnerInfo(const struct isds_DbOwnerInfo *info) {
194 oprintf("dbOwnerInfo = ");
196 if (!info) {
197 oprintf("NULL\n");
198 return;
201 oprintf("{\n");
202 oprintf("\tdbID = %s\n", info->dbID);
204 oprintf("\tdbType = ");
205 print_DbType((long int *) (info->dbType));
206 oprintf("\tic = %s\n", info->ic);
208 print_PersonName(info->personName);
210 oprintf("\tfirmName = %s\n", info->firmName);
212 oprintf("\tbirthInfo = ");
213 if (!info->birthInfo) oprintf("NULL\n");
214 else {
215 oprintf("{\n");
217 oprintf("\t\tbiDate = ");
218 print_date(info->birthInfo->biDate);
220 oprintf("\t\tbiCity = %s\n", info->birthInfo->biCity);
221 oprintf("\t\tbiCounty = %s\n", info->birthInfo->biCounty);
222 oprintf("\t\tbiState = %s\n", info->birthInfo->biState);
223 oprintf("\t}\n");
226 print_Address(info->address);
228 oprintf("\tnationality = %s\n", info->nationality);
229 oprintf("\temail = %s\n", info->email);
230 oprintf("\ttelNumber = %s\n", info->telNumber);
231 oprintf("\tidentifier = %s\n", info->identifier);
232 oprintf("\tregistryCode = %s\n", info->registryCode);
234 oprintf("\tdbState = ");
235 if (!info->dbState) oprintf("NULL\n");
236 else print_DbState(*(info->dbState));
238 oprintf("\tdbEffectiveOVM = ");
239 print_bool(info->dbEffectiveOVM);
241 oprintf("\tdbOpenAddressing = ");
242 print_bool(info->dbOpenAddressing);
244 oprintf("}\n");
249 void print_DbUserInfo(const struct isds_DbUserInfo *info) {
250 oprintf("dbUserInfo = ");
252 if (!info) {
253 oprintf("NULL\n");
254 return;
257 oprintf("{\n");
258 oprintf("\tuserID = %s\n", info->userID);
260 oprintf("\tuserType = ");
261 print_UserType((long int *) (info->userType));
263 oprintf("\tuserPrivils = ");
264 print_UserPrivils(info->userPrivils);
266 print_PersonName(info->personName);
267 print_Address(info->address);
269 oprintf("\tbiDate = ");
270 print_date(info->biDate);
272 oprintf("\tic = %s\n", info->ic);
273 oprintf("\tfirmName = %s\n", info->firmName);
275 oprintf("\tcaStreet = %s\n", info->caStreet);
276 oprintf("\tcaCity = %s\n", info->caCity);
277 oprintf("\tcaZipCode = %s\n", info->caZipCode);
279 oprintf("}\n");
283 void print_timeval(const struct timeval *time) {
284 struct tm broken;
285 char buffer[128];
287 if (!time) {
288 oprintf("NULL\n");
289 return;
292 if (!localtime_r(&(time->tv_sec), &broken)) goto error;
293 if (!strftime(buffer, sizeof(buffer)/sizeof(char), "%c", &broken))
294 goto error;
295 oprintf("%s, %ld us\n", buffer, time->tv_usec);
296 return;
298 error:
299 oprintf("<Error while formatting>\n>");
300 return;
304 void print_event_type(const isds_event_type *type) {
305 if (!type) {
306 oprintf("NULL");
307 return;
309 switch (*type) {
310 case EVENT_UKNOWN: oprintf("UNKNOWN\n"); break;
311 case EVENT_ENTERED_SYSTEM: printf("ENTERED_SYSTEM\n"); break;
312 case EVENT_ACCEPTED_BY_RECIPIENT:
313 oprintf("ACCEPTED_BY_RECIPIENT\n"); break;
314 case EVENT_ACCEPTED_BY_FICTION:
315 oprintf("DELIVERED_BY_FICTION\n"); break;
316 case EVENT_UNDELIVERABLE:
317 oprintf("UNDELIVERABLE\n"); break;
318 case EVENT_COMMERCIAL_ACCEPTED:
319 oprintf("COMMERCIAL_ACCEPTED\n"); break;
320 case EVENT_DELIVERED:
321 oprintf("DELIVERED\n"); break;
322 case EVENT_PRIMARY_LOGIN:
323 oprintf("PRIMARY_LOGIN\n"); break;
324 case EVENT_ENTRUSTED_LOGIN:
325 oprintf("ENTRUSTED_LOGIN\n"); break;
326 case EVENT_SYSCERT_LOGIN:
327 oprintf("SYSCERT_LOGIN\n"); break;
328 default: oprintf("<unknown type %d>\n", *type);
333 void print_events(const struct isds_list *events) {
334 const struct isds_list *item;
335 const struct isds_event *event;
337 if (!events) {
338 oprintf("NULL\n");
339 return;
342 oprintf("{\n");
344 for (item = events; item; item = item->next) {
345 event = (struct isds_event *) item->data;
346 oprintf("\t\t\tevent = ");
347 if (!event) oprintf("NULL");
348 else {
349 oprintf("{\n");
351 oprintf("\t\t\t\ttype = ");
352 print_event_type(event->type);
354 oprintf("\t\t\t\tdescription = %s\n", event->description);
356 oprintf("\t\t\t\ttime = ");
357 print_timeval(event->time);
359 oprintf("\t\t\t}\n");
363 oprintf("\t\t}\n");
367 void print_envelope(const struct isds_envelope *envelope) {
368 oprintf("\tenvelope = ");
370 if (!envelope) {
371 oprintf("NULL\n");
372 return;
374 oprintf("{\n");
376 oprintf("\t\tdmID = %s\n", envelope->dmID);
377 oprintf("\t\tdbIDSender = %s\n", envelope->dbIDSender);
378 oprintf("\t\tdmSender = %s\n", envelope->dmSender);
379 oprintf("\t\tdmSenderAddress = %s\n", envelope->dmSenderAddress);
380 oprintf("\t\tdmSenderType = ");
381 print_DbType(envelope->dmSenderType);
382 oprintf("\t\tdmRecipient = %s\n", envelope->dmRecipient);
383 oprintf("\t\tdmRecipientAddress = %s\n", envelope->dmRecipientAddress);
384 oprintf("\t\tdmAmbiguousRecipient = ");
385 print_bool(envelope->dmAmbiguousRecipient);
386 oprintf("\t\tdmType = %s\n", envelope->dmType);
388 oprintf("\t\tdmSenderOrgUnit = %s\n", envelope->dmSenderOrgUnit);
389 oprintf("\t\tdmSenderOrgUnitNum = ");
390 print_longint(envelope->dmSenderOrgUnitNum);
391 oprintf("\t\tdbIDRecipient = %s\n", envelope->dbIDRecipient);
392 oprintf("\t\tdmRecipientOrgUnit = %s\n", envelope->dmRecipientOrgUnit);
393 oprintf("\t\tdmRecipientOrgUnitNum = ");
394 print_longint(envelope->dmRecipientOrgUnitNum);
395 oprintf("\t\tdmToHands = %s\n", envelope->dmToHands);
396 oprintf("\t\tdmAnnotation = %s\n", envelope->dmAnnotation);
397 oprintf("\t\tdmRecipientRefNumber = %s\n", envelope->dmRecipientRefNumber);
398 oprintf("\t\tdmSenderRefNumber = %s\n", envelope->dmSenderRefNumber);
399 oprintf("\t\tdmRecipientIdent = %s\n", envelope->dmRecipientIdent);
400 oprintf("\t\tdmSenderIdent = %s\n", envelope->dmSenderIdent);
402 oprintf("\t\tdmLegalTitleLaw = ");
403 print_longint(envelope->dmLegalTitleLaw);
404 oprintf("\t\tdmLegalTitleYear = ");
405 print_longint(envelope->dmLegalTitleYear);
406 oprintf("\t\tdmLegalTitleSect = %s\n", envelope->dmLegalTitleSect);
407 oprintf("\t\tdmLegalTitlePar = %s\n", envelope->dmLegalTitlePar);
408 oprintf("\t\tdmLegalTitlePoint = %s\n", envelope->dmLegalTitlePoint);
410 oprintf("\t\tdmPersonalDelivery = ");
411 print_bool(envelope->dmPersonalDelivery);
412 oprintf("\t\tdmAllowSubstDelivery = ");
413 print_bool(envelope->dmAllowSubstDelivery);
414 oprintf("\t\tdmOVM = ");
415 print_bool(envelope->dmOVM);
416 oprintf("\t\tdmPublishOwnID = ");
417 print_bool(envelope->dmPublishOwnID);
419 oprintf("\t\tdmOrdinal = ");
420 if (!envelope->dmOrdinal) oprintf("NULL\n");
421 else oprintf("%lu\n", *(envelope->dmOrdinal));
423 oprintf("\t\tdmMessageStatus = ");
424 if (!envelope->dmMessageStatus) oprintf("NULL\n");
425 else
426 switch(*(envelope->dmMessageStatus)) {
427 case MESSAGESTATE_SENT: oprintf("SENT\n"); break;
428 case MESSAGESTATE_STAMPED: oprintf("STAMPED\n"); break;
429 case MESSAGESTATE_INFECTED: oprintf("INFECTED\n"); break;
430 case MESSAGESTATE_DELIVERED: oprintf("DELIVERED\n"); break;
431 case MESSAGESTATE_SUBSTITUTED: oprintf("SUBSTITUTED\n"); break;
432 case MESSAGESTATE_RECEIVED: oprintf("RECEIVED\n"); break;
433 case MESSAGESTATE_READ: oprintf("READ\n"); break;
434 case MESSAGESTATE_UNDELIVERABLE: oprintf("UNDELIVERABLE\n"); break;
435 case MESSAGESTATE_REMOVED: oprintf("REMOVED\n"); break;
436 case MESSAGESTATE_IN_SAFE: oprintf("IN_SAFE\n"); break;
437 default: oprintf("<unknown type %d>\n",
438 *(envelope->dmMessageStatus));
441 oprintf("\t\tdmAttachmentSize = ");
442 if (!envelope->dmAttachmentSize) oprintf("NULL\n");
443 else oprintf("%lu kB\n", *(envelope->dmAttachmentSize));
445 oprintf("\t\tdmDeliveryTime = ");
446 print_timeval(envelope->dmDeliveryTime);
448 oprintf("\t\tdmAcceptanceTime = ");
449 print_timeval(envelope->dmAcceptanceTime);
451 oprintf("\t\thash = ");
452 print_hash(envelope->hash);
454 oprintf("\t\ttimestamp = %p\n", envelope->timestamp);
455 oprintf("\t\ttimestamp_length = %zu\n", envelope->timestamp_length);
457 oprintf("\t\tevents = ");
458 print_events(envelope->events);
460 oprintf("\t}\n");
464 void print_document(const struct isds_document *document) {
465 oprintf("\t\tdocument = ");
467 if (!document) {
468 oprintf("NULL\n");
469 return;
471 oprintf("\{\n");
473 oprintf("\t\t\tis_xml = %u\n", !!document->is_xml);
474 oprintf("\t\t\txml_node_list = %p\n", document->xml_node_list);
476 oprintf("\t\t\tdata = %p\n", document->data);
477 oprintf("\t\t\tdata_length = %zu\n", document->data_length);
478 oprintf("\t\t\tdmMimeType = %s\n", document->dmMimeType);
480 oprintf("\t\t\tdmFileMetaType = ");
481 switch(document->dmFileMetaType) {
482 case FILEMETATYPE_MAIN: oprintf("MAIN\n"); break;
483 case FILEMETATYPE_ENCLOSURE: oprintf("ENCLOSURE\n"); break;
484 case FILEMETATYPE_SIGNATURE: oprintf("SIGNATURE\n"); break;
485 case FILEMETATYPE_META: oprintf("META\n"); break;
486 default: oprintf("<unknown type %d>\n", document->dmFileMetaType);
489 oprintf("\t\t\tdmFileGuid = %s\n", document->dmFileGuid);
490 oprintf("\t\t\tdmUpFileGuid = %s\n", document->dmUpFileGuid);
491 oprintf("\t\t\tdmFileDescr = %s\n", document->dmFileDescr);
492 oprintf("\t\t\tdmFormat = %s\n", document->dmFormat);
493 oprintf("\t\t}\n");
497 void print_documents(const struct isds_list *documents) {
498 const struct isds_list *item;
500 oprintf("\tdocuments = ");
502 if (!documents) {
503 oprintf("NULL\n");
504 return;
506 oprintf("{\n");
508 for (item = documents; item; item = item->next) {
509 print_document((struct isds_document *) (item->data));
512 oprintf("\t}\n");
516 void print_message(const struct isds_message *message) {
517 oprintf("message = ");
519 if (!message) {
520 oprintf("NULL\n");
521 return;
524 oprintf("{\n");
526 oprintf("\traw = %p\n", message->raw);
527 oprintf("\traw_length = %zu\n", message->raw_length);
528 oprintf("\traw_type = ");
529 print_raw_type(message->raw_type);
530 print_envelope(message->envelope);
531 print_documents(message->documents);
533 oprintf("}\n");
536 void print_copies(const struct isds_list *copies) {
537 const struct isds_list *item;
538 struct isds_message_copy *copy;
540 oprintf("Copies = ");
541 if (!copies) {
542 oprintf("<NULL>\n");
543 return;
546 oprintf("{\n");
547 for (item = copies; item; item = item->next) {
548 copy = (struct isds_message_copy *) item->data;
549 oprintf("\tCopy = ");
551 if (!copy)
552 oprintf("<NULL>\n");
553 else {
554 oprintf("{\n");
555 oprintf("\t\tdbIDRecipient = %s\n", copy->dbIDRecipient);
556 oprintf("\t\tdmRecipientOrgUnit = %s\n", copy->dmRecipientOrgUnit);
558 oprintf("\t\tdmRecipientOrgUnitNum = ");
559 if (copy->dmRecipientOrgUnitNum)
560 oprintf("%ld\n", *copy->dmRecipientOrgUnitNum);
561 else
562 oprintf("<NULL>\n");
563 oprintf("\t\tdmToHands = %s\n", copy->dmToHands);
565 oprintf("\t\terror = %s\n", isds_strerror(copy->error));
566 oprintf("\t\tdmStatus = %s\n", copy->dmStatus);
567 oprintf("\t\tdmID = %s\n", copy->dmID);
568 oprintf("\t}\n");
571 oprintf("}\n");
575 void compare_hashes(const struct isds_hash *hash1,
576 const struct isds_hash *hash2) {
577 isds_error err;
579 oprintf("Comparing hashes... ");
580 err = isds_hash_cmp(hash1, hash2);
581 if (err == IE_SUCCESS)
582 oprintf("Hashes equal\n");
583 else if
584 (err == IE_NOTEQUAL) oprintf("Hashes differ\n");
585 else
586 oprintf("isds_hash_cmp() failed: %s\n", isds_strerror(err));
590 int progressbar(double upload_total, double upload_current,
591 double download_total, double download_current,
592 void *data) {
594 oprintf("Progress: upload %0f/%0f, download %0f/%0f, data=%p\n",
595 upload_current, upload_total, download_current, download_total,
596 data);
597 return 0;
601 /* Print formatted header if locale-encoded value is defined.
602 * @header is locale encoded header name
603 * @value is locale encoded header value */
604 void print_header(const char *header, const char *value) {
605 if (value && *value) oprintf(_("%s: %s\n"), header, value);
609 /* Print formatted header if boolean value is defined.
610 * @header is locale encoded header name */
611 void print_header_bool(const char *header, const _Bool *value) {
612 if (value) print_header(header, (*value) ? _("Yes") : _("No"));
616 /* Print formatted header if long int value is defined.
617 * @header is locale encoded header name */
618 void print_header_longint(const char *header, const long int *value) {
619 if (value) oprintf(_("%s: %ld\n"), header, *value);
623 /* Print formatted header if unsigned long int value is defined.
624 * @header is locale encoded header name */
625 void print_header_ulongint(const char *header, const unsigned long int *value) {
626 if (value) oprintf(_("%s: %lu\n"), header, *value);
630 /* Print formatted header if time value is defined.
631 * @header is locale encoded header name */
632 void print_header_timeval(const char *header, const struct timeval *time) {
633 struct tm broken;
634 char buffer[128];
636 if (!time) return;
638 if (!localtime_r(&(time->tv_sec), &broken)) goto error;
639 if (!strftime(buffer, sizeof(buffer)/sizeof(char), "%c", &broken))
640 goto error;
642 if (!time->tv_usec)
643 oprintf(_("%s: %s\n"), header, buffer);
644 else if ((time->tv_usec % 1000) == 0)
645 oprintf(_("%s: %s, %ld ms\n"), header, buffer, time->tv_usec/1000);
646 else
647 oprintf(_("%s: %s, %ld us\n"), header, buffer, time->tv_usec);
649 return;
651 error:
652 oprintf(_("%s: <Error while formatting time>\n"), header);
653 return;
657 /* Return formatted date as mallocated string. NULL or special error string can
658 * be returned. Application must free even the error string. */
659 char *tm2string(const struct tm *date) {
660 char *buffer;
661 size_t buffer_length = 128;
663 if (!date) return NULL;
665 buffer = malloc(buffer_length);
666 if (!buffer) return strdup(_("<Error while formatting date>"));
668 if (0 == strftime(buffer, buffer_length, "%x", date)) {
669 free(buffer);
670 return strdup(_("<Error while formatting date>"));
673 return buffer;
677 /* Convert string representation of full ISO 8601 or locale date to tm structure.
678 * Return NULL if error occurs
679 * XXX: Not all ISO formats are supported */
680 struct tm *datestring2tm(const char *string) {
681 struct tm *date = NULL;
682 char *offset;
683 if (!string) return NULL;
685 date = calloc(1, sizeof(*date));
686 if (!date) return NULL;
688 /* xsd:date is ISO 8601 string, thus ASCII */
689 offset = strptime(string, "%Y-%m-%d", date);
690 if (offset && *offset == '\0')
691 return date;
693 offset = strptime(string, "%x", date);
694 if (offset && *offset == '\0')
695 return date;
697 free(date);
698 return NULL;
702 /* Print formatted header if date value is defined.
703 * @header is locale encoded header name */
704 void print_header_tm(const char *header, const struct tm *date) {
705 char *string;
707 if (NULL == date) return;
708 string = tm2string(date);
710 if (NULL == string)
711 oprintf(_("%s: <Error while formatting date>\n"), header);
712 else
713 print_header(header, string);
715 free(string);
719 /* Print formatted header if UTF-8 value is defined.
720 * @header is locale encoded header name
721 * @value is UTF-8 encoded header value */
722 void print_header_utf8(const char *header, const char *value) {
723 char *value_locale;
725 if (!value) return;
727 value_locale = utf82locale(value);
728 print_header(header,
729 (value_locale) ?
730 value_locale :
731 _("<Error while converting value>"));
732 free(value_locale);
736 /* Print formatted header and byte size.
737 * @header is locale encoded header name */
738 void print_header_size(const char *header, size_t size) {
739 char *buffer = NULL;
741 if (size < (1<<10))
742 shi_asprintf(&buffer, _("%zu B"), size);
743 else if (size < (1<<20))
744 shi_asprintf(&buffer, _("%0.2f KiB"), (float) size/(1<<10));
745 else
746 shi_asprintf(&buffer, _("%0.2f MiB"), (float) size/(1<<20));
748 print_header(header, buffer);
749 free(buffer);
753 /* Print formatted header if long int KB size is defined.
754 * @header is locale encoded header name */
755 void print_header_kbsize(const char *header, const long int *size) {
756 char *buffer = NULL;
757 if (!size) return;
759 if (*size < 0)
760 shi_asprintf(&buffer, _("<Negative size>"));
761 else if (*size < (1000))
762 shi_asprintf(&buffer, _("%lu kB"), *size);
763 else
764 shi_asprintf(&buffer, _("%0.2f MB"), *size/1000.0);
766 print_header(header, buffer);
767 free(buffer);
771 static const char *DbType2string(const long int *type) {
772 if (!type) return NULL;
773 switch(*type) {
774 case DBTYPE_SYSTEM: return(_("System"));
775 case DBTYPE_FO: return(_("Private individual"));
776 case DBTYPE_PFO: return(_("Self-employed individual"));
777 case DBTYPE_PFO_ADVOK: return(_("Lawyer"));
778 case DBTYPE_PFO_DANPOR: return(_("Tax advisor"));
779 case DBTYPE_PFO_INSSPR: return(_("Insolvency administrator"));
780 case DBTYPE_PO: return(_("Organisation"));
781 case DBTYPE_PO_ZAK: return(_("Organization based by law"));
782 case DBTYPE_PO_REQ: return(_("Organization based on request"));
783 case DBTYPE_OVM: return(_("Public authority"));
784 case DBTYPE_OVM_NOTAR: return(_("Notary"));
785 case DBTYPE_OVM_EXEKUT: return(_("Executor"));
786 case DBTYPE_OVM_REQ: return(_("Public authority based on request"));
787 default: return(_("<Unknown type>"));
792 static const char *UserType2string(const long int *type) {
793 if (!type) return NULL;
794 switch(*type) {
795 case USERTYPE_PRIMARY: return(_("Primary"));
796 case USERTYPE_ENTRUSTED: return(_("Entrusted"));
797 case USERTYPE_ADMINISTRATOR: return(_("Administrator"));
798 case USERTYPE_OFFICIAL: return(_("Official"));
799 default: return(_("<Unknown type>"));
804 static const char *isds_sender_type2string(const isds_sender_type *type) {
805 if (!type) return NULL;
806 switch(*type) {
807 case SENDERTYPE_PRIMARY: return(_("Primary"));
808 case SENDERTYPE_ENTRUSTED: return(_("Entrusted"));
809 case SENDERTYPE_ADMINISTRATOR: return(_("Administrator"));
810 case SENDERTYPE_OFFICIAL: return(_("Official"));
811 case SENDERTYPE_VIRTUAL: return(_("Virtual"));
812 default: return(_("<unknown type>"));
817 /* Return formatted user privileges. Caller must free the string */
818 static char *UserPrivils2string(const long int *privils) {
820 const char *priviledges[] = {
821 N_("Read non-personal"),
822 N_("Read all"),
823 N_("Send and read sent"),
824 N_("List messages and read delivery details"),
825 N_("Search boxes"),
826 N_("Administer her box"),
827 N_("Read from safe"),
828 N_("Delete from safe")
830 const int priviledges_count = sizeof(priviledges)/sizeof(priviledges[0]);
831 char *buffer = NULL, *new_buffer = NULL;
833 if (!privils) return NULL;
835 /*oprintf("%ld (", *privils);*/
837 for (int i = 0; i < priviledges_count; i++) {
838 if (*privils & (1<<i)) {
839 if ((*privils % (1<<i)))
840 shi_asprintf(&new_buffer, _("%s, %s"),
841 buffer, _(priviledges[i]));
842 else
843 shi_asprintf(&new_buffer, "%s", _(priviledges[i]));
845 if (!new_buffer) {
846 free(buffer);
847 return(strdup(_("<Error while formatting privileges>")));
850 free(buffer);
851 buffer = new_buffer;
852 new_buffer = NULL;
856 if (*privils >= (1<<priviledges_count)) {
857 if ((*privils % (1<<priviledges_count)))
858 shi_asprintf(&new_buffer, _("%s, %s"),
859 buffer, _("<Unknown privilege>"));
860 else
861 shi_asprintf(&new_buffer, "%s", _("<Unknown privilege>"));
863 if (!new_buffer) {
864 free(buffer);
865 return(strdup(_("<Error while formatting privileges>")));
868 free(buffer);
869 buffer = new_buffer;
870 new_buffer = NULL;
873 return buffer;
877 static const char *DmType2string(const char *type) {
878 if (!type) return NULL;
879 if (!strcmp(type, "V"))
880 return(_("Public"));
881 else if (!strcmp(type, "K"))
882 return(_("Commercial"));
883 else if (!strcmp(type, "A"))
884 return(_("Commercial (initiatory, unused, subsidized)"));
885 else if (!strcmp(type, "B"))
886 return(_("Commercial (initiatory, used, subsidized)"));
887 else if (!strcmp(type, "C"))
888 return(_("Commercial (initiatory, expired, subsidized)"));
889 else if (!strcmp(type, "D"))
890 return(_("Commercial (externally subsidized)"));
891 else if (!strcmp(type, "E"))
892 return(_("Commercial (prepaid by a stamp)"));
893 else if (!strcmp(type, "G"))
894 return(_("Commercial (sponsored)"));
895 else if (!strcmp(type, "I"))
896 return(_("Commercial (initiatory, unused, paid by sender)"));
897 else if (!strcmp(type, "O"))
898 return(_("Commercial (response paid by recipient)"));
899 else if (!strcmp(type, "X"))
900 return(_("Commercial (initiatory, expired, paid by sender)"));
901 else if (!strcmp(type, "Y"))
902 return(_("Commercial (initiatory, used, paid by sender)"));
903 else if (!strcmp(type, "Z"))
904 return(_("Commercial (limitedly subsidized)"));
905 else return(_("<Unknown type>"));
909 /* Simplified commercial status printed on message listing.
910 * 'P' is a public message sent by a government
911 * 'C' is a commercial message
912 * 'I' is a commercial message offering to pay response instead of the
913 * responder
914 * 'i' is a commercial message that offered to pay reposne, but it does not
915 * anymore.
916 * 'R' is a commercial response message paid by sender of the I message. */
917 static const char DmType2flag(const char *type) {
918 if (!type) return ' ';
919 if (!strcmp(type, "V")) return('P');
920 else if (!strcmp(type, "K")) return('C');
921 else if (!strcmp(type, "A")) return('I');
922 else if (!strcmp(type, "B")) return('i');
923 else if (!strcmp(type, "C")) return('i');
924 else if (!strcmp(type, "D")) return('C');
925 else if (!strcmp(type, "E")) return('C');
926 else if (!strcmp(type, "G")) return('C');
927 else if (!strcmp(type, "I")) return('I');
928 else if (!strcmp(type, "O")) return('R');
929 else if (!strcmp(type, "X")) return('i');
930 else if (!strcmp(type, "Y")) return('i');
931 else if (!strcmp(type, "Z")) return('C');
932 else return('?');
936 static const char *DmMessageStatus2string(const isds_message_status *status) {
937 if (!status) return NULL;
938 switch(*status) {
939 case MESSAGESTATE_SENT: return(_("Sent"));
940 case MESSAGESTATE_STAMPED: return(_("Stamped"));
941 case MESSAGESTATE_INFECTED: return(_("Infected"));
942 case MESSAGESTATE_DELIVERED: return(_("Delivered ordinary"));
943 case MESSAGESTATE_SUBSTITUTED: return(_("Delivered substitutably"));
944 case MESSAGESTATE_RECEIVED: return(_("Accepted"));
945 case MESSAGESTATE_READ: return(_("Read"));
946 case MESSAGESTATE_UNDELIVERABLE: return(_("Undeliverable"));
947 case MESSAGESTATE_REMOVED: return(_("Deleted"));
948 case MESSAGESTATE_IN_SAFE: return(_("Stored in safe"));
949 default: return(_("<Unknown state>"));
954 static const char DmMessageStatus2flag(const isds_message_status *status) {
955 if (!status) return ' ';
956 switch(*status) {
957 case MESSAGESTATE_SENT: return('>');
958 case MESSAGESTATE_STAMPED: return('t');
959 case MESSAGESTATE_INFECTED: return('I');
960 case MESSAGESTATE_DELIVERED: return('N');
961 case MESSAGESTATE_SUBSTITUTED: return('n');
962 case MESSAGESTATE_RECEIVED: return('O');
963 case MESSAGESTATE_READ: return(' ');
964 case MESSAGESTATE_UNDELIVERABLE: return('!');
965 case MESSAGESTATE_REMOVED: return('D');
966 case MESSAGESTATE_IN_SAFE: return('S');
967 default: return('?');
972 /* Return timeval time formatted into shortest string with respect to current
973 * time. Caller must free the string. */
974 static char *timeval2shortstring(const struct timeval *timeval) {
975 struct tm broken, current_broken;
976 time_t current_time;
977 char *buffer = NULL;
978 const size_t buffer_size = 16;
980 if (!timeval) return NULL;
982 buffer = malloc(buffer_size);
983 if (!buffer) goto error;
985 /* Get current time */
986 current_time = time(NULL);
987 if (current_time == (time_t) -1) goto error;
988 if (!localtime_r(&current_time, &current_broken)) goto error;
990 /* Get broken time */
991 if (!localtime_r(&(timeval->tv_sec), &broken)) goto error;
993 /* Select proper abbreviated string representation */
994 if (broken.tm_year == current_broken.tm_year &&
995 broken.tm_yday == current_broken.tm_yday) {
996 /* Minute resolution in the same day */
997 if (!strftime(buffer, buffer_size, _("%k:%M"), &broken))
998 goto error;
999 } else {
1000 /* Otherwise month and day */
1001 if (!strftime(buffer, buffer_size, _("%b %d"), &broken))
1002 goto error;
1005 return buffer;
1007 error:
1008 free(buffer);
1009 return strdup(_("<Error>"));
1013 /* Formatted Law Authorization if defined. You must free it. */
1014 static char *envelope_law2string(const struct isds_envelope *envelope) {
1015 char *output = NULL;
1016 char *year_locale = NULL, *law_locale = NULL;
1017 char *sect_locale = NULL, *par_locale = NULL, *point_locale = NULL;
1019 if (!envelope ||
1020 !(envelope->dmLegalTitleYear || envelope->dmLegalTitleLaw ||
1021 envelope->dmLegalTitleSect || envelope->dmLegalTitlePar ||
1022 envelope->dmLegalTitlePoint)
1023 ) return NULL;
1025 if (envelope->dmLegalTitleYear)
1026 shi_asprintf(&year_locale, "%ld", *envelope->dmLegalTitleYear);
1027 else
1028 year_locale = strdup(_("?"));
1030 if (envelope->dmLegalTitleLaw)
1031 shi_asprintf(&law_locale, "%ld", *envelope->dmLegalTitleLaw);
1032 else
1033 law_locale = strdup(_("?"));
1035 sect_locale = utf82locale(envelope->dmLegalTitleSect);
1036 par_locale = utf82locale(envelope->dmLegalTitlePar);
1037 point_locale = utf82locale(envelope->dmLegalTitlePoint);
1039 if (point_locale)
1040 shi_asprintf(&output, _("point %s, par. %s, sect. %s, %s/%s Coll."),
1041 point_locale, par_locale, sect_locale,
1042 law_locale, year_locale);
1043 else if (par_locale)
1044 shi_asprintf(&output, _("par. %s, sect. %s, %s/%s Coll."),
1045 par_locale, sect_locale, law_locale, year_locale);
1046 else if (sect_locale)
1047 shi_asprintf(&output, _("sect. %s, %s/%s Coll."),
1048 sect_locale, law_locale, year_locale);
1049 else
1050 shi_asprintf(&output, _("%s/%s Coll."),
1051 law_locale, year_locale);
1053 free(year_locale);
1054 free(law_locale);
1055 free(sect_locale);
1056 free(par_locale);
1057 free(point_locale);
1058 return output;
1062 static const char *isds_payment_type2string(const isds_payment_type *type) {
1063 if (!type) return NULL;
1064 switch(*type) {
1065 case PAYMENT_SENDER: return(_("Payed by sender"));
1066 case PAYMENT_STAMP: return(_("Stamp pre-paid by sender"));
1067 case PAYMENT_SPONSOR: return(_("Sponsor pays all messages"));
1068 case PAYMENT_RESPONSE: return(_("Recipient pays a response"));
1069 case PAYMENT_SPONSOR_LIMITED: return(_("Limitedly subsidized"));
1070 case PAYMENT_SPONSOR_EXTERNAL: return(_("Externally subsidized"));
1071 default: return(_("<unknown type>"));
1076 /* Print formatted header if time any of message ID.
1077 * @header is locale encoded header name */
1078 static void print_header_messages_ids(const char *header,
1079 const char *ref_number, const char *ident) {
1080 if (ref_number || ident) {
1081 oprintf(_("%s:\n"), header);
1082 print_header_utf8(_("\tReference number"), ref_number);
1083 print_header_utf8(_("\tFile ID"), ident);
1088 /* Return formatted hash value */
1089 char *hash2string(const struct isds_hash *hash) {
1090 const char *algorithm_string = NULL;
1091 char *buffer = NULL, *octet = NULL, *new_buffer = NULL;
1093 if (!hash || !hash->value) return NULL;
1095 switch(hash->algorithm) {
1096 case HASH_ALGORITHM_MD5: algorithm_string = (_("MD5")); break;
1097 case HASH_ALGORITHM_SHA_1: algorithm_string = (_("SHA-1")); break;
1098 case HASH_ALGORITHM_SHA_224: algorithm_string = (_("SHA-224")); break;
1099 case HASH_ALGORITHM_SHA_256: algorithm_string = (_("SHA-256")); break;
1100 case HASH_ALGORITHM_SHA_384: algorithm_string = (_("SHA-384")); break;
1101 case HASH_ALGORITHM_SHA_512: algorithm_string = (_("SHA-512")); break;
1102 default: algorithm_string = (_("<Unknown hash algorithm>")); break;
1105 for (int i = 0; i < hash->length; i++) {
1106 shi_asprintf(&octet, "%02x", ((uint8_t *)(hash->value))[i]);
1107 if (!octet) {
1108 free(buffer); free(octet); return NULL;
1111 if (i > 0)
1112 shi_asprintf(&new_buffer, _("%s:%s"), buffer, octet);
1113 else
1114 shi_asprintf(&new_buffer, "%s", octet);
1115 if (!new_buffer) {
1116 free(buffer); free(octet); return NULL;
1119 buffer = new_buffer; new_buffer = NULL;
1122 shi_asprintf(&new_buffer, _("%s %s"), algorithm_string, buffer);
1123 free(buffer);
1125 return new_buffer;
1129 /* Print if any message delivery info exists. */
1130 void print_message_delivery_info(const struct isds_envelope *envelope) {
1131 char *hash_string = NULL;
1133 if (envelope && (envelope->dmType || envelope->dmMessageStatus ||
1134 envelope->dmDeliveryTime ||
1135 envelope->dmAcceptanceTime || envelope->dmPersonalDelivery ||
1136 envelope->dmAllowSubstDelivery || envelope->hash ||
1137 envelope->dmOrdinal)) {
1138 oprintf(_("Delivery data:\n"));
1139 print_header(_("\tMessage type"), DmType2string(envelope->dmType));
1140 print_header(_("\tMessage status"),
1141 DmMessageStatus2string(envelope->dmMessageStatus));
1142 print_header_timeval(_("\tDelivered"), envelope->dmDeliveryTime);
1143 print_header_timeval(_("\tAccepted"), envelope->dmAcceptanceTime);
1144 print_header_bool(_("\tPersonal delivery required"),
1145 envelope->dmPersonalDelivery);
1146 print_header_bool(_("\tAllow substitutable delivery"),
1147 envelope->dmAllowSubstDelivery);
1149 hash_string = hash2string(envelope->hash);
1150 print_header(_("\tHash"), hash_string);
1151 free(hash_string);
1153 print_header_ulongint(_("\tOrdinal number"), envelope->dmOrdinal);
1158 static const char *event_type2string(const isds_event_type *type) {
1159 if (!type) return (_("<Undefined>"));
1161 switch (*type) {
1162 case EVENT_UKNOWN: return(_("Unknown"));
1163 case EVENT_ENTERED_SYSTEM:
1164 return(_("Entered system"));
1165 case EVENT_ACCEPTED_BY_RECIPIENT:
1166 return(_("Accepted by recipient"));
1167 case EVENT_ACCEPTED_BY_FICTION:
1168 return(_("Delivered substitutably"));
1169 case EVENT_UNDELIVERABLE:
1170 return(_("Undeliverable"));
1171 case EVENT_COMMERCIAL_ACCEPTED:
1172 return(_("Commerical message accepted by "
1173 "recipient")); break;
1174 case EVENT_DELIVERED:
1175 return(_("Delivered into box")); break;
1176 case EVENT_PRIMARY_LOGIN:
1177 return(_("Primary user logged in")); break;
1178 case EVENT_ENTRUSTED_LOGIN:
1179 return(_("Entrusted user logged in")); break;
1180 case EVENT_SYSCERT_LOGIN:
1181 return(_("Application logged in by system "
1182 "certificate")); break;
1183 default: return(_("<Unknown event type>"));
1188 /* Print if any delivery event exists. */
1189 void print_delivery_events(const struct isds_list *events) {
1190 int counter_width = 3;
1191 int order = 0;
1192 const struct isds_list *item;
1193 struct isds_event *event;
1195 if (!events) return;
1197 oprintf(_("Delivery events:\n"));
1199 for (item = events; item; item = item->next) {
1200 event = (struct isds_event *) item->data;
1201 if (!event) continue;
1202 order++;
1204 oprintf(_("%*d %s\n"), counter_width, order,
1205 event_type2string(event->type));
1206 print_header_utf8(_("\tDescription"), event->description);
1207 print_header_timeval(_("\tWhen"), event->time);
1212 /* Print formatted message envelope */
1213 void format_envelope(const struct isds_envelope *envelope) {
1214 char *law_string = NULL;
1216 if (!envelope) {
1217 oprintf(_("<Missing envelope>\n"));
1218 return;
1221 print_header_utf8(_("Message ID"), envelope->dmID);
1223 if (envelope->dbIDSender || envelope->dmSender ||
1224 envelope->dmSenderOrgUnit || envelope->dmSenderOrgUnitNum ||
1225 envelope->dmSenderAddress || envelope->dmSenderType ||
1226 envelope->dmOVM || envelope->dmPublishOwnID) {
1227 oprintf(_("Sender:\n"));
1228 print_header_utf8(_("\tID"), envelope->dbIDSender);
1229 print_header_utf8(_("\tName"), envelope->dmSender);
1230 print_header_utf8(_("\tUnit"), envelope->dmSenderOrgUnit);
1231 print_header_longint(_("\tUnit number"), envelope->dmSenderOrgUnitNum);
1232 print_header_utf8(_("\tAddress"), envelope->dmSenderAddress);
1233 print_header(_("\tType"), DbType2string(envelope->dmSenderType));
1234 print_header_bool(_("\tAs public authority"), envelope->dmOVM);
1235 print_header_bool(_("\tPublish user's identity"),
1236 envelope->dmPublishOwnID);
1239 if (envelope->dbIDRecipient || envelope->dmRecipient ||
1240 envelope->dmRecipientOrgUnit || envelope->dmRecipientOrgUnitNum ||
1241 envelope->dmToHands || envelope->dmRecipientAddress ||
1242 envelope->dmAmbiguousRecipient) {
1243 oprintf(_("Recipient:\n"));
1244 print_header_utf8(_("\tID"), envelope->dbIDRecipient);
1245 print_header_utf8(_("\tName"), envelope->dmRecipient);
1246 print_header_utf8(_("\tUnit"), envelope->dmRecipientOrgUnit);
1247 print_header_longint(_("\tUnit number"),
1248 envelope->dmRecipientOrgUnitNum);
1249 print_header_utf8(_("To hands"), envelope->dmToHands);
1250 print_header_utf8(_("\tAddress"), envelope->dmRecipientAddress);
1251 print_header_bool(_("\tAs public authority"),
1252 envelope->dmAmbiguousRecipient);
1255 print_header_utf8(_("Subject"), envelope->dmAnnotation);
1257 print_header_messages_ids(_("Sender message IDs"),
1258 envelope->dmSenderRefNumber, envelope->dmSenderIdent);
1259 print_header_messages_ids(_("Recipient message IDs"),
1260 envelope->dmRecipientRefNumber, envelope->dmRecipientIdent);
1262 law_string = envelope_law2string(envelope);
1263 print_header(_("Law authorization"), law_string);
1264 free(law_string);
1266 print_message_delivery_info(envelope);
1268 print_header_kbsize(_("Document total size"), envelope->dmAttachmentSize);
1270 /*oprintf("\t\ttimestamp = %p\n", envelope->timestamp);
1271 oprintf("\t\ttimestamp_length = %zu\n", envelope->timestamp_length);*/
1272 print_delivery_events(envelope->events);
1276 const char *DmFileMetaType2string(isds_FileMetaType type) {
1277 switch(type) {
1278 case FILEMETATYPE_MAIN: return(_("Main document"));
1279 case FILEMETATYPE_ENCLOSURE: return(_("Enclosure"));
1280 case FILEMETATYPE_SIGNATURE: return(_("Signature"));
1281 case FILEMETATYPE_META: return(_("Meta document"));
1282 default: return(_("<unknown document type>"));
1287 /* Computes ordinal number of document identified by GUID
1288 * @documents is list of documents where to search
1289 * @id is UTF-8 encoded document ID reference
1290 * Return allocated array of ordinal numbers terminated by -1. Normally only
1291 * one document with @id exists. However ISDS does not check this higher
1292 * requirements and can transport message with duplicate document identifiers.
1293 * Therefore this function returns array of ordinals. Return NULL if error
1294 * occurs (e.g. memory insufficiency). */
1295 static int *dmFileGuid2ordinar(const struct isds_list *documents,
1296 const char *id) {
1297 const struct isds_list *item;
1298 struct isds_document *document;
1299 size_t ordinars_length = 64, offset = 0;
1300 int *ordinars = NULL, *new_ordinars;
1301 int ordinar = 0;
1303 if (!documents || !id || !*id) return NULL;
1304 ordinars = malloc(ordinars_length * sizeof(*ordinars));
1305 if (!ordinars) return NULL;
1307 for (item = documents; item; item = item->next) {
1308 if (!item->data) continue;
1309 ordinar++;
1310 document = (struct isds_document *) (item->data);
1312 if (document->dmFileGuid && !strcmp(document->dmFileGuid, id)) {
1313 if (offset == ordinars_length) {
1314 /* Grow ordinals array */
1315 ordinars_length *= 2;
1316 new_ordinars = realloc(ordinars,
1317 ordinars_length * sizeof(*ordinars));
1318 if (!new_ordinars) {
1319 free(ordinars);
1320 return NULL;
1322 ordinars = new_ordinars;
1325 ordinars[offset++] = ordinar;
1329 ordinars[offset] = -1;
1330 return ordinars;
1334 /* @id is UTF-8 encoded GUID of referred document
1335 * @refernces is array of ordinal numbers if exist terminated by -1. Can be
1336 * NULL to signal error. */
1337 static void format_document_reference(char *id, int *references) {
1338 char *buffer = NULL, *new_buffer = NULL;
1339 if (!id) return;
1341 if (references && *references != -1) {
1342 for (; *references > 0; references++) {
1343 if (!buffer) {
1344 shi_asprintf(&new_buffer, _("%d"), *references);
1345 } else {
1346 shi_asprintf(&new_buffer, _("%s, %d"), buffer, *references);
1348 if (!new_buffer) {
1349 zfree(buffer);
1350 break;
1352 buffer = new_buffer;
1353 new_buffer = NULL;
1355 } else {
1356 char *id_locale = utf82locale(id);
1357 shi_asprintf(&buffer,
1358 _("<Reference to non-existing document ID `%s'>"), id_locale);
1359 free(id_locale);
1362 if (buffer)
1363 print_header(_("\tRefers to"), buffer);
1364 else
1365 print_header(_("\tRefers to"), _("<Error while formatting reference>"));
1366 free(buffer);
1370 /* Print formatted document
1371 * @references is ordinal number of referred document. Formally it's array
1372 * terminated by -1 because non-well-formed message can have more documents
1373 * with equal IDs */
1374 void format_document(const struct isds_document *document, int order,
1375 int *references) {
1376 int counter_width = 3;
1377 char *filename_locale = NULL;
1379 if (!document) return;
1381 oprintf(_("%*d "), counter_width, order);
1383 if (document->dmFileDescr) {
1384 filename_locale = utf82locale(document->dmFileDescr);
1385 oprintf("%s\n", filename_locale);
1386 free(filename_locale);
1387 } else {
1388 oprintf(_("<Unknown file name>\n"));
1391 if (document->is_xml) {
1392 char *message =NULL;
1393 int nodes = 0;
1395 for (xmlNodePtr node = document->xml_node_list; node;
1396 node = node->next) nodes++;
1397 shi_asprintf(&message, ngettext("%d node", "%d nodes", nodes), nodes);
1398 if (message) {
1399 print_header(_("\tXML document"), message);
1400 free(message);
1402 } else {
1403 print_header_size(_("\tSize"), document->data_length);
1405 print_header(_("\tMIME type"), document->dmMimeType);
1407 print_header(_("\tType"), DmFileMetaType2string(document->dmFileMetaType));
1408 print_header_utf8(_("\tMeta format"), document->dmFormat);
1410 print_header_utf8(_("\tID"), document->dmFileGuid);
1411 format_document_reference(document->dmUpFileGuid, references);
1415 /* Print formatted message documents */
1416 void format_documents(const struct isds_list *documents) {
1417 const struct isds_list *item;
1418 const struct isds_document *document;
1419 int i = 0;
1420 int *references;
1421 if (!documents) return;
1423 oprintf(_("Documents:\n"));
1425 for (item = documents; item; item = item->next) {
1426 if (!item->data) continue;
1427 document = (struct isds_document *) item->data;
1428 references = dmFileGuid2ordinar(documents, document->dmUpFileGuid);
1429 format_document(document, ++i, references);
1430 free(references);
1435 /* Print formatted message */
1436 void format_message(const struct isds_message *message) {
1437 if (!message) return;
1438 format_envelope(message->envelope);
1439 format_documents(message->documents);
1443 /* Print formatted list of message copies */
1444 void format_copies(const struct isds_list *copies) {
1445 const struct isds_list *item;
1446 const struct isds_message_copy *copy;
1447 int i = 0;
1448 int counter_width = 3;
1449 if (!copies) return;
1451 for (item = copies; item; item = item->next) {
1452 if (!item->data) continue;
1453 copy = (struct isds_message_copy *) item->data;
1454 i++;
1456 oprintf(_("%*d Recipient:\n"), counter_width, i);
1457 print_header_utf8(_("\tID"), copy->dbIDRecipient);
1458 print_header_utf8(_("\tUnit"), copy->dmRecipientOrgUnit);
1459 print_header_longint(_("\tUnit number"), copy->dmRecipientOrgUnitNum);
1460 print_header_utf8(_("\tTo hands"), copy->dmToHands);
1465 void print_message_list(const struct isds_list *messages, _Bool outgoing) {
1466 const struct isds_list *item;
1467 struct isds_envelope *envelope;
1468 unsigned long int counter = 0;
1470 int counter_max, id_max = 0, name_max = 0, subject_max = 0;
1471 int counter_width, id_width = 0, flags_width = 2, time_width = 6,
1472 name_width = 0, subject_width = 0;
1474 char *id_locale = NULL, flags_locale[3], *time_locale = NULL,
1475 *name_locale = NULL, *subject_locale = NULL;
1476 int screen_cols;
1477 int width;
1480 /* Compute column widths */
1481 rl_get_screen_size(NULL, &screen_cols);
1483 /* Get real maximal widths */
1484 for (counter = 0, item = messages; item; item = item->next) {
1485 if (!item->data || !((struct isds_message *)item->data)->envelope)
1486 continue;
1487 envelope = ((struct isds_message *) item->data)->envelope;
1488 counter++;
1490 width = utf8width(envelope->dmID);
1491 if (width > id_max) id_max = width;
1493 width = utf8width((outgoing) ?
1494 envelope->dmRecipient : envelope->dmSender);
1495 if (width > name_max) name_max = width;
1497 width = utf8width(envelope->dmAnnotation);
1498 if (width > subject_max) subject_max = width;
1500 counter_max = numberwidth(counter);
1502 /* Correct widths to fit into window */
1503 if (counter_max < 0) counter_width = -3; else counter_width = counter_max;
1504 if (id_max < 0) id_width = -6; else id_width = id_max;
1505 if (name_max < 0) name_width = -20; else name_width = name_max;
1506 if (subject_max < 0) subject_width = -32; else subject_width = subject_max;
1508 width = abs(counter_width) + 1 + abs(id_width) + 1 + abs(flags_width) + 1 +
1509 abs(time_width) + 1 + abs(name_width) + 1 + abs(subject_width);
1510 if (width > screen_cols) {
1511 width -= abs(name_width) + abs(subject_width);
1513 name_width = subject_width = 0;
1514 while (width + name_width + subject_width < screen_cols) {
1515 if (name_width < abs(name_max)) name_width++;
1516 if (subject_width < abs(subject_max)) subject_width++;
1518 if (width + name_width + subject_width > screen_cols) subject_width--;
1521 /* Print header */
1522 /* TRANSLATORS: "No" is abbreviation for "Number" in listing header. */
1523 onprint(pgettext("list header", "No"), counter_width);
1524 oprintf(" ");
1525 onprint(_("ID"), id_width);
1526 oprintf(" ");
1527 onprint(_("Flags"), flags_width);
1528 oprintf(" ");
1529 onprint(_("Delivered"), time_width);
1530 oprintf(" ");
1531 onprint((outgoing) ? _("To") : _("From"), name_width);
1532 oprintf(" ");
1533 onprint(_("Subject"), subject_width);
1534 oprintf("\n");
1535 for (int i = 0; i < screen_cols; i++) oprintf(_("-"));
1536 oprintf("\n");
1538 /* Print the list */
1539 for (counter = 0, item = messages; item; item = item->next) {
1540 envelope = ((struct isds_message *) item->data)->envelope;
1541 counter++;
1543 oprintf(_("%*lu "), counter_width, counter);
1545 if (!envelope) {
1546 oprintf(_("<Missing envelope>\n"));
1547 continue;
1550 id_locale = utf82locale(envelope->dmID);
1551 name_locale = utf82locale((outgoing) ?
1552 envelope->dmRecipient: envelope->dmSender);
1553 flags_locale[0] = DmType2flag(envelope->dmType);
1554 flags_locale[1] = DmMessageStatus2flag(envelope->dmMessageStatus);
1555 flags_locale[2] = '\0';
1556 time_locale = timeval2shortstring(envelope->dmDeliveryTime);
1557 subject_locale = utf82locale(envelope->dmAnnotation);
1559 onprint(id_locale, id_width);
1560 oprintf(" ");
1561 onprint(flags_locale, flags_width);
1562 oprintf(" ");
1563 onprint(time_locale, time_width);
1564 oprintf(" ");
1565 onprint(name_locale, name_width);
1566 oprintf(" ");
1567 onprint(subject_locale, subject_width);
1568 oprintf("\n");
1570 zfree(id_locale);
1571 zfree(time_locale);
1572 zfree(name_locale);
1573 zfree(subject_locale);
1578 static void format_PersonName(const struct isds_PersonName *personName) {
1579 if (!personName) return;
1581 oprintf(_("Person name:\n"));
1582 print_header_utf8(_("\tFirst"), personName->pnFirstName);
1583 print_header_utf8(_("\tMiddle"), personName->pnMiddleName);
1584 print_header_utf8(_("\tLast"), personName->pnLastName);
1585 print_header_utf8(_("\tLast at birth"),
1586 personName->pnLastNameAtBirth);
1590 static void format_BirthInfo(const struct isds_BirthInfo *birth) {
1591 if (!birth || !(birth->biDate || birth->biCity || birth->biCounty
1592 || birth->biState)) return;
1594 oprintf(_("Birth details:\n"));
1596 print_header_tm(_("\tDate"), birth->biDate);
1597 print_header_utf8(_("\tCity"), birth->biCity);
1598 print_header_utf8(_("\tCounty"), birth->biCounty);
1599 print_header_utf8(_("\tState"), birth->biState);
1603 static void format_Address(const struct isds_Address *address) {
1604 if (!address || !(address->adCity || address->adState ||
1605 address->adNumberInStreet || address->adNumberInMunicipality ||
1606 address->adZipCode || address->adState)) return;
1608 oprintf("Address:\n");
1609 print_header_utf8(_("\tCity"), address->adCity);
1610 print_header_utf8(_("\tStreet"), address->adStreet);
1611 print_header_utf8(_("\tNumber in street"), address->adNumberInStreet);
1612 print_header_utf8(_("\tNumber in municipality"),
1613 address->adNumberInMunicipality);
1614 print_header_utf8(_("\tZIP code"), address->adZipCode);
1615 print_header_utf8(_("\tState"), address->adState);
1619 /* Return static box state string or NULL if undefined */
1620 const char *DbState2string(const long int *state) {
1621 if (!state) return NULL;
1623 switch(*state) {
1624 case DBSTATE_ACCESSIBLE: return(_("Accessible"));
1625 case DBSTATE_TEMP_UNACCESSIBLE: return(_("Temporary inaccessible"));
1626 case DBSTATE_NOT_YET_ACCESSIBLE: return(_("Not yet accessible"));
1627 case DBSTATE_PERM_UNACCESSIBLE: return(_("Permanently inaccessible"));
1628 case DBSTATE_REMOVED: return(_("Deleted"));
1629 default: return(_("<unknown state>"));
1634 void format_DbOwnerInfo(const struct isds_DbOwnerInfo *info) {
1635 if (!info) return;
1637 print_header_utf8(_("Box ID"), info->dbID);
1638 print_header(_("Type"), DbType2string((long int *) (info->dbType)));
1639 print_header_utf8(_("Subject name"), info->firmName);
1640 print_header_utf8(_("Identity number"), info->ic);
1642 format_PersonName(info->personName);
1643 format_BirthInfo(info->birthInfo);
1645 format_Address(info->address);
1647 print_header_utf8(_("Nationality"), info->nationality);
1648 print_header_utf8(_("E-mail"), info->email);
1649 print_header_utf8(_("Phone"), info->telNumber);
1651 print_header_utf8(_("Identifier"), info->identifier);
1652 print_header_utf8(_("Registry code"), info->registryCode);
1654 print_header(_("State"), DbState2string(info->dbState));
1655 print_header_bool(_("Act as public authority"), info->dbEffectiveOVM);
1656 print_header_bool(_("Receive commercial messages"),
1657 info->dbOpenAddressing);
1661 static void format_supervising_firm(const char *ic, const char *firmName) {
1662 if (!ic && !firmName) return;
1664 oprintf(_("Supervising subject:\n"));
1665 print_header_utf8(_("\tIdentity number"), ic);
1666 print_header_utf8(_("\tName"), firmName);
1670 static void format_contact_address(const char *caStreet, const char *caCity,
1671 const char *caZipCode, const char *caState) {
1672 if (!caStreet && !caCity && !caZipCode) return;
1674 oprintf(_("Contact address:\n"));
1675 print_header_utf8(_("\tStreet"), caStreet);
1676 print_header_utf8(_("\tCity"), caCity);
1677 print_header_utf8(_("\tZIP code"), caZipCode);
1678 print_header_utf8(_("\tState"), caState);
1682 void format_DbUserInfo(const struct isds_DbUserInfo *info) {
1683 char *buffer;
1685 if (!info) return;
1687 print_header_utf8(_("User ID"), info->userID);
1688 print_header(_("Type"), UserType2string((long int *) (info->userType)));
1690 buffer = UserPrivils2string(info->userPrivils);
1691 print_header(_("Privileges"), buffer);
1692 zfree(buffer);
1694 format_PersonName(info->personName);
1695 format_Address(info->address);
1697 print_header_tm(_("Birth date"), info->biDate);
1699 format_supervising_firm(info->ic, info->firmName);
1700 format_contact_address(info->caStreet, info->caCity, info->caZipCode,
1701 info->caState);
1705 /* Print formated details about message sender */
1706 void format_sender_info(const char *dbID, const isds_sender_type *type,
1707 const char *raw_type, const char *name) {
1708 const char *type_string;
1710 if (!dbID && !type && !raw_type && !name) return;
1712 oprintf(_("Message sender:\n"));
1713 print_header_utf8(_("\tMessage ID"), dbID);
1715 type_string = isds_sender_type2string(type);
1716 if (type_string)
1717 print_header(_("\tType"), type_string);
1718 else
1719 print_header_utf8(_("\tRaw type"), raw_type);
1721 print_header_utf8(_("\tName"), name);
1725 static const char *credit_event_type2string(
1726 const isds_credit_event_type type) {
1727 switch (type) {
1728 case ISDS_CREDIT_CHARGED: return(_("Credit charged"));
1729 case ISDS_CREDIT_DISCHARGED: return(_("Credit discharged"));
1730 case ISDS_CREDIT_MESSAGE_SENT: return(_("Message sent"));
1731 case ISDS_CREDIT_STORAGE_SET: return(_("Long-term storage set"));
1732 case ISDS_CREDIT_EXPIRED: return(_("Credit expired"));
1733 default: return(_("<Unknown credit event type>"));
1738 /* Print formated details about credit change event */
1739 void format_credit_event(const struct isds_credit_event *event) {
1740 if (NULL == event) return;
1742 print_header_timeval(_("When"), event->time);
1743 /* FIXME: Format the currency */
1744 print_header_longint(_("Credit change [CZK/100]"), &event->credit_change);
1745 print_header_longint(_("Total credit [CZK/100]"), &event->new_credit);
1746 print_header(_("Type"), credit_event_type2string(event->type));
1748 switch (event->type) {
1749 case ISDS_CREDIT_CHARGED:
1750 print_header(_("Transation ID"),
1751 event->details.charged.transaction);
1752 break;
1753 case ISDS_CREDIT_DISCHARGED:
1754 print_header(_("Transation ID"),
1755 event->details.discharged.transaction);
1756 break;
1757 case ISDS_CREDIT_MESSAGE_SENT:
1758 print_header(_("Message ID"),
1759 event->details.message_sent.message_id);
1760 print_header(_("Message recipient"),
1761 event->details.message_sent.recipient);
1762 break;
1763 case ISDS_CREDIT_STORAGE_SET:
1764 if (NULL != event->details.storage_set.old_capacity) {
1765 oprintf(_("Old setting:\n"));
1766 oprintf(ngettext("%s: %ld message\n", "%s: %ld messages",
1767 *event->details.storage_set.old_capacity),
1768 _("\tCapacity"),
1769 *event->details.storage_set.old_capacity);
1770 print_header_tm(_("\tValid from"),
1771 event->details.storage_set.old_valid_from);
1772 print_header_tm(_("\tValid to"),
1773 event->details.storage_set.old_valid_to);
1775 oprintf(_("New setting:\n"));
1776 oprintf(ngettext("%s: %ld message\n", "%s: %ld messages",
1777 event->details.storage_set.new_capacity),
1778 _("\tCapacity"),
1779 event->details.storage_set.new_capacity);
1780 print_header_tm(_("\tValid from"),
1781 event->details.storage_set.new_valid_from);
1782 print_header_tm(_("\tValid to"),
1783 event->details.storage_set.new_valid_to);
1784 print_header_utf8(_("Initiator"),
1785 event->details.storage_set.initiator);
1786 break;
1787 case ISDS_CREDIT_EXPIRED:
1788 break;
1789 default:
1790 oprintf(_("Detail can be missing due to unkown type.\n"));
1795 void format_commercial_permission(
1796 const struct isds_commercial_permission *permission) {
1797 if (NULL == permission) return;
1799 print_header(_("Payment type"),
1800 isds_payment_type2string(&permission->type));
1801 print_header_utf8(_("Allowed recipient box ID"), permission->recipient);
1802 print_header_utf8(_("Payed by owner of box ID"), permission->payer);
1803 print_header_timeval(_("Permission expires"), permission->expiration);
1804 print_header_ulongint(_("Remaining messages"), permission->count);
1805 print_header_utf8(_("Reference to request"), permission->reply_identifier);