Print struct tm has header
[shigofumi.git] / src / data.c
blob8ce1aef4dbd53c0591d8f7e3a584aac710f4f477
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);
417 oprintf("\t\tdmOrdinal = ");
418 if (!envelope->dmOrdinal) oprintf("NULL\n");
419 else oprintf("%lu\n", *(envelope->dmOrdinal));
421 oprintf("\t\tdmMessageStatus = ");
422 if (!envelope->dmMessageStatus) oprintf("NULL\n");
423 else
424 switch(*(envelope->dmMessageStatus)) {
425 case MESSAGESTATE_SENT: oprintf("SENT\n"); break;
426 case MESSAGESTATE_STAMPED: oprintf("STAMPED\n"); break;
427 case MESSAGESTATE_INFECTED: oprintf("INFECTED\n"); break;
428 case MESSAGESTATE_DELIVERED: oprintf("DELIVERED\n"); break;
429 case MESSAGESTATE_SUBSTITUTED: oprintf("SUBSTITUTED\n"); break;
430 case MESSAGESTATE_RECEIVED: oprintf("RECEIVED\n"); break;
431 case MESSAGESTATE_READ: oprintf("READ\n"); break;
432 case MESSAGESTATE_UNDELIVERABLE: oprintf("UNDELIVERABLE\n"); break;
433 case MESSAGESTATE_REMOVED: oprintf("REMOVED\n"); break;
434 case MESSAGESTATE_IN_SAFE: oprintf("IN_SAFE\n"); break;
435 default: oprintf("<unknown type %d>\n",
436 *(envelope->dmMessageStatus));
439 oprintf("\t\tdmAttachmentSize = ");
440 if (!envelope->dmAttachmentSize) oprintf("NULL\n");
441 else oprintf("%lu kB\n", *(envelope->dmAttachmentSize));
443 oprintf("\t\tdmDeliveryTime = ");
444 print_timeval(envelope->dmDeliveryTime);
446 oprintf("\t\tdmAcceptanceTime = ");
447 print_timeval(envelope->dmAcceptanceTime);
449 oprintf("\t\thash = ");
450 print_hash(envelope->hash);
452 oprintf("\t\ttimestamp = %p\n", envelope->timestamp);
453 oprintf("\t\ttimestamp_length = %zu\n", envelope->timestamp_length);
455 oprintf("\t\tevents = ");
456 print_events(envelope->events);
458 oprintf("\t}\n");
462 void print_document(const struct isds_document *document) {
463 oprintf("\t\tdocument = ");
465 if (!document) {
466 oprintf("NULL\n");
467 return;
469 oprintf("\{\n");
471 oprintf("\t\t\tis_xml = %u\n", !!document->is_xml);
472 oprintf("\t\t\txml_node_list = %p\n", document->xml_node_list);
474 oprintf("\t\t\tdata = %p\n", document->data);
475 oprintf("\t\t\tdata_length = %zu\n", document->data_length);
476 oprintf("\t\t\tdmMimeType = %s\n", document->dmMimeType);
478 oprintf("\t\t\tdmFileMetaType = ");
479 switch(document->dmFileMetaType) {
480 case FILEMETATYPE_MAIN: oprintf("MAIN\n"); break;
481 case FILEMETATYPE_ENCLOSURE: oprintf("ENCLOSURE\n"); break;
482 case FILEMETATYPE_SIGNATURE: oprintf("SIGNATURE\n"); break;
483 case FILEMETATYPE_META: oprintf("META\n"); break;
484 default: oprintf("<unknown type %d>\n", document->dmFileMetaType);
487 oprintf("\t\t\tdmFileGuid = %s\n", document->dmFileGuid);
488 oprintf("\t\t\tdmUpFileGuid = %s\n", document->dmUpFileGuid);
489 oprintf("\t\t\tdmFileDescr = %s\n", document->dmFileDescr);
490 oprintf("\t\t\tdmFormat = %s\n", document->dmFormat);
491 oprintf("\t\t}\n");
495 void print_documents(const struct isds_list *documents) {
496 const struct isds_list *item;
498 oprintf("\tdocuments = ");
500 if (!documents) {
501 oprintf("NULL\n");
502 return;
504 oprintf("{\n");
506 for (item = documents; item; item = item->next) {
507 print_document((struct isds_document *) (item->data));
510 oprintf("\t}\n");
514 void print_message(const struct isds_message *message) {
515 oprintf("message = ");
517 if (!message) {
518 oprintf("NULL\n");
519 return;
522 oprintf("{\n");
524 oprintf("\traw = %p\n", message->raw);
525 oprintf("\traw_length = %zu\n", message->raw_length);
526 oprintf("\traw_type = ");
527 print_raw_type(message->raw_type);
528 print_envelope(message->envelope);
529 print_documents(message->documents);
531 oprintf("}\n");
534 void print_copies(const struct isds_list *copies) {
535 const struct isds_list *item;
536 struct isds_message_copy *copy;
538 oprintf("Copies = ");
539 if (!copies) {
540 oprintf("<NULL>\n");
541 return;
544 oprintf("{\n");
545 for (item = copies; item; item = item->next) {
546 copy = (struct isds_message_copy *) item->data;
547 oprintf("\tCopy = ");
549 if (!copy)
550 oprintf("<NULL>\n");
551 else {
552 oprintf("{\n");
553 oprintf("\t\tdbIDRecipient = %s\n", copy->dbIDRecipient);
554 oprintf("\t\tdmRecipientOrgUnit = %s\n", copy->dmRecipientOrgUnit);
556 oprintf("\t\tdmRecipientOrgUnitNum = ");
557 if (copy->dmRecipientOrgUnitNum)
558 oprintf("%ld\n", *copy->dmRecipientOrgUnitNum);
559 else
560 oprintf("<NULL>\n");
561 oprintf("\t\tdmToHands = %s\n", copy->dmToHands);
563 oprintf("\t\terror = %s\n", isds_strerror(copy->error));
564 oprintf("\t\tdmStatus = %s\n", copy->dmStatus);
565 oprintf("\t\tdmID = %s\n", copy->dmID);
566 oprintf("\t}\n");
569 oprintf("}\n");
573 void compare_hashes(const struct isds_hash *hash1,
574 const struct isds_hash *hash2) {
575 isds_error err;
577 oprintf("Comparing hashes... ");
578 err = isds_hash_cmp(hash1, hash2);
579 if (err == IE_SUCCESS)
580 oprintf("Hashes equal\n");
581 else if
582 (err == IE_NOTEQUAL) oprintf("Hashes differ\n");
583 else
584 oprintf("isds_hash_cmp() failed: %s\n", isds_strerror(err));
588 int progressbar(double upload_total, double upload_current,
589 double download_total, double download_current,
590 void *data) {
592 oprintf("Progress: upload %0f/%0f, download %0f/%0f, data=%p\n",
593 upload_current, upload_total, download_current, download_total,
594 data);
595 return 0;
599 /* Print formatted header if locale-encoded value is defined.
600 * @header is locale encoded header name
601 * @value is locale encoded header value */
602 void print_header(const char *header, const char *value) {
603 if (value && *value) oprintf(_("%s: %s\n"), header, value);
607 /* Print formatted header if boolean value is defined.
608 * @header is locale encoded header name */
609 void print_header_bool(const char *header, _Bool *value) {
610 if (value) print_header(header, (*value) ? _("Yes") : _("No"));
614 /* Print formatted header if long int value is defined.
615 * @header is locale encoded header name */
616 void print_header_longint(const char *header, long int *value) {
617 if (value) oprintf(_("%s: %ld\n"), header, *value);
621 /* Print formatted header if unsigned long int value is defined.
622 * @header is locale encoded header name */
623 void print_header_ulongint(const char *header, unsigned long int *value) {
624 if (value) oprintf(_("%s: %lu\n"), header, *value);
628 /* Print formatted header if time value is defined.
629 * @header is locale encoded header name */
630 void print_header_timeval(const char *header, struct timeval *time) {
631 struct tm broken;
632 char buffer[128];
634 if (!time) return;
636 if (!localtime_r(&(time->tv_sec), &broken)) goto error;
637 if (!strftime(buffer, sizeof(buffer)/sizeof(char), "%c", &broken))
638 goto error;
640 if (!time->tv_usec)
641 oprintf(_("%s: %s\n"), header, buffer);
642 else if ((time->tv_usec % 1000) == 0)
643 oprintf(_("%s: %s, %ld ms\n"), header, buffer, time->tv_usec/1000);
644 else
645 oprintf(_("%s: %s, %ld us\n"), header, buffer, time->tv_usec);
647 return;
649 error:
650 oprintf(_("%s: <Error while formatting time>\n"), header);
651 return;
655 /* Return formatted date as mallocated string. NULL or special error string can
656 * be returned. Application must free even the error string. */
657 char *tm2string(const struct tm *date) {
658 char *buffer;
659 size_t buffer_length = 128;
661 if (!date) return NULL;
663 buffer = malloc(buffer_length);
664 if (!buffer) return strdup(_("<Error while formatting date>"));
666 if (0 == strftime(buffer, buffer_length, "%x", date)) {
667 free(buffer);
668 return strdup(_("<Error while formatting date>"));
671 return buffer;
675 /* Convert string representation of full ISO 8601 or locale date to tm structure.
676 * Return NULL if error occurs
677 * XXX: Not all ISO formats are supported */
678 struct tm *datestring2tm(const char *string) {
679 struct tm *date = NULL;
680 char *offset;
681 if (!string) return NULL;
683 date = calloc(1, sizeof(*date));
684 if (!date) return NULL;
686 /* xsd:date is ISO 8601 string, thus ASCII */
687 offset = strptime(string, "%Y-%m-%d", date);
688 if (offset && *offset == '\0')
689 return date;
691 offset = strptime(string, "%x", date);
692 if (offset && *offset == '\0')
693 return date;
695 free(date);
696 return NULL;
700 /* Print formatted header if date value is defined.
701 * @header is locale encoded header name */
702 void print_header_tm(const char *header, struct tm *date) {
703 char *string;
705 if (NULL == date) return;
706 string = tm2string(date);
708 if (NULL == string)
709 oprintf(_("%s: <Error while formatting date>\n"), header);
710 else
711 print_header(header, string);
713 free(string);
717 /* Print formatted header if UTF-9 value is defined.
718 * @header is locale encoded header name
719 * @value is UTF-8 encoded header value */
720 void print_header_utf8(const char *header, const char *value) {
721 char *value_locale;
723 if (!value) return;
725 value_locale = utf82locale(value);
726 print_header(header,
727 (value_locale) ?
728 value_locale :
729 _("<Error while converting value>"));
730 free(value_locale);
734 /* Print formatted header and byte size.
735 * @header is locale encoded header name */
736 void print_header_size(const char *header, size_t size) {
737 char *buffer = NULL;
739 if (size < (1<<10))
740 shi_asprintf(&buffer, _("%zu B"), size);
741 else if (size < (1<<20))
742 shi_asprintf(&buffer, _("%0.2f KiB"), (float) size/(1<<10));
743 else
744 shi_asprintf(&buffer, _("%0.2f MiB"), (float) size/(1<<20));
746 print_header(header, buffer);
747 free(buffer);
751 /* Print formatted header if long int KB size is defined.
752 * @header is locale encoded header name */
753 void print_header_kbsize(const char *header, const long int *size) {
754 char *buffer = NULL;
755 if (!size) return;
757 if (*size < 0)
758 shi_asprintf(&buffer, _("<Negative size>"));
759 else if (*size < (1000))
760 shi_asprintf(&buffer, _("%lu kB"), *size);
761 else
762 shi_asprintf(&buffer, _("%0.2f MB"), *size/1000.0);
764 print_header(header, buffer);
765 free(buffer);
769 static const char *DbType2string(const long int *type) {
770 if (!type) return NULL;
771 switch(*type) {
772 case DBTYPE_SYSTEM: return(_("System"));
773 case DBTYPE_FO: return(_("Private individual"));
774 case DBTYPE_PFO: return(_("Self-employed individual"));
775 case DBTYPE_PFO_ADVOK: return(_("Lawyer"));
776 case DBTYPE_PFO_DANPOR: return(_("Tax advisor"));
777 case DBTYPE_PFO_INSSPR: return(_("Insolvency administrator"));
778 case DBTYPE_PO: return(_("Organisation"));
779 case DBTYPE_PO_ZAK: return(_("Organization based by law"));
780 case DBTYPE_PO_REQ: return(_("Organization based on request"));
781 case DBTYPE_OVM: return(_("Public authority"));
782 case DBTYPE_OVM_NOTAR: return(_("Notary"));
783 case DBTYPE_OVM_EXEKUT: return(_("Executor"));
784 case DBTYPE_OVM_REQ: return(_("Public authority based on request"));
785 default: return(_("<Unknown type>"));
790 static const char *UserType2string(const long int *type) {
791 if (!type) return NULL;
792 switch(*type) {
793 case USERTYPE_PRIMARY: return(_("Primary"));
794 case USERTYPE_ENTRUSTED: return(_("Entrusted"));
795 case USERTYPE_ADMINISTRATOR: return(_("Administrator"));
796 case USERTYPE_OFFICIAL: return(_("Official"));
797 default: return(_("<Unknown type>"));
802 static const char *isds_sender_type2string(const isds_sender_type *type) {
803 if (!type) return NULL;
804 switch(*type) {
805 case SENDERTYPE_PRIMARY: return(_("Primary"));
806 case SENDERTYPE_ENTRUSTED: return(_("Entrusted"));
807 case SENDERTYPE_ADMINISTRATOR: return(_("Administrator"));
808 case SENDERTYPE_OFFICIAL: return(_("Official"));
809 case SENDERTYPE_VIRTUAL: return(_("Virtual"));
810 default: return(_("<unknown type>"));
815 /* Return formatted user privileges. Caller must free the string */
816 static char *UserPrivils2string(const long int *privils) {
818 const char *priviledges[] = {
819 N_("Read non-personal"),
820 N_("Read all"),
821 N_("Send and read sent"),
822 N_("List messages and read delivery details"),
823 N_("Search boxes"),
824 N_("Administer her box"),
825 N_("Read from safe"),
826 N_("Delete from safe")
828 const int priviledges_count = sizeof(priviledges)/sizeof(priviledges[0]);
829 char *buffer = NULL, *new_buffer = NULL;
831 if (!privils) return NULL;
833 /*oprintf("%ld (", *privils);*/
835 for (int i = 0; i < priviledges_count; i++) {
836 if (*privils & (1<<i)) {
837 if ((*privils % (1<<i)))
838 shi_asprintf(&new_buffer, _("%s, %s"),
839 buffer, _(priviledges[i]));
840 else
841 shi_asprintf(&new_buffer, "%s", _(priviledges[i]));
843 if (!new_buffer) {
844 free(buffer);
845 return(strdup(_("<Error while formatting privileges>")));
848 free(buffer);
849 buffer = new_buffer;
850 new_buffer = NULL;
854 if (*privils >= (1<<priviledges_count)) {
855 if ((*privils % (1<<priviledges_count)))
856 shi_asprintf(&new_buffer, _("%s, %s"),
857 buffer, _("<Unknown privilege>"));
858 else
859 shi_asprintf(&new_buffer, "%s", _("<Unknown privilege>"));
861 if (!new_buffer) {
862 free(buffer);
863 return(strdup(_("<Error while formatting privileges>")));
866 free(buffer);
867 buffer = new_buffer;
868 new_buffer = NULL;
871 return buffer;
875 static const char *DmType2string(const char *type) {
876 if (!type) return NULL;
877 if (!strcmp(type, "V"))
878 return(_("Public"));
879 else if (!strcmp(type, "K"))
880 return(_("Commercial"));
881 else if (!strcmp(type, "A"))
882 return(_("Commercial (initiatory, unused, subsidized)"));
883 else if (!strcmp(type, "B"))
884 return(_("Commercial (initiatory, used, subsidized)"));
885 else if (!strcmp(type, "C"))
886 return(_("Commercial (initiatory, expired, subsidized)"));
887 else if (!strcmp(type, "D"))
888 return(_("Commercial (externally subsidized)"));
889 else if (!strcmp(type, "E"))
890 return(_("Commercial (prepaid by a stamp)"));
891 else if (!strcmp(type, "G"))
892 return(_("Commercial (sponsored)"));
893 else if (!strcmp(type, "I"))
894 return(_("Commercial (initiatory, unused, paid by sender)"));
895 else if (!strcmp(type, "O"))
896 return(_("Commercial (response paid by recipient)"));
897 else if (!strcmp(type, "X"))
898 return(_("Commercial (initiatory, expired, paid by sender)"));
899 else if (!strcmp(type, "Y"))
900 return(_("Commercial (initiatory, used, paid by sender)"));
901 else if (!strcmp(type, "Z"))
902 return(_("Commercial (limitedly subsidized)"));
903 else return(_("<Unknown type>"));
907 /* Simplified commercial status printed on message listing.
908 * 'P' is a public message sent by a government
909 * 'C' is a commercial message
910 * 'I' is a commercial message offering to pay response instead of the
911 * responder
912 * 'i' is a commercial message that offered to pay reposne, but it does not
913 * anymore.
914 * 'R' is a commercial response message paid by sender of the I message. */
915 static const char DmType2flag(const char *type) {
916 if (!type) return ' ';
917 if (!strcmp(type, "V")) return('P');
918 else if (!strcmp(type, "K")) return('C');
919 else if (!strcmp(type, "A")) return('I');
920 else if (!strcmp(type, "B")) return('i');
921 else if (!strcmp(type, "C")) return('i');
922 else if (!strcmp(type, "D")) return('C');
923 else if (!strcmp(type, "E")) return('C');
924 else if (!strcmp(type, "G")) return('C');
925 else if (!strcmp(type, "I")) return('I');
926 else if (!strcmp(type, "O")) return('R');
927 else if (!strcmp(type, "X")) return('i');
928 else if (!strcmp(type, "Y")) return('i');
929 else if (!strcmp(type, "Z")) return('C');
930 else return('?');
934 static const char *DmMessageStatus2string(const isds_message_status *status) {
935 if (!status) return NULL;
936 switch(*status) {
937 case MESSAGESTATE_SENT: return(_("Sent"));
938 case MESSAGESTATE_STAMPED: return(_("Stamped"));
939 case MESSAGESTATE_INFECTED: return(_("Infected"));
940 case MESSAGESTATE_DELIVERED: return(_("Delivered ordinary"));
941 case MESSAGESTATE_SUBSTITUTED: return(_("Delivered substitutably"));
942 case MESSAGESTATE_RECEIVED: return(_("Accepted"));
943 case MESSAGESTATE_READ: return(_("Read"));
944 case MESSAGESTATE_UNDELIVERABLE: return(_("Undeliverable"));
945 case MESSAGESTATE_REMOVED: return(_("Deleted"));
946 case MESSAGESTATE_IN_SAFE: return(_("Stored in safe"));
947 default: return(_("<Unknown state>"));
952 static const char DmMessageStatus2flag(const isds_message_status *status) {
953 if (!status) return ' ';
954 switch(*status) {
955 case MESSAGESTATE_SENT: return('>');
956 case MESSAGESTATE_STAMPED: return('t');
957 case MESSAGESTATE_INFECTED: return('I');
958 case MESSAGESTATE_DELIVERED: return('N');
959 case MESSAGESTATE_SUBSTITUTED: return('n');
960 case MESSAGESTATE_RECEIVED: return('O');
961 case MESSAGESTATE_READ: return(' ');
962 case MESSAGESTATE_UNDELIVERABLE: return('!');
963 case MESSAGESTATE_REMOVED: return('D');
964 case MESSAGESTATE_IN_SAFE: return('S');
965 default: return('?');
970 /* Return timeval time formatted into shortest string with respect to current
971 * time. Caller must free the string. */
972 static char *timeval2shortstring(const struct timeval *timeval) {
973 struct tm broken, current_broken;
974 time_t current_time;
975 char *buffer = NULL;
976 const size_t buffer_size = 16;
978 if (!timeval) return NULL;
980 buffer = malloc(buffer_size);
981 if (!buffer) goto error;
983 /* Get current time */
984 current_time = time(NULL);
985 if (current_time == (time_t) -1) goto error;
986 if (!localtime_r(&current_time, &current_broken)) goto error;
988 /* Get broken time */
989 if (!localtime_r(&(timeval->tv_sec), &broken)) goto error;
991 /* Select proper abbreviated string representation */
992 if (broken.tm_year == current_broken.tm_year &&
993 broken.tm_yday == current_broken.tm_yday) {
994 /* Minute resolution in the same day */
995 if (!strftime(buffer, buffer_size, _("%k:%M"), &broken))
996 goto error;
997 } else {
998 /* Otherwise month and day */
999 if (!strftime(buffer, buffer_size, _("%b %d"), &broken))
1000 goto error;
1003 return buffer;
1005 error:
1006 free(buffer);
1007 return strdup(_("<Error>"));
1011 /* Formatted Law Authorization if defined. You must free it. */
1012 static char *envelope_law2string(const struct isds_envelope *envelope) {
1013 char *output = NULL;
1014 char *year_locale = NULL, *law_locale = NULL;
1015 char *sect_locale = NULL, *par_locale = NULL, *point_locale = NULL;
1017 if (!envelope ||
1018 !(envelope->dmLegalTitleYear || envelope->dmLegalTitleLaw ||
1019 envelope->dmLegalTitleSect || envelope->dmLegalTitlePar ||
1020 envelope->dmLegalTitlePoint)
1021 ) return NULL;
1023 if (envelope->dmLegalTitleYear)
1024 shi_asprintf(&year_locale, "%ld", *envelope->dmLegalTitleYear);
1025 else
1026 year_locale = strdup(_("?"));
1028 if (envelope->dmLegalTitleLaw)
1029 shi_asprintf(&law_locale, "%ld", *envelope->dmLegalTitleLaw);
1030 else
1031 law_locale = strdup(_("?"));
1033 sect_locale = utf82locale(envelope->dmLegalTitleSect);
1034 par_locale = utf82locale(envelope->dmLegalTitlePar);
1035 point_locale = utf82locale(envelope->dmLegalTitlePoint);
1037 if (point_locale)
1038 shi_asprintf(&output, _("point %s, par. %s, sect. %s, %s/%s Coll."),
1039 point_locale, par_locale, sect_locale,
1040 law_locale, year_locale);
1041 else if (par_locale)
1042 shi_asprintf(&output, _("par. %s, sect. %s, %s/%s Coll."),
1043 par_locale, sect_locale, law_locale, year_locale);
1044 else if (sect_locale)
1045 shi_asprintf(&output, _("sect. %s, %s/%s Coll."),
1046 sect_locale, law_locale, year_locale);
1047 else
1048 shi_asprintf(&output, _("%s/%s Coll."),
1049 law_locale, year_locale);
1051 free(year_locale);
1052 free(law_locale);
1053 free(sect_locale);
1054 free(par_locale);
1055 free(point_locale);
1056 return output;
1060 static const char *isds_payment_type2string(const isds_payment_type *type) {
1061 if (!type) return NULL;
1062 switch(*type) {
1063 case PAYMENT_SENDER: return(_("Payed by sender"));
1064 case PAYMENT_STAMP: return(_("Stamp pre-paid by sender"));
1065 case PAYMENT_SPONSOR: return(_("Sponsor pays all messages"));
1066 case PAYMENT_RESPONSE: return(_("Recipient pays a response"));
1067 case PAYMENT_SPONSOR_LIMITED: return(_("Limitedly subsidized"));
1068 case PAYMENT_SPONSOR_EXTERNAL: return(_("Externally subsidized"));
1069 default: return(_("<unknown type>"));
1074 /* Print formatted header if time any of message ID.
1075 * @header is locale encoded header name */
1076 static void print_header_messages_ids(const char *header,
1077 const char *ref_number, const char *ident) {
1078 if (ref_number || ident) {
1079 oprintf(_("%s:\n"), header);
1080 print_header_utf8(_("\tReference number"), ref_number);
1081 print_header_utf8(_("\tFile ID"), ident);
1086 /* Return formatted hash value */
1087 char *hash2string(const struct isds_hash *hash) {
1088 const char *algorithm_string = NULL;
1089 char *buffer = NULL, *octet = NULL, *new_buffer = NULL;
1091 if (!hash || !hash->value) return NULL;
1093 switch(hash->algorithm) {
1094 case HASH_ALGORITHM_MD5: algorithm_string = (_("MD5")); break;
1095 case HASH_ALGORITHM_SHA_1: algorithm_string = (_("SHA-1")); break;
1096 case HASH_ALGORITHM_SHA_224: algorithm_string = (_("SHA-224")); break;
1097 case HASH_ALGORITHM_SHA_256: algorithm_string = (_("SHA-256")); break;
1098 case HASH_ALGORITHM_SHA_384: algorithm_string = (_("SHA-384")); break;
1099 case HASH_ALGORITHM_SHA_512: algorithm_string = (_("SHA-512")); break;
1100 default: algorithm_string = (_("<Unknown hash algorithm>")); break;
1103 for (int i = 0; i < hash->length; i++) {
1104 shi_asprintf(&octet, "%02x", ((uint8_t *)(hash->value))[i]);
1105 if (!octet) {
1106 free(buffer); free(octet); return NULL;
1109 if (i > 0)
1110 shi_asprintf(&new_buffer, _("%s:%s"), buffer, octet);
1111 else
1112 shi_asprintf(&new_buffer, "%s", octet);
1113 if (!new_buffer) {
1114 free(buffer); free(octet); return NULL;
1117 buffer = new_buffer; new_buffer = NULL;
1120 shi_asprintf(&new_buffer, _("%s %s"), algorithm_string, buffer);
1121 free(buffer);
1123 return new_buffer;
1127 /* Print if any message delivery info exists. */
1128 void print_message_delivery_info(const struct isds_envelope *envelope) {
1129 char *hash_string = NULL;
1131 if (envelope && (envelope->dmType || envelope->dmMessageStatus ||
1132 envelope->dmDeliveryTime ||
1133 envelope->dmAcceptanceTime || envelope->dmPersonalDelivery ||
1134 envelope->dmAllowSubstDelivery || envelope->hash ||
1135 envelope->dmOrdinal)) {
1136 oprintf(_("Delivery data:\n"));
1137 print_header(_("\tMessage type"), DmType2string(envelope->dmType));
1138 print_header(_("\tMessage status"),
1139 DmMessageStatus2string(envelope->dmMessageStatus));
1140 print_header_timeval(_("\tDelivered"), envelope->dmDeliveryTime);
1141 print_header_timeval(_("\tAccepted"), envelope->dmAcceptanceTime);
1142 print_header_bool(_("\tPersonal delivery required"),
1143 envelope->dmPersonalDelivery);
1144 print_header_bool(_("\tAllow substitutable delivery"),
1145 envelope->dmAllowSubstDelivery);
1147 hash_string = hash2string(envelope->hash);
1148 print_header(_("\tHash"), hash_string);
1149 free(hash_string);
1151 print_header_ulongint(_("\tOrdinal number"), envelope->dmOrdinal);
1156 static const char *event_type2string(const isds_event_type *type) {
1157 if (!type) return (_("<Undefined>"));
1159 switch (*type) {
1160 case EVENT_UKNOWN: return(_("Unknown"));
1161 case EVENT_ENTERED_SYSTEM:
1162 return(_("Entered system"));
1163 case EVENT_ACCEPTED_BY_RECIPIENT:
1164 return(_("Accepted by recipient"));
1165 case EVENT_ACCEPTED_BY_FICTION:
1166 return(_("Delivered substitutably"));
1167 case EVENT_UNDELIVERABLE:
1168 return(_("Undeliverable"));
1169 case EVENT_COMMERCIAL_ACCEPTED:
1170 return(_("Commerical message accepted by "
1171 "recipient")); break;
1172 case EVENT_DELIVERED:
1173 return(_("Delivered into box")); break;
1174 case EVENT_PRIMARY_LOGIN:
1175 return(_("Primary user logged in")); break;
1176 case EVENT_ENTRUSTED_LOGIN:
1177 return(_("Entrusted user logged in")); break;
1178 case EVENT_SYSCERT_LOGIN:
1179 return(_("Application logged in by system "
1180 "certificate")); break;
1181 default: return(_("<Unknown event type>"));
1186 /* Print if any delivery event exists. */
1187 void print_delivery_events(const struct isds_list *events) {
1188 int counter_width = 3;
1189 int order = 0;
1190 const struct isds_list *item;
1191 struct isds_event *event;
1193 if (!events) return;
1195 oprintf(_("Delivery events:\n"));
1197 for (item = events; item; item = item->next) {
1198 event = (struct isds_event *) item->data;
1199 if (!event) continue;
1200 order++;
1202 oprintf(_("%*d %s\n"), counter_width, order,
1203 event_type2string(event->type));
1204 print_header_utf8(_("\tDescription"), event->description);
1205 print_header_timeval(_("\tWhen"), event->time);
1210 /* Print formatted message envelope */
1211 void format_envelope(const struct isds_envelope *envelope) {
1212 char *law_string = NULL;
1214 if (!envelope) {
1215 oprintf(_("<Missing envelope>\n"));
1216 return;
1219 print_header_utf8(_("Message ID"), envelope->dmID);
1221 if (envelope->dbIDSender || envelope->dmSender ||
1222 envelope->dmSenderOrgUnit || envelope->dmSenderOrgUnitNum ||
1223 envelope->dmSenderAddress || envelope->dmSenderType ||
1224 envelope->dmOVM) {
1225 oprintf(_("Sender:\n"));
1226 print_header_utf8(_("\tID"), envelope->dbIDSender);
1227 print_header_utf8(_("\tName"), envelope->dmSender);
1228 print_header_utf8(_("\tUnit"), envelope->dmSenderOrgUnit);
1229 print_header_longint(_("\tUnit number"), envelope->dmSenderOrgUnitNum);
1230 print_header_utf8(_("\tAddress"), envelope->dmSenderAddress);
1231 print_header(_("\tType"), DbType2string(envelope->dmSenderType));
1232 print_header_bool(_("\tAs public authority"), envelope->dmOVM);
1235 if (envelope->dbIDRecipient || envelope->dmRecipient ||
1236 envelope->dmRecipientOrgUnit || envelope->dmRecipientOrgUnitNum ||
1237 envelope->dmToHands || envelope->dmRecipientAddress ||
1238 envelope->dmAmbiguousRecipient) {
1239 oprintf(_("Recipient:\n"));
1240 print_header_utf8(_("\tID"), envelope->dbIDRecipient);
1241 print_header_utf8(_("\tName"), envelope->dmRecipient);
1242 print_header_utf8(_("\tUnit"), envelope->dmRecipientOrgUnit);
1243 print_header_longint(_("\tUnit number"),
1244 envelope->dmRecipientOrgUnitNum);
1245 print_header_utf8(_("To hands"), envelope->dmToHands);
1246 print_header_utf8(_("\tAddress"), envelope->dmRecipientAddress);
1247 print_header_bool(_("\tAs public authority"),
1248 envelope->dmAmbiguousRecipient);
1251 print_header_utf8(_("Subject"), envelope->dmAnnotation);
1253 print_header_messages_ids(_("Sender message IDs"),
1254 envelope->dmSenderRefNumber, envelope->dmSenderIdent);
1255 print_header_messages_ids(_("Recipient message IDs"),
1256 envelope->dmRecipientRefNumber, envelope->dmRecipientIdent);
1258 law_string = envelope_law2string(envelope);
1259 print_header(_("Law authorization"), law_string);
1260 free(law_string);
1262 print_message_delivery_info(envelope);
1264 print_header_kbsize(_("Document total size"), envelope->dmAttachmentSize);
1266 /*oprintf("\t\ttimestamp = %p\n", envelope->timestamp);
1267 oprintf("\t\ttimestamp_length = %zu\n", envelope->timestamp_length);*/
1268 print_delivery_events(envelope->events);
1272 const char *DmFileMetaType2string(isds_FileMetaType type) {
1273 switch(type) {
1274 case FILEMETATYPE_MAIN: return(_("Main document"));
1275 case FILEMETATYPE_ENCLOSURE: return(_("Enclosure"));
1276 case FILEMETATYPE_SIGNATURE: return(_("Signature"));
1277 case FILEMETATYPE_META: return(_("Meta document"));
1278 default: return(_("<unknown document type>"));
1283 /* Computes ordinal number of document identified by GUID
1284 * @documents is list of documents where to search
1285 * @id is UTF-8 encoded document ID reference
1286 * Return allocated array of ordinal numbers terminated by -1. Normally only
1287 * one document with @id exists. However ISDS does not check this higher
1288 * requirements and can transport message with duplicate document identifiers.
1289 * Therefore this function returns array of ordinals. Return NULL if error
1290 * occurs (e.g. memory insufficiency). */
1291 static int *dmFileGuid2ordinar(const struct isds_list *documents,
1292 const char *id) {
1293 const struct isds_list *item;
1294 struct isds_document *document;
1295 size_t ordinars_length = 64, offset = 0;
1296 int *ordinars = NULL, *new_ordinars;
1297 int ordinar = 0;
1299 if (!documents || !id || !*id) return NULL;
1300 ordinars = malloc(ordinars_length * sizeof(*ordinars));
1301 if (!ordinars) return NULL;
1303 for (item = documents; item; item = item->next) {
1304 if (!item->data) continue;
1305 ordinar++;
1306 document = (struct isds_document *) (item->data);
1308 if (document->dmFileGuid && !strcmp(document->dmFileGuid, id)) {
1309 if (offset == ordinars_length) {
1310 /* Grow ordinals array */
1311 ordinars_length *= 2;
1312 new_ordinars = realloc(ordinars,
1313 ordinars_length * sizeof(*ordinars));
1314 if (!new_ordinars) {
1315 free(ordinars);
1316 return NULL;
1318 ordinars = new_ordinars;
1321 ordinars[offset++] = ordinar;
1325 ordinars[offset] = -1;
1326 return ordinars;
1330 /* @id is UTF-8 encoded GUID of referred document
1331 * @refernces is array of ordinal numbers if exist terminated by -1. Can be
1332 * NULL to signal error. */
1333 static void format_document_reference(char *id, int *references) {
1334 char *buffer = NULL, *new_buffer = NULL;
1335 if (!id) return;
1337 if (references && *references != -1) {
1338 for (; *references > 0; references++) {
1339 if (!buffer) {
1340 shi_asprintf(&new_buffer, _("%d"), *references);
1341 } else {
1342 shi_asprintf(&new_buffer, _("%s, %d"), buffer, *references);
1344 if (!new_buffer) {
1345 zfree(buffer);
1346 break;
1348 buffer = new_buffer;
1349 new_buffer = NULL;
1351 } else {
1352 char *id_locale = utf82locale(id);
1353 shi_asprintf(&buffer,
1354 _("<Reference to non-existing document ID `%s'>"), id_locale);
1355 free(id_locale);
1358 if (buffer)
1359 print_header(_("\tRefers to"), buffer);
1360 else
1361 print_header(_("\tRefers to"), _("<Error while formatting reference>"));
1362 free(buffer);
1366 /* Print formatted document
1367 * @references is ordinal number of referred document. Formally it's array
1368 * terminated by -1 because non-well-formed message can have more documents
1369 * with equal IDs */
1370 void format_document(const struct isds_document *document, int order,
1371 int *references) {
1372 int counter_width = 3;
1373 char *filename_locale = NULL;
1375 if (!document) return;
1377 oprintf(_("%*d "), counter_width, order);
1379 if (document->dmFileDescr) {
1380 filename_locale = utf82locale(document->dmFileDescr);
1381 oprintf("%s\n", filename_locale);
1382 free(filename_locale);
1383 } else {
1384 oprintf(_("<Unknown file name>\n"));
1387 if (document->is_xml) {
1388 char *message =NULL;
1389 int nodes = 0;
1391 for (xmlNodePtr node = document->xml_node_list; node;
1392 node = node->next) nodes++;
1393 shi_asprintf(&message, ngettext("%d node", "%d nodes", nodes), nodes);
1394 if (message) {
1395 print_header(_("\tXML document"), message);
1396 free(message);
1398 } else {
1399 print_header_size(_("\tSize"), document->data_length);
1401 print_header(_("\tMIME type"), document->dmMimeType);
1403 print_header(_("\tType"), DmFileMetaType2string(document->dmFileMetaType));
1404 print_header_utf8(_("\tMeta format"), document->dmFormat);
1406 print_header_utf8(_("\tID"), document->dmFileGuid);
1407 format_document_reference(document->dmUpFileGuid, references);
1411 /* Print formatted message documents */
1412 void format_documents(const struct isds_list *documents) {
1413 const struct isds_list *item;
1414 const struct isds_document *document;
1415 int i = 0;
1416 int *references;
1417 if (!documents) return;
1419 oprintf(_("Documents:\n"));
1421 for (item = documents; item; item = item->next) {
1422 if (!item->data) continue;
1423 document = (struct isds_document *) item->data;
1424 references = dmFileGuid2ordinar(documents, document->dmUpFileGuid);
1425 format_document(document, ++i, references);
1426 free(references);
1431 /* Print formatted message */
1432 void format_message(const struct isds_message *message) {
1433 if (!message) return;
1434 format_envelope(message->envelope);
1435 format_documents(message->documents);
1439 /* Print formatted list of message copies */
1440 void format_copies(const struct isds_list *copies) {
1441 const struct isds_list *item;
1442 const struct isds_message_copy *copy;
1443 int i = 0;
1444 int counter_width = 3;
1445 if (!copies) return;
1447 for (item = copies; item; item = item->next) {
1448 if (!item->data) continue;
1449 copy = (struct isds_message_copy *) item->data;
1450 i++;
1452 oprintf(_("%*d Recipient:\n"), counter_width, i);
1453 print_header_utf8(_("\tID"), copy->dbIDRecipient);
1454 print_header_utf8(_("\tUnit"), copy->dmRecipientOrgUnit);
1455 print_header_longint(_("\tUnit number"), copy->dmRecipientOrgUnitNum);
1456 print_header_utf8(_("\tTo hands"), copy->dmToHands);
1461 void print_message_list(const struct isds_list *messages, _Bool outgoing) {
1462 const struct isds_list *item;
1463 struct isds_envelope *envelope;
1464 unsigned long int counter = 0;
1466 int counter_max, id_max = 0, name_max = 0, subject_max = 0;
1467 int counter_width, id_width = 0, flags_width = 2, time_width = 6,
1468 name_width = 0, subject_width = 0;
1470 char *id_locale = NULL, flags_locale[3], *time_locale = NULL,
1471 *name_locale = NULL, *subject_locale = NULL;
1472 int screen_cols;
1473 int width;
1476 /* Compute column widths */
1477 rl_get_screen_size(NULL, &screen_cols);
1479 /* Get real maximal widths */
1480 for (counter = 0, item = messages; item; item = item->next) {
1481 if (!item->data || !((struct isds_message *)item->data)->envelope)
1482 continue;
1483 envelope = ((struct isds_message *) item->data)->envelope;
1484 counter++;
1486 width = utf8width(envelope->dmID);
1487 if (width > id_max) id_max = width;
1489 width = utf8width((outgoing) ?
1490 envelope->dmRecipient : envelope->dmSender);
1491 if (width > name_max) name_max = width;
1493 width = utf8width(envelope->dmAnnotation);
1494 if (width > subject_max) subject_max = width;
1496 counter_max = numberwidth(counter);
1498 /* Correct widths to fit into window */
1499 if (counter_max < 0) counter_width = -3; else counter_width = counter_max;
1500 if (id_max < 0) id_width = -6; else id_width = id_max;
1501 if (name_max < 0) name_width = -20; else name_width = name_max;
1502 if (subject_max < 0) subject_width = -32; else subject_width = subject_max;
1504 width = abs(counter_width) + 1 + abs(id_width) + 1 + abs(flags_width) + 1 +
1505 abs(time_width) + 1 + abs(name_width) + 1 + abs(subject_width);
1506 if (width > screen_cols) {
1507 width -= abs(name_width) + abs(subject_width);
1509 name_width = subject_width = 0;
1510 while (width + name_width + subject_width < screen_cols) {
1511 if (name_width < abs(name_max)) name_width++;
1512 if (subject_width < abs(subject_max)) subject_width++;
1514 if (width + name_width + subject_width > screen_cols) subject_width--;
1517 /* Print header */
1518 /* TRANSLATORS: "No" is abbreviation for "Number" in listing header. */
1519 onprint(pgettext("list header", "No"), counter_width);
1520 oprintf(" ");
1521 onprint(_("ID"), id_width);
1522 oprintf(" ");
1523 onprint(_("Flags"), flags_width);
1524 oprintf(" ");
1525 onprint(_("Delivered"), time_width);
1526 oprintf(" ");
1527 onprint((outgoing) ? _("To") : _("From"), name_width);
1528 oprintf(" ");
1529 onprint(_("Subject"), subject_width);
1530 oprintf("\n");
1531 for (int i = 0; i < screen_cols; i++) oprintf(_("-"));
1532 oprintf("\n");
1534 /* Print the list */
1535 for (counter = 0, item = messages; item; item = item->next) {
1536 envelope = ((struct isds_message *) item->data)->envelope;
1537 counter++;
1539 oprintf(_("%*lu "), counter_width, counter);
1541 if (!envelope) {
1542 oprintf(_("<Missing envelope>\n"));
1543 continue;
1546 id_locale = utf82locale(envelope->dmID);
1547 name_locale = utf82locale((outgoing) ?
1548 envelope->dmRecipient: envelope->dmSender);
1549 flags_locale[0] = DmType2flag(envelope->dmType);
1550 flags_locale[1] = DmMessageStatus2flag(envelope->dmMessageStatus);
1551 flags_locale[2] = '\0';
1552 time_locale = timeval2shortstring(envelope->dmDeliveryTime);
1553 subject_locale = utf82locale(envelope->dmAnnotation);
1555 onprint(id_locale, id_width);
1556 oprintf(" ");
1557 onprint(flags_locale, flags_width);
1558 oprintf(" ");
1559 onprint(time_locale, time_width);
1560 oprintf(" ");
1561 onprint(name_locale, name_width);
1562 oprintf(" ");
1563 onprint(subject_locale, subject_width);
1564 oprintf("\n");
1566 zfree(id_locale);
1567 zfree(time_locale);
1568 zfree(name_locale);
1569 zfree(subject_locale);
1574 static void format_PersonName(const struct isds_PersonName *personName) {
1575 if (!personName) return;
1577 oprintf(_("Person name:\n"));
1578 print_header_utf8(_("\tFirst"), personName->pnFirstName);
1579 print_header_utf8(_("\tMiddle"), personName->pnMiddleName);
1580 print_header_utf8(_("\tLast"), personName->pnLastName);
1581 print_header_utf8(_("\tLast at birth"),
1582 personName->pnLastNameAtBirth);
1586 static void format_BirthInfo(const struct isds_BirthInfo *birth) {
1587 if (!birth || !(birth->biDate || birth->biCity || birth->biCounty
1588 || birth->biState)) return;
1590 oprintf(_("Birth details:\n"));
1592 print_header_tm(_("\tDate"), birth->biDate);
1593 print_header_utf8(_("\tCity"), birth->biCity);
1594 print_header_utf8(_("\tCounty"), birth->biCounty);
1595 print_header_utf8(_("\tState"), birth->biState);
1599 static void format_Address(const struct isds_Address *address) {
1600 if (!address || !(address->adCity || address->adState ||
1601 address->adNumberInStreet || address->adNumberInMunicipality ||
1602 address->adZipCode || address->adState)) return;
1604 oprintf("Address:\n");
1605 print_header_utf8(_("\tCity"), address->adCity);
1606 print_header_utf8(_("\tStreet"), address->adStreet);
1607 print_header_utf8(_("\tNumber in street"), address->adNumberInStreet);
1608 print_header_utf8(_("\tNumber in municipality"),
1609 address->adNumberInMunicipality);
1610 print_header_utf8(_("\tZIP code"), address->adZipCode);
1611 print_header_utf8(_("\tState"), address->adState);
1615 /* Return static box state string or NULL if undefined */
1616 const char *DbState2string(const long int *state) {
1617 if (!state) return NULL;
1619 switch(*state) {
1620 case DBSTATE_ACCESSIBLE: return(_("Accessible"));
1621 case DBSTATE_TEMP_UNACCESSIBLE: return(_("Temporary inaccessible"));
1622 case DBSTATE_NOT_YET_ACCESSIBLE: return(_("Not yet accessible"));
1623 case DBSTATE_PERM_UNACCESSIBLE: return(_("Permanently inaccessible"));
1624 case DBSTATE_REMOVED: return(_("Deleted"));
1625 default: return(_("<unknown state>"));
1630 void format_DbOwnerInfo(const struct isds_DbOwnerInfo *info) {
1631 if (!info) return;
1633 print_header_utf8(_("Box ID"), info->dbID);
1634 print_header(_("Type"), DbType2string((long int *) (info->dbType)));
1635 print_header_utf8(_("Subject name"), info->firmName);
1636 print_header_utf8(_("Identity number"), info->ic);
1638 format_PersonName(info->personName);
1639 format_BirthInfo(info->birthInfo);
1641 format_Address(info->address);
1643 print_header_utf8(_("Nationality"), info->nationality);
1644 print_header_utf8(_("E-mail"), info->email);
1645 print_header_utf8(_("Phone"), info->telNumber);
1647 print_header_utf8(_("Identifier"), info->identifier);
1648 print_header_utf8(_("Registry code"), info->registryCode);
1650 print_header(_("State"), DbState2string(info->dbState));
1651 print_header_bool(_("Act as public authority"), info->dbEffectiveOVM);
1652 print_header_bool(_("Receive commercial messages"),
1653 info->dbOpenAddressing);
1657 static void format_supervising_firm(const char *ic, const char *firmName) {
1658 if (!ic && !firmName) return;
1660 oprintf(_("Supervising subject:\n"));
1661 print_header_utf8(_("\tIdentity number"), ic);
1662 print_header_utf8(_("\tName"), firmName);
1666 static void format_contact_address(const char *caStreet, const char *caCity,
1667 const char *caZipCode, const char *caState) {
1668 if (!caStreet && !caCity && !caZipCode) return;
1670 oprintf(_("Contact address:\n"));
1671 print_header_utf8(_("\tStreet"), caStreet);
1672 print_header_utf8(_("\tCity"), caCity);
1673 print_header_utf8(_("\tZIP code"), caZipCode);
1674 print_header_utf8(_("\tState"), caState);
1678 void format_DbUserInfo(const struct isds_DbUserInfo *info) {
1679 char *buffer;
1681 if (!info) return;
1683 print_header_utf8(_("User ID"), info->userID);
1684 print_header(_("Type"), UserType2string((long int *) (info->userType)));
1686 buffer = UserPrivils2string(info->userPrivils);
1687 print_header(_("Privileges"), buffer);
1688 zfree(buffer);
1690 format_PersonName(info->personName);
1691 format_Address(info->address);
1693 print_header_tm(_("Birth date"), info->biDate);
1695 format_supervising_firm(info->ic, info->firmName);
1696 format_contact_address(info->caStreet, info->caCity, info->caZipCode,
1697 info->caState);
1701 /* Print formated details about message sender */
1702 void format_sender_info(const char *dbID, const isds_sender_type *type,
1703 const char *raw_type, const char *name) {
1704 const char *type_string;
1706 if (!dbID && !type && !raw_type && !name) return;
1708 oprintf(_("Message sender:\n"));
1709 print_header_utf8(_("\tMessage ID"), dbID);
1711 type_string = isds_sender_type2string(type);
1712 if (type_string)
1713 print_header(_("\tType"), type_string);
1714 else
1715 print_header_utf8(_("\tRaw type"), raw_type);
1717 print_header_utf8(_("\tName"), name);
1721 void format_commercial_permission(
1722 const struct isds_commercial_permission *permission) {
1723 if (NULL == permission) return;
1725 print_header(_("Payment type"),
1726 isds_payment_type2string(&permission->type));
1727 print_header_utf8(_("Allowed recipient box ID"), permission->recipient);
1728 print_header_utf8(_("Payed by owner of box ID"), permission->payer);
1729 print_header_timeval(_("Permission expires"), permission->expiration);
1730 print_header_ulongint(_("Remaining messages"), permission->count);
1731 print_header_utf8(_("Reference to request"), permission->reply_identifier);