Transfotm data.c printf() into UI oprintf()
[shigofumi.git] / src / data.c
blob86ed48058e5e07daa0f02a8018c0a3530c5e2e25
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_ACCEPTED_BY_RECIPIENT:
312 oprintf("ACCEPTED_BY_RECIPIENT\n"); break;
313 case EVENT_ACCEPTED_BY_FICTION:
314 oprintf("DELIVERED_BY_FICTION\n"); break;
315 case EVENT_UNDELIVERABLE:
316 oprintf("UNDELIVERABLE\n"); break;
317 default: oprintf("<unknown type %d>\n", *type);
322 void print_events(const struct isds_list *events) {
323 const struct isds_list *item;
324 const struct isds_event *event;
326 if (!events) {
327 oprintf("NULL\n");
328 return;
331 oprintf("{\n");
333 for (item = events; item; item = item->next) {
334 event = (struct isds_event *) item->data;
335 oprintf("\t\t\tevent = ");
336 if (!event) oprintf("NULL");
337 else {
338 oprintf("{\n");
340 oprintf("\t\t\t\ttype = ");
341 print_event_type(event->type);
343 oprintf("\t\t\t\tdescription = %s\n", event->description);
345 oprintf("\t\t\t\ttime = ");
346 print_timeval(event->time);
348 oprintf("\t\t\t}\n");
352 oprintf("\t\t}\n");
356 void print_envelope(const struct isds_envelope *envelope) {
357 oprintf("\tenvelope = ");
359 if (!envelope) {
360 oprintf("NULL\n");
361 return;
363 oprintf("{\n");
365 oprintf("\t\tdmID = %s\n", envelope->dmID);
366 oprintf("\t\tdbIDSender = %s\n", envelope->dbIDSender);
367 oprintf("\t\tdmSender = %s\n", envelope->dmSender);
368 oprintf("\t\tdmSenderAddress = %s\n", envelope->dmSenderAddress);
369 oprintf("\t\tdmSenderType = ");
370 print_DbType(envelope->dmSenderType);
371 oprintf("\t\tdmRecipient = %s\n", envelope->dmRecipient);
372 oprintf("\t\tdmRecipientAddress = %s\n", envelope->dmRecipientAddress);
373 oprintf("\t\tdmAmbiguousRecipient = ");
374 print_bool(envelope->dmAmbiguousRecipient);
375 oprintf("\t\tdmType = %s\n", envelope->dmType);
377 oprintf("\t\tdmSenderOrgUnit = %s\n", envelope->dmSenderOrgUnit);
378 oprintf("\t\tdmSenderOrgUnitNum = ");
379 print_longint(envelope->dmSenderOrgUnitNum);
380 oprintf("\t\tdbIDRecipient = %s\n", envelope->dbIDRecipient);
381 oprintf("\t\tdmRecipientOrgUnit = %s\n", envelope->dmRecipientOrgUnit);
382 oprintf("\t\tdmRecipientOrgUnitNum = ");
383 print_longint(envelope->dmRecipientOrgUnitNum);
384 oprintf("\t\tdmToHands = %s\n", envelope->dmToHands);
385 oprintf("\t\tdmAnnotation = %s\n", envelope->dmAnnotation);
386 oprintf("\t\tdmRecipientRefNumber = %s\n", envelope->dmRecipientRefNumber);
387 oprintf("\t\tdmSenderRefNumber = %s\n", envelope->dmSenderRefNumber);
388 oprintf("\t\tdmRecipientIdent = %s\n", envelope->dmRecipientIdent);
389 oprintf("\t\tdmSenderIdent = %s\n", envelope->dmSenderIdent);
391 oprintf("\t\tdmLegalTitleLaw = ");
392 print_longint(envelope->dmLegalTitleLaw);
393 oprintf("\t\tdmLegalTitleYear = ");
394 print_longint(envelope->dmLegalTitleYear);
395 oprintf("\t\tdmLegalTitleSect = %s\n", envelope->dmLegalTitleSect);
396 oprintf("\t\tdmLegalTitlePar = %s\n", envelope->dmLegalTitlePar);
397 oprintf("\t\tdmLegalTitlePoint = %s\n", envelope->dmLegalTitlePoint);
399 oprintf("\t\tdmPersonalDelivery = ");
400 print_bool(envelope->dmPersonalDelivery);
401 oprintf("\t\tdmAllowSubstDelivery = ");
402 print_bool(envelope->dmAllowSubstDelivery);
403 oprintf("\t\tdmOVM = ");
404 print_bool(envelope->dmOVM);
406 oprintf("\t\tdmOrdinal = ");
407 if (!envelope->dmOrdinal) oprintf("NULL\n");
408 else oprintf("%lu\n", *(envelope->dmOrdinal));
410 oprintf("\t\tdmMessageStatus = ");
411 if (!envelope->dmMessageStatus) oprintf("NULL\n");
412 else
413 switch(*(envelope->dmMessageStatus)) {
414 case MESSAGESTATE_SENT: oprintf("SENT\n"); break;
415 case MESSAGESTATE_STAMPED: oprintf("STAMPED\n"); break;
416 case MESSAGESTATE_INFECTED: oprintf("INFECTED\n"); break;
417 case MESSAGESTATE_DELIVERED: oprintf("DELIVERED\n"); break;
418 case MESSAGESTATE_SUBSTITUTED: oprintf("SUBSTITUTED\n"); break;
419 case MESSAGESTATE_RECEIVED: oprintf("RECEIVED\n"); break;
420 case MESSAGESTATE_READ: oprintf("READ\n"); break;
421 case MESSAGESTATE_UNDELIVERABLE: oprintf("UNDELIVERABLE\n"); break;
422 case MESSAGESTATE_REMOVED: oprintf("REMOVED\n"); break;
423 case MESSAGESTATE_IN_SAFE: oprintf("IN_SAFE\n"); break;
424 default: oprintf("<unknown type %d>\n",
425 *(envelope->dmMessageStatus));
428 oprintf("\t\tdmAttachmentSize = ");
429 if (!envelope->dmAttachmentSize) oprintf("NULL\n");
430 else oprintf("%lu kB\n", *(envelope->dmAttachmentSize));
432 oprintf("\t\tdmDeliveryTime = ");
433 print_timeval(envelope->dmDeliveryTime);
435 oprintf("\t\tdmAcceptanceTime = ");
436 print_timeval(envelope->dmAcceptanceTime);
438 oprintf("\t\thash = ");
439 print_hash(envelope->hash);
441 oprintf("\t\ttimestamp = %p\n", envelope->timestamp);
442 oprintf("\t\ttimestamp_length = %zu\n", envelope->timestamp_length);
444 oprintf("\t\tevents = ");
445 print_events(envelope->events);
447 oprintf("\t}\n");
451 void print_document(const struct isds_document *document) {
452 oprintf("\t\tdocument = ");
454 if (!document) {
455 oprintf("NULL\n");
456 return;
458 oprintf("\{\n");
460 oprintf("\t\t\tis_xml = %u\n", !!document->is_xml);
461 oprintf("\t\t\txml_node_list = %p\n", document->xml_node_list);
463 oprintf("\t\t\tdata = %p\n", document->data);
464 oprintf("\t\t\tdata_length = %zu\n", document->data_length);
465 oprintf("\t\t\tdmMimeType = %s\n", document->dmMimeType);
467 oprintf("\t\t\tdmFileMetaType = ");
468 switch(document->dmFileMetaType) {
469 case FILEMETATYPE_MAIN: oprintf("MAIN\n"); break;
470 case FILEMETATYPE_ENCLOSURE: oprintf("ENCLOSURE\n"); break;
471 case FILEMETATYPE_SIGNATURE: oprintf("SIGNATURE\n"); break;
472 case FILEMETATYPE_META: oprintf("META\n"); break;
473 default: oprintf("<unknown type %d>\n", document->dmFileMetaType);
476 oprintf("\t\t\tdmFileGuid = %s\n", document->dmFileGuid);
477 oprintf("\t\t\tdmUpFileGuid = %s\n", document->dmUpFileGuid);
478 oprintf("\t\t\tdmFileDescr = %s\n", document->dmFileDescr);
479 oprintf("\t\t\tdmFormat = %s\n", document->dmFormat);
480 oprintf("\t\t}\n");
484 void print_documents(const struct isds_list *documents) {
485 const struct isds_list *item;
487 oprintf("\tdocuments = ");
489 if (!documents) {
490 oprintf("NULL\n");
491 return;
493 oprintf("{\n");
495 for (item = documents; item; item = item->next) {
496 print_document((struct isds_document *) (item->data));
499 oprintf("\t}\n");
503 void print_message(const struct isds_message *message) {
504 oprintf("message = ");
506 if (!message) {
507 oprintf("NULL\n");
508 return;
511 oprintf("{\n");
513 oprintf("\traw = %p\n", message->raw);
514 oprintf("\traw_length = %zu\n", message->raw_length);
515 oprintf("\traw_type = ");
516 print_raw_type(message->raw_type);
517 print_envelope(message->envelope);
518 print_documents(message->documents);
520 oprintf("}\n");
523 void print_copies(const struct isds_list *copies) {
524 const struct isds_list *item;
525 struct isds_message_copy *copy;
527 oprintf("Copies = ");
528 if (!copies) {
529 oprintf("<NULL>\n");
530 return;
533 oprintf("{\n");
534 for (item = copies; item; item = item->next) {
535 copy = (struct isds_message_copy *) item->data;
536 oprintf("\tCopy = ");
538 if (!copy)
539 oprintf("<NULL>\n");
540 else {
541 oprintf("{\n");
542 oprintf("\t\tdbIDRecipient = %s\n", copy->dbIDRecipient);
543 oprintf("\t\tdmRecipientOrgUnit = %s\n", copy->dmRecipientOrgUnit);
545 oprintf("\t\tdmRecipientOrgUnitNum = ");
546 if (copy->dmRecipientOrgUnitNum)
547 oprintf("%ld\n", *copy->dmRecipientOrgUnitNum);
548 else
549 oprintf("<NULL>\n");
550 oprintf("\t\tdmToHands = %s\n", copy->dmToHands);
552 oprintf("\t\terror = %s\n", isds_strerror(copy->error));
553 oprintf("\t\tdmStatus = %s\n", copy->dmStatus);
554 oprintf("\t\tdmID = %s\n", copy->dmID);
555 oprintf("\t}\n");
558 oprintf("}\n");
562 void compare_hashes(const struct isds_hash *hash1,
563 const struct isds_hash *hash2) {
564 isds_error err;
566 oprintf("Comparing hashes... ");
567 err = isds_hash_cmp(hash1, hash2);
568 if (err == IE_SUCCESS)
569 oprintf("Hashes equal\n");
570 else if
571 (err == IE_NOTEQUAL) oprintf("Hashes differ\n");
572 else
573 oprintf("isds_hash_cmp() failed: %s\n", isds_strerror(err));
577 int progressbar(double upload_total, double upload_current,
578 double download_total, double download_current,
579 void *data) {
581 oprintf("Progress: upload %0f/%0f, download %0f/%0f, data=%p\n",
582 upload_current, upload_total, download_current, download_total,
583 data);
584 return 0;
588 /* Print formatted header if locale-encoded value is defined.
589 * @header is locale encoded header name
590 * @value is locale encoded header value */
591 void print_header(const char *header, const char *value) {
592 if (value && *value) oprintf(_("%s: %s\n"), header, value);
596 /* Print formatted header if boolean value is defined.
597 * @header is locale encoded header name */
598 void print_header_bool(const char *header, _Bool *value) {
599 if (value) print_header(header, (*value) ? _("Yes") : _("No"));
603 /* Print formatted header if long int value is defined.
604 * @header is locale encoded header name */
605 void print_header_longint(const char *header, long int *value) {
606 if (value) oprintf(_("%s: %ld\n"), header, *value);
610 /* Print formatted header if unsigned long int value is defined.
611 * @header is locale encoded header name */
612 void print_header_ulongint(const char *header, unsigned long int *value) {
613 if (value) oprintf(_("%s: %ld\n"), header, *value);
617 /* Print formatted header if time value is defined.
618 * @header is locale encoded header name */
619 void print_header_timeval(const char *header, struct timeval *time) {
620 struct tm broken;
621 char buffer[128];
623 if (!time) return;
625 if (!localtime_r(&(time->tv_sec), &broken)) goto error;
626 if (!strftime(buffer, sizeof(buffer)/sizeof(char), "%c", &broken))
627 goto error;
629 if (!time->tv_usec)
630 oprintf(_("%s: %s\n"), header, buffer);
631 else if ((time->tv_usec % 1000) == 0)
632 oprintf(_("%s: %s, %ld ms\n"), header, buffer, time->tv_usec/1000);
633 else
634 oprintf(_("%s: %s, %ld us\n"), header, buffer, time->tv_usec);
636 return;
638 error:
639 oprintf(_("%s: <Error while formatting time>\n"), header);
640 return;
644 /* Print formatted header if UTF-9 value is defined.
645 * @header is locale encoded header name
646 * @value is UTF-8 encoded header value */
647 void print_header_utf8(const char *header, const char *value) {
648 char *value_locale;
650 if (!value) return;
652 value_locale = utf82locale(value);
653 print_header(header,
654 (value_locale) ?
655 value_locale :
656 _("<Error while converting value>"));
657 free(value_locale);
661 /* Print formatted header and byte size.
662 * @header is locale encoded header name */
663 void print_header_size(const char *header, size_t size) {
664 char *buffer = NULL;
666 if (size < (1<<10))
667 shi_asprintf(&buffer, _("%zu B"), size);
668 else if (size < (1<<20))
669 shi_asprintf(&buffer, _("%0.2f KiB"), (float) size/(1<<10));
670 else
671 shi_asprintf(&buffer, _("%0.2f MiB"), (float) size/(1<<20));
673 print_header(header, buffer);
674 free(buffer);
678 /* Print formatted header if long int KB size is defined.
679 * @header is locale encoded header name */
680 void print_header_kbsize(const char *header, const long int *size) {
681 char *buffer = NULL;
682 if (!size) return;
684 if (*size < 0)
685 shi_asprintf(&buffer, _("<Negative size>"));
686 else if (*size < (1000))
687 shi_asprintf(&buffer, _("%lu kB"), *size);
688 else
689 shi_asprintf(&buffer, _("%0.2f MB"), *size/1000.0);
691 print_header(header, buffer);
692 free(buffer);
696 static const char *DbType2string(const long int *type) {
697 if (!type) return NULL;
698 switch(*type) {
699 case DBTYPE_SYSTEM: return(_("System"));
700 case DBTYPE_FO: return(_("Private individual"));
701 case DBTYPE_PFO: return(_("Self-employed individual"));
702 case DBTYPE_PFO_ADVOK: return(_("Lawyer"));
703 case DBTYPE_PFO_DANPOR: return(_("Tax advisor"));
704 case DBTYPE_PFO_INSSPR: return(_("Insolvency administrator"));
705 case DBTYPE_PO: return(_("Organisation"));
706 case DBTYPE_PO_ZAK: return(_("Organization based by law"));
707 case DBTYPE_PO_REQ: return(_("Organization based on request"));
708 case DBTYPE_OVM: return(_("Public authority"));
709 case DBTYPE_OVM_NOTAR: return(_("Notary"));
710 case DBTYPE_OVM_EXEKUT: return(_("Executor"));
711 case DBTYPE_OVM_REQ: return(_("Public authority based on request"));
712 default: return(_("<Unknown type>"));
717 static const char *UserType2string(const long int *type) {
718 if (!type) return NULL;
719 switch(*type) {
720 case USERTYPE_PRIMARY: return(_("Primary"));
721 case USERTYPE_ENTRUSTED: return(_("Entrusted"));
722 case USERTYPE_ADMINISTRATOR: return(_("Administrator"));
723 case USERTYPE_OFFICIAL: return(_("Official"));
724 default: return(_("<Unknown type>"));
729 /* Return formatted user privileges. Caller must free the string */
730 static char *UserPrivils2string(const long int *privils) {
732 const char *priviledges[] = {
733 N_("Read non-personal"),
734 N_("Read all"),
735 N_("Send and read sent"),
736 N_("List messages and read delivery details"),
737 N_("Search boxes"),
738 N_("Administer her box"),
739 N_("Read from safe"),
740 N_("Delete from safe")
742 const int priviledges_count = sizeof(priviledges)/sizeof(priviledges[0]);
743 char *buffer = NULL, *new_buffer = NULL;
745 if (!privils) return NULL;
747 /*oprintf("%ld (", *privils);*/
749 for (int i = 0; i < priviledges_count; i++) {
750 if (*privils & (1<<i)) {
751 if ((*privils % (1<<i)))
752 shi_asprintf(&new_buffer, _("%s, %s"),
753 buffer, _(priviledges[i]));
754 else
755 shi_asprintf(&new_buffer, "%s", _(priviledges[i]));
757 if (!new_buffer) {
758 free(buffer);
759 return(strdup(_("<Error while formatting privileges>")));
762 free(buffer);
763 buffer = new_buffer;
764 new_buffer = NULL;
768 if (*privils >= (1<<priviledges_count)) {
769 if ((*privils % (1<<priviledges_count)))
770 shi_asprintf(&new_buffer, _("%s, %s"),
771 buffer, _("<Unknown privilege>"));
772 else
773 shi_asprintf(&new_buffer, "%s", _("<Unknown privilege>"));
775 if (!new_buffer) {
776 free(buffer);
777 return(strdup(_("<Error while formatting privileges>")));
780 free(buffer);
781 buffer = new_buffer;
782 new_buffer = NULL;
785 return buffer;
789 static const char *DmType2string(const char *type) {
790 if (!type) return NULL;
791 if (!strcmp(type, "V")) return(_("Public"));
792 else if (!strcmp(type, "K")) return(_("Commercial"));
793 else return(_("<Unknown type>"));
797 static const char DmType2flag(const char *type) {
798 if (!type) return ' ';
799 if (!strcmp(type, "V")) return('P');
800 else if (!strcmp(type, "K")) return('C');
801 else return('?');
805 static const char *DmMessageStatus2string(const isds_message_status *status) {
806 if (!status) return NULL;
807 switch(*status) {
808 case MESSAGESTATE_SENT: return(_("Sent"));
809 case MESSAGESTATE_STAMPED: return(_("Stamped"));
810 case MESSAGESTATE_INFECTED: return(_("Infected"));
811 case MESSAGESTATE_DELIVERED: return(_("Delivered ordinary"));
812 case MESSAGESTATE_SUBSTITUTED: return(_("Delivered substitutably"));
813 case MESSAGESTATE_RECEIVED: return(_("Accepted"));
814 case MESSAGESTATE_READ: return(_("Read"));
815 case MESSAGESTATE_UNDELIVERABLE: return(_("Undeliverable"));
816 case MESSAGESTATE_REMOVED: return(_("Deleted"));
817 case MESSAGESTATE_IN_SAFE: return(_("Stored in safe"));
818 default: return(_("<Unknown state>"));
823 static const char DmMessageStatus2flag(const isds_message_status *status) {
824 if (!status) return ' ';
825 switch(*status) {
826 case MESSAGESTATE_SENT: return('>');
827 case MESSAGESTATE_STAMPED: return('t');
828 case MESSAGESTATE_INFECTED: return('I');
829 case MESSAGESTATE_DELIVERED: return('N');
830 case MESSAGESTATE_SUBSTITUTED: return('n');
831 case MESSAGESTATE_RECEIVED: return('O');
832 case MESSAGESTATE_READ: return(' ');
833 case MESSAGESTATE_UNDELIVERABLE: return('!');
834 case MESSAGESTATE_REMOVED: return('D');
835 case MESSAGESTATE_IN_SAFE: return('S');
836 default: return('?');
841 /* Return timeval time formatted into shortest string with respect to current
842 * time. Caller must free the string. */
843 static char *timeval2shortstring(const struct timeval *timeval) {
844 struct tm broken, current_broken;
845 time_t current_time;
846 char *buffer = NULL;
847 const size_t buffer_size = 16;
849 if (!timeval) return NULL;
851 buffer = malloc(buffer_size);
852 if (!buffer) goto error;
854 /* Get current time */
855 current_time = time(NULL);
856 if (current_time == (time_t) -1) goto error;
857 if (!localtime_r(&current_time, &current_broken)) goto error;
859 /* Get broken time */
860 if (!localtime_r(&(timeval->tv_sec), &broken)) goto error;
862 /* Select proper abbreviated string representation */
863 if (broken.tm_year == current_broken.tm_year &&
864 broken.tm_yday == current_broken.tm_yday) {
865 /* Minute resolution in the same day */
866 if (!strftime(buffer, buffer_size, _("%k:%M"), &broken))
867 goto error;
868 } else {
869 /* Otherwise month and day */
870 if (!strftime(buffer, buffer_size, _("%b %d"), &broken))
871 goto error;
874 return buffer;
876 error:
877 free(buffer);
878 return strdup(_("<Error>"));
882 /* Formatted Law Authorization if defined. You must free it. */
883 static char *envelope_law2string(const struct isds_envelope *envelope) {
884 char *output = NULL;
885 char *year_locale = NULL, *law_locale = NULL;
886 char *sect_locale = NULL, *par_locale = NULL, *point_locale = NULL;
888 if (!envelope ||
889 !(envelope->dmLegalTitleYear || envelope->dmLegalTitleLaw ||
890 envelope->dmLegalTitleSect || envelope->dmLegalTitlePar ||
891 envelope->dmLegalTitlePoint)
892 ) return NULL;
894 if (envelope->dmLegalTitleYear)
895 shi_asprintf(&year_locale, "%ld", *envelope->dmLegalTitleYear);
896 else
897 year_locale = strdup(_("?"));
899 if (envelope->dmLegalTitleLaw)
900 shi_asprintf(&law_locale, "%ld", *envelope->dmLegalTitleLaw);
901 else
902 law_locale = strdup(_("?"));
904 sect_locale = utf82locale(envelope->dmLegalTitleSect);
905 par_locale = utf82locale(envelope->dmLegalTitlePar);
906 point_locale = utf82locale(envelope->dmLegalTitlePoint);
908 if (point_locale)
909 shi_asprintf(&output, _("point %s, par. %s, sect. %s, %s/%s Coll."),
910 point_locale, par_locale, sect_locale,
911 law_locale, year_locale);
912 else if (par_locale)
913 shi_asprintf(&output, _("par. %s, sect. %s, %s/%s Coll."),
914 par_locale, sect_locale, law_locale, year_locale);
915 else if (sect_locale)
916 shi_asprintf(&output, _("sect. %s, %s/%s Coll."),
917 sect_locale, law_locale, year_locale);
918 else
919 shi_asprintf(&output, _("%s/%s Coll."),
920 law_locale, year_locale);
922 free(year_locale);
923 free(law_locale);
924 free(sect_locale);
925 free(par_locale);
926 free(point_locale);
927 return output;
931 /* Print formatted header if time any of message ID.
932 * @header is locale encoded header name */
933 static void print_header_messages_ids(const char *header,
934 const char *ref_number, const char *ident) {
935 if (ref_number || ident) {
936 oprintf(_("%s:\n"), header);
937 print_header_utf8(_("\tReference number"), ref_number);
938 print_header_utf8(_("\tFile ID"), ident);
943 /* Return formatted hash value */
944 char *hash2string(const struct isds_hash *hash) {
945 const char *algorithm_string = NULL;
946 char *buffer = NULL, *octet = NULL, *new_buffer = NULL;
948 if (!hash || !hash->value) return NULL;
950 switch(hash->algorithm) {
951 case HASH_ALGORITHM_MD5: algorithm_string = (_("MD5")); break;
952 case HASH_ALGORITHM_SHA_1: algorithm_string = (_("SHA-1")); break;
953 case HASH_ALGORITHM_SHA_224: algorithm_string = (_("SHA-224")); break;
954 case HASH_ALGORITHM_SHA_256: algorithm_string = (_("SHA-256")); break;
955 case HASH_ALGORITHM_SHA_384: algorithm_string = (_("SHA-384")); break;
956 case HASH_ALGORITHM_SHA_512: algorithm_string = (_("SHA-512")); break;
957 default: algorithm_string = (_("<Unknown hash algorithm>")); break;
960 for (int i = 0; i < hash->length; i++) {
961 shi_asprintf(&octet, "%02x", ((uint8_t *)(hash->value))[i]);
962 if (!octet) {
963 free(buffer); free(octet); return NULL;
966 if (i > 0)
967 shi_asprintf(&new_buffer, _("%s:%s"), buffer, octet);
968 else
969 shi_asprintf(&new_buffer, "%s", octet);
970 if (!new_buffer) {
971 free(buffer); free(octet); return NULL;
974 buffer = new_buffer; new_buffer = NULL;
977 shi_asprintf(&new_buffer, _("%s %s"), algorithm_string, buffer);
978 free(buffer);
980 return new_buffer;
984 /* Print if any message delivery info exists. */
985 void print_message_delivery_info(const struct isds_envelope *envelope) {
986 char *hash_string = NULL;
988 if (envelope && (envelope->dmType || envelope->dmMessageStatus ||
989 envelope->dmDeliveryTime ||
990 envelope->dmAcceptanceTime || envelope->dmPersonalDelivery ||
991 envelope->dmAllowSubstDelivery || envelope->hash ||
992 envelope->dmOrdinal)) {
993 oprintf(_("Delivery data:\n"));
994 print_header(_("\tMessage type"), DmType2string(envelope->dmType));
995 print_header(_("\tMessage status"),
996 DmMessageStatus2string(envelope->dmMessageStatus));
997 print_header_timeval(_("\tDelivered"), envelope->dmDeliveryTime);
998 print_header_timeval(_("\tAccepted"), envelope->dmAcceptanceTime);
999 print_header_bool(_("\tPersonal delivery required"),
1000 envelope->dmPersonalDelivery);
1001 print_header_bool(_("\tAllow substitutable delivery"),
1002 envelope->dmAllowSubstDelivery);
1004 hash_string = hash2string(envelope->hash);
1005 print_header(_("\tHash"), hash_string);
1006 free(hash_string);
1008 print_header_ulongint(_("\tOrdinal number"), envelope->dmOrdinal);
1013 static const char *event_type2string(const isds_event_type *type) {
1014 if (!type) return (_("<Undefined>"));
1016 switch (*type) {
1017 case EVENT_UKNOWN: return(_("Unknown"));
1018 case EVENT_ACCEPTED_BY_RECIPIENT:
1019 return(_("Accepted by recipient"));
1020 case EVENT_ACCEPTED_BY_FICTION:
1021 return(_("Delivered substitutably"));
1022 case EVENT_UNDELIVERABLE:
1023 return(_("Undeliverable"));
1024 default: return(_("<Unknown event type>"));
1029 /* Print if any delivery event exists. */
1030 void print_delivery_events(const struct isds_list *events) {
1031 int counter_width = 3;
1032 int order = 0;
1033 const struct isds_list *item;
1034 struct isds_event *event;
1036 if (!events) return;
1038 oprintf(_("Delivery events:\n"));
1040 for (item = events; item; item = item->next) {
1041 event = (struct isds_event *) item->data;
1042 if (!event) continue;
1043 order++;
1045 oprintf(_("%*d %s\n"), counter_width, order,
1046 event_type2string(event->type));
1047 print_header_utf8(_("\tDescription"), event->description);
1048 print_header_timeval(_("\tWhen"), event->time);
1053 /* Print formatted message envelope */
1054 void format_envelope(const struct isds_envelope *envelope) {
1055 char *law_string = NULL;
1057 if (!envelope) {
1058 oprintf(_("<Missing envelope>\n"));
1059 return;
1062 print_header_utf8(_("Message ID"), envelope->dmID);
1064 if (envelope->dbIDSender || envelope->dmSender ||
1065 envelope->dmSenderOrgUnit || envelope->dmSenderOrgUnitNum ||
1066 envelope->dmSenderAddress || envelope->dmSenderType ||
1067 envelope->dmOVM) {
1068 oprintf(_("Sender:\n"));
1069 print_header_utf8(_("\tID"), envelope->dbIDSender);
1070 print_header_utf8(_("\tName"), envelope->dmSender);
1071 print_header_utf8(_("\tUnit"), envelope->dmSenderOrgUnit);
1072 print_header_longint(_("\tUnit number"), envelope->dmSenderOrgUnitNum);
1073 print_header_utf8(_("\tAddress"), envelope->dmSenderAddress);
1074 print_header(_("\tType"), DbType2string(envelope->dmSenderType));
1075 print_header_bool(_("\tAs public authority"), envelope->dmOVM);
1078 if (envelope->dbIDRecipient || envelope->dmRecipient ||
1079 envelope->dmRecipientOrgUnit || envelope->dmRecipientOrgUnitNum ||
1080 envelope->dmToHands || envelope->dmRecipientAddress ||
1081 envelope->dmAmbiguousRecipient) {
1082 oprintf(_("Recipient:\n"));
1083 print_header_utf8(_("\tID"), envelope->dbIDRecipient);
1084 print_header_utf8(_("\tName"), envelope->dmRecipient);
1085 print_header_utf8(_("\tUnit"), envelope->dmRecipientOrgUnit);
1086 print_header_longint(_("\tUnit number"),
1087 envelope->dmRecipientOrgUnitNum);
1088 print_header_utf8(_("To hands"), envelope->dmToHands);
1089 print_header_utf8(_("\tAddress"), envelope->dmRecipientAddress);
1090 print_header_bool(_("\tAs public authority"),
1091 envelope->dmAmbiguousRecipient);
1094 print_header_utf8(_("Subject"), envelope->dmAnnotation);
1096 print_header_messages_ids(_("Sender message IDs"),
1097 envelope->dmSenderRefNumber, envelope->dmSenderIdent);
1098 print_header_messages_ids(_("Recipient message IDs"),
1099 envelope->dmRecipientRefNumber, envelope->dmRecipientIdent);
1101 law_string = envelope_law2string(envelope);
1102 print_header(_("Law authorization"), law_string);
1103 free(law_string);
1105 print_message_delivery_info(envelope);
1107 print_header_kbsize(_("Document total size"), envelope->dmAttachmentSize);
1109 /*oprintf("\t\ttimestamp = %p\n", envelope->timestamp);
1110 oprintf("\t\ttimestamp_length = %zu\n", envelope->timestamp_length);*/
1111 print_delivery_events(envelope->events);
1115 const char *DmFileMetaType2string(isds_FileMetaType type) {
1116 switch(type) {
1117 case FILEMETATYPE_MAIN: return(_("Main document"));
1118 case FILEMETATYPE_ENCLOSURE: return(_("Enclosure"));
1119 case FILEMETATYPE_SIGNATURE: return(_("Signature"));
1120 case FILEMETATYPE_META: return(_("Meta document"));
1121 default: return(_("<unknown document type>"));
1126 /* Computes ordinal number of document identified by GUID
1127 * @documents is list of documents where to search
1128 * @id is UTF-8 encoded document ID reference
1129 * Return allocated array of ordinal numbers terminated by -1. Normally only
1130 * one document with @id exists. However ISDS does not check this higher
1131 * requirements and can transport message with duplicate document identifiers.
1132 * Therefore this function returns array of ordinals. Return NULL if error
1133 * occurs (e.g. memory insufficiency). */
1134 static int *dmFileGuid2ordinar(const struct isds_list *documents,
1135 const char *id) {
1136 const struct isds_list *item;
1137 struct isds_document *document;
1138 size_t ordinars_length = 64, offset = 0;
1139 int *ordinars = NULL, *new_ordinars;
1140 int ordinar = 0;
1142 if (!documents || !id || !*id) return NULL;
1143 ordinars = malloc(ordinars_length * sizeof(*ordinars));
1144 if (!ordinars) return NULL;
1146 for (item = documents; item; item = item->next) {
1147 if (!item->data) continue;
1148 ordinar++;
1149 document = (struct isds_document *) (item->data);
1151 if (document->dmFileGuid && !strcmp(document->dmFileGuid, id)) {
1152 if (offset == ordinars_length) {
1153 /* Grow ordinals array */
1154 ordinars_length *= 2;
1155 new_ordinars = realloc(ordinars,
1156 ordinars_length * sizeof(*ordinars));
1157 if (!new_ordinars) {
1158 free(ordinars);
1159 return NULL;
1161 ordinars = new_ordinars;
1164 ordinars[offset++] = ordinar;
1168 ordinars[offset] = -1;
1169 return ordinars;
1173 /* @id is UTF-8 encoded GUID of referred document
1174 * @refernces is array of ordinal numbers if exist terminated by -1. Can be
1175 * NULL to signal error. */
1176 static void format_document_reference(char *id, int *references) {
1177 char *buffer = NULL, *new_buffer = NULL;
1178 if (!id) return;
1180 if (references && *references != -1) {
1181 for (; *references > 0; references++) {
1182 if (!buffer) {
1183 shi_asprintf(&new_buffer, _("%d"), *references);
1184 } else {
1185 shi_asprintf(&new_buffer, _("%s, %d"), buffer, *references);
1187 if (!new_buffer) {
1188 zfree(buffer);
1189 break;
1191 buffer = new_buffer;
1192 new_buffer = NULL;
1194 } else {
1195 char *id_locale = utf82locale(id);
1196 shi_asprintf(&buffer,
1197 _("<Reference to non-existing document ID `%s'>"), id_locale);
1198 free(id_locale);
1201 if (buffer)
1202 print_header(_("\tRefers to"), buffer);
1203 else
1204 print_header(_("\tRefers to"), _("<Error while formatting reference>"));
1205 free(buffer);
1209 /* Print formatted document
1210 * @references is ordinal number of referred document. Formally it's array
1211 * terminated by -1 because non-well-formed message can have more documents
1212 * with equal IDs */
1213 void format_document(const struct isds_document *document, int order,
1214 int *references) {
1215 int counter_width = 3;
1216 char *filename_locale = NULL;
1218 if (!document) return;
1220 oprintf(_("%*d "), counter_width, order);
1222 if (document->dmFileDescr) {
1223 filename_locale = utf82locale(document->dmFileDescr);
1224 oprintf("%s\n", filename_locale);
1225 free(filename_locale);
1226 } else {
1227 oprintf(_("<Unknown file name>\n"));
1230 if (document->is_xml) {
1231 char *message =NULL;
1232 int nodes = 0;
1234 for (xmlNodePtr node = document->xml_node_list; node;
1235 node = node->next) nodes++;
1236 shi_asprintf(&message, ngettext("%d node", "%d nodes", nodes), nodes);
1237 if (message) {
1238 print_header(_("\tXML document"), message);
1239 free(message);
1241 } else {
1242 print_header_size(_("\tSize"), document->data_length);
1244 print_header(_("\tMIME type"), document->dmMimeType);
1246 print_header(_("\tType"), DmFileMetaType2string(document->dmFileMetaType));
1247 print_header_utf8(_("\tMeta format"), document->dmFormat);
1249 print_header_utf8(_("\tID"), document->dmFileGuid);
1250 format_document_reference(document->dmUpFileGuid, references);
1254 /* Print formatted message documents */
1255 void format_documents(const struct isds_list *documents) {
1256 const struct isds_list *item;
1257 const struct isds_document *document;
1258 int i = 0;
1259 int *references;
1260 if (!documents) return;
1262 oprintf(_("Documents:\n"));
1264 for (item = documents; item; item = item->next) {
1265 if (!item->data) continue;
1266 document = (struct isds_document *) item->data;
1267 references = dmFileGuid2ordinar(documents, document->dmUpFileGuid);
1268 format_document(document, ++i, references);
1269 free(references);
1274 /* Print formatted message */
1275 void format_message(const struct isds_message *message) {
1276 if (!message) return;
1277 format_envelope(message->envelope);
1278 format_documents(message->documents);
1282 /* Print formatted list of message copies */
1283 void format_copies(const struct isds_list *copies) {
1284 const struct isds_list *item;
1285 const struct isds_message_copy *copy;
1286 int i = 0;
1287 int counter_width = 3;
1288 if (!copies) return;
1290 for (item = copies; item; item = item->next) {
1291 if (!item->data) continue;
1292 copy = (struct isds_message_copy *) item->data;
1293 i++;
1295 oprintf(_("%*d Recipient:\n"), counter_width, i);
1296 print_header_utf8(_("\tID"), copy->dbIDRecipient);
1297 print_header_utf8(_("\tUnit"), copy->dmRecipientOrgUnit);
1298 print_header_longint(_("\tUnit number"), copy->dmRecipientOrgUnitNum);
1299 print_header_utf8(_("\tTo hands"), copy->dmToHands);
1304 void print_message_list(const struct isds_list *messages, _Bool outgoing) {
1305 const struct isds_list *item;
1306 struct isds_envelope *envelope;
1307 unsigned long int counter = 0;
1309 int counter_max, id_max = 0, name_max = 0, subject_max = 0;
1310 int counter_width, id_width = 0, flags_width = 2, time_width = 6,
1311 name_width = 0, subject_width = 0;
1313 char *id_locale = NULL, flags_locale[3], *time_locale = NULL,
1314 *name_locale = NULL, *subject_locale = NULL;
1315 int screen_cols;
1316 int width;
1319 /* Compute column widths */
1320 rl_get_screen_size(NULL, &screen_cols);
1322 /* Get real maximal widths */
1323 for (counter = 0, item = messages; item; item = item->next) {
1324 if (!item->data || !((struct isds_message *)item->data)->envelope)
1325 continue;
1326 envelope = ((struct isds_message *) item->data)->envelope;
1327 counter++;
1329 width = utf8width(envelope->dmID);
1330 if (width > id_max) id_max = width;
1332 width = utf8width((outgoing) ?
1333 envelope->dmRecipient : envelope->dmSender);
1334 if (width > name_max) name_max = width;
1336 width = utf8width(envelope->dmAnnotation);
1337 if (width > subject_max) subject_max = width;
1339 counter_max = numberwidth(counter);
1341 /* Correct widths to fit into window */
1342 if (counter_max < 0) counter_width = -3; else counter_width = counter_max;
1343 if (id_max < 0) id_width = -6; else id_width = id_max;
1344 if (name_max < 0) name_width = -20; else name_width = name_max;
1345 if (subject_max < 0) subject_width = -32; else subject_width = subject_max;
1347 width = abs(counter_width) + 1 + abs(id_width) + 1 + abs(flags_width) + 1 +
1348 abs(time_width) + 1 + abs(name_width) + 1 + abs(subject_width);
1349 if (width > screen_cols) {
1350 width -= abs(name_width) + abs(subject_width);
1352 name_width = subject_width = 0;
1353 while (width + name_width + subject_width < screen_cols) {
1354 if (name_width < abs(name_max)) name_width++;
1355 if (subject_width < abs(subject_max)) subject_width++;
1357 if (width + name_width + subject_width > screen_cols) subject_width--;
1360 /* Print header */
1361 /* TRANSLATORS: "No" is abbreviation for "Number" in listing header. */
1362 fnprint(stdout, pgettext("list header", "No"), counter_width);
1363 putchar(' ');
1364 fnprint(stdout, _("ID"), id_width);
1365 putchar(' ');
1366 fnprint(stdout, _("Flags"), flags_width);
1367 putchar(' ');
1368 fnprint(stdout, _("Delivered"), time_width);
1369 putchar(' ');
1370 fnprint(stdout, (outgoing) ? _("To") : _("From"), name_width);
1371 putchar(' ');
1372 fnprint(stdout, _("Subject"), subject_width);
1373 oprintf("\n");
1374 for (int i = 0; i < screen_cols; i++) oprintf(_("-"));
1375 oprintf("\n");
1377 /* Print the list */
1378 for (counter = 0, item = messages; item; item = item->next) {
1379 envelope = ((struct isds_message *) item->data)->envelope;
1380 counter++;
1382 oprintf(_("%*lu "), counter_width, counter);
1384 if (!envelope) {
1385 oprintf(_("<Missing envelope>\n"));
1386 continue;
1389 id_locale = utf82locale(envelope->dmID);
1390 name_locale = utf82locale((outgoing) ?
1391 envelope->dmRecipient: envelope->dmSender);
1392 flags_locale[0] = DmType2flag(envelope->dmType);
1393 flags_locale[1] = DmMessageStatus2flag(envelope->dmMessageStatus);
1394 flags_locale[2] = '\0';
1395 time_locale = timeval2shortstring(envelope->dmDeliveryTime);
1396 subject_locale = utf82locale(envelope->dmAnnotation);
1398 fnprint(stdout, id_locale, id_width);
1399 putchar(' ');
1400 fnprint(stdout, flags_locale, flags_width);
1401 putchar(' ');
1402 fnprint(stdout, time_locale, time_width);
1403 putchar(' ');
1404 fnprint(stdout, name_locale, name_width);
1405 putchar(' ');
1406 fnprint(stdout, subject_locale, subject_width);
1407 oprintf("\n");
1409 zfree(id_locale);
1410 zfree(time_locale);
1411 zfree(name_locale);
1412 zfree(subject_locale);
1417 static void format_PersonName(const struct isds_PersonName *personName) {
1418 if (!personName) return;
1420 oprintf(_("Person name:\n"));
1421 print_header_utf8("\tFirst", personName->pnFirstName);
1422 print_header_utf8("\tMiddle", personName->pnMiddleName);
1423 print_header_utf8("\tLast", personName->pnLastName);
1424 print_header_utf8("\tLast at birth", personName->pnLastNameAtBirth);
1428 /* Return formatted date as mallocated string. NULL or special error string can
1429 * be returned. Application must free even the error string. */
1430 char *tm2string(const struct tm *date) {
1431 char *buffer;
1432 size_t buffer_length = 128;
1434 if (!date) return NULL;
1436 buffer = malloc(buffer_length);
1437 if (!buffer) return strdup(_("<Error while formatting date>"));
1439 if (0 == strftime(buffer, buffer_length, "%x", date)) {
1440 free(buffer);
1441 return strdup(_("<Error while formatting date>"));
1444 return buffer;
1448 /* Convert string representation of full ISO 8601 or locale date to tm structure.
1449 * Return NULL if error occurs
1450 * XXX: Not all ISO formats are supported */
1451 struct tm *datestring2tm(const char *string) {
1452 struct tm *date = NULL;
1453 char *offset;
1454 if (!string) return NULL;
1456 date = calloc(1, sizeof(*date));
1457 if (!date) return NULL;
1459 /* xsd:date is ISO 8601 string, thus ASCII */
1460 offset = strptime(string, "%Y-%m-%d", date);
1461 if (offset && *offset == '\0')
1462 return date;
1464 offset = strptime(string, "%x", date);
1465 if (offset && *offset == '\0')
1466 return date;
1468 free(date);
1469 return NULL;
1473 static void format_BirthInfo(const struct isds_BirthInfo *birth) {
1474 char *date;
1475 if (!birth || !(birth->biDate || birth->biCity || birth->biCounty
1476 || birth->biState)) return;
1478 oprintf(_("Birth details:\n"));
1480 date = tm2string(birth->biDate);
1481 print_header(_("\tDate"), date);
1482 free(date);
1484 print_header_utf8(_("\tCity"), birth->biCity);
1485 print_header_utf8(_("\tCounty"), birth->biCounty);
1486 print_header_utf8(_("\tState"), birth->biState);
1490 static void format_Address(const struct isds_Address *address) {
1491 if (!address || !(address->adCity || address->adState ||
1492 address->adNumberInStreet || address->adNumberInMunicipality ||
1493 address->adZipCode || address->adState)) return;
1495 oprintf("Address:\n");
1496 print_header_utf8(_("\tCity"), address->adCity);
1497 print_header_utf8(_("\tStreet"), address->adStreet);
1498 print_header_utf8(_("\tNumber in street"), address->adNumberInStreet);
1499 print_header_utf8(_("\tNumber in municipality"),
1500 address->adNumberInMunicipality);
1501 print_header_utf8(_("\tZIP code"), address->adZipCode);
1502 print_header_utf8(_("\tState"), address->adState);
1506 /* Return static box state string or NULL if undefined */
1507 const char *DbState2string(const long int *state) {
1508 if (!state) return NULL;
1510 switch(*state) {
1511 case DBSTATE_ACCESSIBLE: return(_("Accessible"));
1512 case DBSTATE_TEMP_UNACCESSIBLE: return(_("Temporary inaccessible"));
1513 case DBSTATE_NOT_YET_ACCESSIBLE: return(_("Not yet accessible"));
1514 case DBSTATE_PERM_UNACCESSIBLE: return(_("Permanently inaccessible"));
1515 case DBSTATE_REMOVED: return(_("Deleted"));
1516 default: return(_("<unknown state>"));
1521 void format_DbOwnerInfo(const struct isds_DbOwnerInfo *info) {
1522 if (!info) return;
1524 print_header_utf8(_("Box ID"), info->dbID);
1525 print_header(_("Type"), DbType2string((long int *) (info->dbType)));
1526 print_header_utf8(_("Subject name"), info->firmName);
1527 print_header_utf8(_("Identity number"), info->ic);
1529 format_PersonName(info->personName);
1530 format_BirthInfo(info->birthInfo);
1532 format_Address(info->address);
1534 print_header_utf8(_("Nationality"), info->nationality);
1535 print_header_utf8(_("E-mail"), info->email);
1536 print_header_utf8(_("Phone"), info->telNumber);
1538 print_header_utf8(_("Identifier"), info->identifier);
1539 print_header_utf8(_("Registry code"), info->registryCode);
1541 print_header(_("State"), DbState2string(info->dbState));
1542 print_header_bool(_("Act as public authority"), info->dbEffectiveOVM);
1543 print_header_bool(_("Receive commercial messages"),
1544 info->dbOpenAddressing);
1548 static void format_supervising_firm(const char *ic, const char *firmName) {
1549 if (!ic && !firmName) return;
1551 oprintf(_("Supervising subject:\n"));
1552 print_header_utf8(_("\tIdentity number"), ic);
1553 print_header_utf8(_("\tName"), firmName);
1557 static void format_contact_address(const char *caStreet, const char *caCity,
1558 const char *caZipCode, const char *caState) {
1559 if (!caStreet && !caCity && !caZipCode) return;
1561 oprintf(_("Contact address:\n"));
1562 print_header_utf8(_("\tStreet"), caStreet);
1563 print_header_utf8(_("\tCity"), caCity);
1564 print_header_utf8(_("\tZIP code"), caZipCode);
1565 print_header_utf8(_("\tState"), caState);
1569 void format_DbUserInfo(const struct isds_DbUserInfo *info) {
1570 char *buffer;
1572 if (!info) return;
1574 print_header_utf8(_("User ID"), info->userID);
1575 print_header(_("Type"), UserType2string((long int *) (info->userType)));
1577 buffer = UserPrivils2string(info->userPrivils);
1578 print_header(_("Privileges"), buffer);
1579 zfree(buffer);
1581 format_PersonName(info->personName);
1582 format_Address(info->address);
1584 buffer = tm2string(info->biDate);
1585 print_header(_("Birth date"), buffer);
1586 zfree(buffer);
1588 format_supervising_firm(info->ic, info->firmName);
1589 format_contact_address(info->caStreet, info->caCity, info->caZipCode,
1590 info->caState);