1 #include "pEp_internal.h"
2 #include "message_api.h"
12 #define MIN(A, B) ((B) > (A) ? (A) : (B))
15 #define MAX(A, B) ((B) > (A) ? (B) : (A))
19 static bool string_equality(const char *s1, const char *s2)
21 if (s1 == NULL || s2 == NULL)
26 return strcmp(s1, s2) == 0;
29 static bool is_mime_type(const bloblist_t *bl, const char *mt)
33 return bl && string_equality(bl->mime_type, mt);
36 static bool is_fileending(const bloblist_t *bl, const char *fe)
40 if (bl == NULL || bl->filename == NULL)
43 assert(bl && bl->filename);
45 size_t fe_len = strlen(fe);
46 size_t fn_len = strlen(bl->filename);
51 assert(fn_len > fe_len);
53 return strcmp(bl->filename + (fn_len - fe_len), fe) == 0;
56 void import_attached_keys(PEP_SESSION session, const message *msg)
62 for (bl = msg->attachments; bl && bl->value; bl = bl->next) {
63 assert(bl && bl->value && bl->size);
65 if (bl->mime_type == NULL ||
66 is_mime_type(bl, "application/octet-stream")) {
67 if (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
68 is_fileending(bl, ".key") ||
69 string_equality(bl->filename, "key.asc"))
70 import_key(session, bl->value, bl->size);
72 else if (is_mime_type(bl, "application/pgp-keys")) {
73 import_key(session, bl->value, bl->size);
75 else if (is_mime_type(bl, "text/plain")) {
76 if (is_fileending(bl, ".pgp") || is_fileending(bl, ".gpg") ||
77 is_fileending(bl, ".key") || is_fileending(bl, ".asc"))
78 import_key(session, bl->value, bl->size);
83 void attach_own_key(PEP_SESSION session, message *msg)
92 if (msg->dir == PEP_dir_incoming)
95 assert(msg->from && msg->from->fpr);
96 if (msg->from == NULL || msg->from->fpr == NULL)
99 PEP_STATUS status = export_key(session, msg->from->fpr, &keydata, &size);
100 assert(status == PEP_STATUS_OK);
101 if (status != PEP_STATUS_OK)
105 bl = bloblist_add(msg->attachments, keydata, size, "application/pgp-keys",
107 if (msg->attachments == NULL && bl)
108 msg->attachments = bl;
111 static void add_opt_field(message *msg, const char *name, const char *value)
115 if (msg && name && value) {
116 stringpair_t *pair = new_stringpair(name, value);
120 stringpair_list_t *field = stringpair_list_add(msg->opt_fields, pair);
124 if (msg->opt_fields == NULL)
125 msg->opt_fields = field;
129 PEP_cryptotech determine_encryption_format(message *msg)
133 if (is_PGP_message_text(msg->longmsg)) {
134 msg->enc_format = PEP_enc_pieces;
135 return PEP_crypt_OpenPGP;
137 else if (msg->attachments && msg->attachments->next &&
138 is_mime_type(msg->attachments, "application/pgp-encrypted") &&
139 is_PGP_message_text(msg->attachments->next->value)
141 msg->enc_format = PEP_enc_PGP_MIME;
142 return PEP_crypt_OpenPGP;
145 msg->enc_format = PEP_enc_none;
146 return PEP_crypt_none;
150 static char * combine_short_and_long(const char *shortmsg, const char *longmsg)
155 assert(strcmp(shortmsg, "pEp") != 0);
160 ptext = calloc(1, strlen(shortmsg) + strlen(longmsg) + 12);
165 strcpy(ptext, "Subject: ");
166 strcat(ptext, shortmsg);
167 strcat(ptext, "\n\n");
168 strcat(ptext, longmsg);
173 static int seperate_short_and_long(const char *src, char **shortmsg, char **longmsg)
175 char *_shortmsg = NULL;
176 char *_longmsg = NULL;
185 if (strncasecmp(src, "subject: ", 9) == 0) {
186 char *line_end = strchr(src, '\n');
188 if (line_end == NULL) {
189 _shortmsg = strdup(src + 9);
190 if (_shortmsg == NULL)
195 size_t n = line_end - src;
197 if (*(line_end - 1) == '\r')
198 _shortmsg = strndup(src + 9, n - 10);
200 _shortmsg = strndup(src + 9, n - 9);
202 if (_shortmsg == NULL)
205 while (*(src + n) && (*(src + n) == '\n' || *(src + n) == '\r'))
209 _longmsg = strdup(src + n);
210 if (_longmsg == NULL)
216 _shortmsg = strdup("");
217 if (_shortmsg == NULL)
219 _longmsg = strdup(src);
220 if (_longmsg == NULL)
224 *shortmsg = _shortmsg;
236 static PEP_STATUS copy_fields(message *dst, const message *src)
241 free_timestamp(dst->sent);
244 dst->sent = timestamp_dup(src->sent);
245 if (dst->sent == NULL)
246 return PEP_OUT_OF_MEMORY;
249 free_timestamp(dst->recv);
252 dst->recv = timestamp_dup(src->recv);
253 if (dst->recv == NULL)
254 return PEP_OUT_OF_MEMORY;
257 free_identity(dst->from);
260 dst->from = identity_dup(src->from);
261 if (dst->from == NULL)
262 return PEP_OUT_OF_MEMORY;
265 free_identity_list(dst->to);
267 if (src->to && src->to->ident) {
268 dst->to = identity_list_dup(src->to);
270 return PEP_OUT_OF_MEMORY;
273 free_identity(dst->recv_by);
276 dst->recv_by = identity_dup(src->recv_by);
277 if (dst->recv_by == NULL)
278 return PEP_OUT_OF_MEMORY;
281 free_identity_list(dst->cc);
283 if (src->cc && src->cc->ident) {
284 dst->cc = identity_list_dup(src->cc);
286 return PEP_OUT_OF_MEMORY;
289 free_identity_list(dst->bcc);
291 if (src->bcc && src->bcc->ident) {
292 dst->bcc = identity_list_dup(src->bcc);
293 if (dst->bcc == NULL)
294 return PEP_OUT_OF_MEMORY;
297 free_identity_list(dst->reply_to);
298 dst->reply_to = NULL;
299 if (src->reply_to && src->reply_to->ident) {
300 dst->reply_to = identity_list_dup(src->reply_to);
301 if (dst->reply_to == NULL)
302 return PEP_OUT_OF_MEMORY;
305 free_stringlist(dst->in_reply_to);
306 dst->in_reply_to = NULL;
307 if (src->in_reply_to && src->in_reply_to->value) {
308 dst->in_reply_to = stringlist_dup(src->in_reply_to);
309 if (dst->in_reply_to == NULL)
310 return PEP_OUT_OF_MEMORY;
313 free_stringlist(dst->references);
314 dst->references = NULL;
315 if (src->references) {
316 dst->references = stringlist_dup(src->references);
317 if (dst->references == NULL)
318 return PEP_OUT_OF_MEMORY;
321 free_stringlist(dst->keywords);
322 dst->keywords = NULL;
323 if (src->keywords && src->keywords->value) {
324 dst->keywords = stringlist_dup(src->keywords);
325 if (dst->keywords == NULL)
326 return PEP_OUT_OF_MEMORY;
330 dst->comments = NULL;
332 dst->comments = strdup(src->comments);
333 assert(dst->comments);
334 if (dst->comments == NULL)
335 return PEP_OUT_OF_MEMORY;
338 return PEP_STATUS_OK;
341 static message * clone_to_empty_message(const message * src)
344 message * msg = NULL;
348 msg = calloc(1, sizeof(message));
355 status = copy_fields(msg, src);
356 if (status != PEP_STATUS_OK)
366 static PEP_STATUS encrypt_PGP_MIME(
373 PEP_STATUS status = PEP_STATUS_OK;
374 bool free_ptext = false;
378 char *mimetext = NULL;
380 assert(dst->longmsg == NULL);
381 dst->enc_format = PEP_enc_PGP_MIME;
383 if (src->shortmsg && strcmp(src->shortmsg, "pEp") != 0) {
384 ptext = combine_short_and_long(src->shortmsg, src->longmsg);
389 else if (src->longmsg) {
390 ptext = src->longmsg;
396 message *_src = calloc(1, sizeof(message));
400 _src->longmsg = ptext;
401 _src->longmsg_formatted = src->longmsg_formatted;
402 _src->attachments = src->attachments;
403 _src->enc_format = PEP_enc_none;
404 status = mime_encode_message(_src, true, &mimetext);
405 assert(status == PEP_STATUS_OK);
410 if (mimetext == NULL)
413 status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
419 dst->longmsg = strdup("this message was encrypted with p≡p "
420 "http://pEp-project.org");
421 if (dst->longmsg == NULL)
424 char *v = strdup("Version: 1");
428 bloblist_t *_a = new_bloblist(v, 11, "application/pgp-encrypted", NULL);
431 dst->attachments = _a;
433 _ctext = malloc(csize);
437 memcpy(_ctext, ctext, csize);
439 _a = bloblist_add(_a, _ctext, csize, "application/octet-stream",
444 return PEP_STATUS_OK;
447 status = PEP_OUT_OF_MEMORY;
456 static PEP_STATUS encrypt_PGP_in_pieces(
463 PEP_STATUS status = PEP_STATUS_OK;
467 assert(dst->longmsg == NULL);
468 assert(dst->attachments == NULL);
470 dst->enc_format = PEP_enc_pieces;
472 if (src->shortmsg && strcmp(src->shortmsg, "pEp") != 0) {
473 char *ptext = combine_short_and_long(src->shortmsg, src->longmsg);
477 status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
481 dst->longmsg = strndup(ctext, csize);
482 assert(dst->longmsg);
483 if (dst->longmsg == NULL)
490 else if (src->longmsg) {
491 char *ptext = src->longmsg;
492 status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
495 dst->longmsg = strndup(ctext, csize);
496 assert(dst->longmsg);
497 if (dst->longmsg == NULL)
505 dst->longmsg = strdup("");
506 if (dst->longmsg == NULL)
510 if (src->longmsg_formatted) {
511 char *ptext = src->longmsg_formatted;
512 status = encrypt_and_sign(session, keys, ptext, strlen(ptext), &ctext,
515 char *_ctext = malloc(csize);
519 memcpy(_ctext, ctext, csize);
521 bloblist_t *_a = bloblist_add(dst->attachments, _ctext, csize,
522 "application/octet-stream", "PGPexch.htm.pgp");
525 if (dst->attachments == NULL)
526 dst->attachments = _a;
533 if (src->attachments) {
534 if (dst->attachments == NULL) {
535 dst->attachments = new_bloblist(NULL, 0, NULL, NULL);
536 if (dst->attachments == NULL)
540 bloblist_t *_s = src->attachments;
541 bloblist_t *_d = dst->attachments;
543 for (int n = 0; _s && _s->value; _s = _s->next) {
544 int psize = _s->size;
545 char *ptext = _s->value;
546 status = encrypt_and_sign(session, keys, ptext, psize, &ctext,
549 char *filename = NULL;
552 size_t len = strlen(_s->filename);
553 filename = calloc(1, len + 5);
554 if (filename == NULL)
557 strcpy(filename, _s->filename);
558 strcpy(filename + len, ".pgp");
561 filename = calloc(1, 20);
562 if (filename == NULL)
567 snprintf(filename, 20, "Attachment%d.pgp", n);
570 char *_ctext = malloc(csize);
574 memcpy(_ctext, ctext, csize);
576 _d = bloblist_add(_d, _ctext, csize, "application/octet-stream",
587 return PEP_STATUS_OK;
590 status = PEP_OUT_OF_MEMORY;
596 DYNAMIC_API PEP_STATUS encrypt_message(
599 stringlist_t * extra,
601 PEP_enc_format enc_format
604 PEP_STATUS status = PEP_STATUS_OK;
605 message * msg = NULL;
606 stringlist_t * keys = NULL;
611 assert(enc_format != PEP_enc_none);
613 if (!(session && src && dst && enc_format != PEP_enc_none))
614 return PEP_ILLEGAL_VALUE;
616 determine_encryption_format(src);
617 if (src->enc_format != PEP_enc_none)
618 return PEP_ILLEGAL_VALUE;
622 status = myself(session, src->from);
623 if (status != PEP_STATUS_OK)
626 keys = new_stringlist(src->from->fpr);
630 stringlist_t *_k = keys;
633 _k = stringlist_append(_k, extra);
638 bool dest_keys_found = true;
641 for (_il = src->to; _il && _il->ident; _il = _il->next) {
642 PEP_STATUS _status = update_identity(session, _il->ident);
643 if (_status != PEP_STATUS_OK) {
648 if (_il->ident->fpr && _il->ident->fpr[0]) {
649 _k = stringlist_add(_k, _il->ident->fpr);
654 dest_keys_found = false;
655 status = PEP_KEY_NOT_FOUND;
659 for (_il = src->cc; _il && _il->ident; _il = _il->next) {
660 PEP_STATUS _status = update_identity(session, _il->ident);
661 if (_status != PEP_STATUS_OK)
667 if (_il->ident->fpr && _il->ident->fpr[0]) {
668 _k = stringlist_add(_k, _il->ident->fpr);
673 dest_keys_found = false;
674 status = PEP_KEY_NOT_FOUND;
678 if (!dest_keys_found) {
679 free_stringlist(keys);
680 attach_own_key(session, src);
681 return PEP_UNENCRYPTED;
684 msg = clone_to_empty_message(src);
688 switch (enc_format) {
689 case PEP_enc_PGP_MIME:
690 status = encrypt_PGP_MIME(session, src, keys, msg);
691 if (status != PEP_STATUS_OK)
696 status = encrypt_PGP_in_pieces(session, src, keys, msg);
697 if (status != PEP_STATUS_OK)
699 attach_own_key(session, msg);
708 status = PEP_ILLEGAL_VALUE;
713 free_stringlist(keys);
715 if (msg && msg->shortmsg == NULL)
716 msg->shortmsg = strdup("pEp");
722 status = PEP_OUT_OF_MEMORY;
725 free_stringlist(keys);
731 static bool is_encrypted_attachment(const bloblist_t *blob)
737 if (blob->filename == NULL)
740 ext = strrchr(blob->filename, '.');
744 if (strcmp(blob->mime_type, "application/octet-stream")) {
745 if (strcmp(ext, ".pgp") == 0 || strcmp(ext, ".gpg") == 0 ||
746 strcmp(ext, ".asc") == 0)
749 else if (strcmp(blob->mime_type, "text/plain")) {
750 if (strcmp(ext, ".asc") == 0)
757 static bool is_encrypted_html_attachment(const bloblist_t *blob)
760 assert(blob->filename);
762 if (strncmp(blob->filename, "PGPexch.htm.", 12) == 0) {
763 if (strcmp(blob->filename + 11, ".pgp") == 0 ||
764 strcmp(blob->filename + 11, ".asc") == 0)
771 static char * without_double_ending(const char *filename)
777 ext = strrchr(filename, '.');
781 return strndup(filename, ext - filename);
784 static PEP_color decrypt_color(PEP_STATUS status)
787 case PEP_UNENCRYPTED:
789 case PEP_VERIFY_NO_KEY:
790 case PEP_VERIFIED_AND_TRUSTED:
791 return PEP_rating_unencrypted;
794 return PEP_rating_unreliable;
796 case PEP_DECRYPTED_AND_VERIFIED:
797 return PEP_rating_reliable;
799 case PEP_DECRYPT_NO_KEY:
800 return PEP_rating_have_no_key;
802 case PEP_DECRYPT_WRONG_FORMAT:
803 case PEP_CANNOT_DECRYPT_UNKNOWN:
804 return PEP_rating_cannot_decrypt;
807 return PEP_rating_undefined;
811 static PEP_color _rating(PEP_comm_type ct)
813 if (ct == PEP_ct_unknown)
814 return PEP_rating_undefined;
816 else if (ct == PEP_ct_compromized)
817 return PEP_rating_under_attack;
819 else if (ct >= PEP_ct_confirmed_enc_anon)
820 return PEP_rating_trusted_and_anonymized;
822 else if (ct >= PEP_ct_strong_encryption)
823 return PEP_rating_trusted;
825 else if (ct >= PEP_ct_strong_but_unconfirmed && ct < PEP_ct_confirmed)
826 return PEP_rating_reliable;
828 else if (ct == PEP_ct_no_encryption || ct == PEP_ct_no_encrypted_channel)
829 return PEP_rating_unencrypted;
832 return PEP_rating_unreliable;
835 static PEP_color key_color(PEP_SESSION session, const char *fpr) {
836 PEP_comm_type comm_type = PEP_ct_unknown;
841 PEP_STATUS status = get_key_rating(session, fpr, &comm_type);
842 if (status != PEP_STATUS_OK)
843 return PEP_rating_undefined;
845 return _rating(comm_type);
848 static PEP_color keylist_color(PEP_SESSION session, stringlist_t *keylist)
850 PEP_color color = PEP_rating_reliable;
852 assert(keylist && keylist->value);
853 if (keylist == NULL || keylist->value == NULL)
854 return PEP_rating_unencrypted;
857 for (_kl = keylist; _kl && _kl->value; _kl = _kl->next) {
861 color = key_color(session, _kl->value);
862 if (color == PEP_rating_under_attack)
863 return PEP_rating_under_attack;
865 if (color >= PEP_rating_reliable) {
866 status = least_trust(session, _kl->value, &ct);
867 if (status != PEP_STATUS_OK)
868 return PEP_rating_undefined;
869 if (ct == PEP_ct_unknown)
870 color = PEP_rating_unreliable;
879 static char * keylist_to_string(const stringlist_t *keylist)
882 size_t size = stringlist_length(keylist);
884 const stringlist_t *_kl;
885 for (_kl = keylist; _kl && _kl->value; _kl = _kl->next) {
886 size += strlen(_kl->value);
889 char *result = calloc(1, size);
894 for (_kl = keylist; _kl && _kl->value; _kl = _kl->next) {
895 _r = stpcpy(_r, _kl->value);
896 if (_kl->next && _kl->next->value)
897 _r = stpcpy(_r, ",");
907 static const char * color_to_string(PEP_color color)
910 case PEP_rating_cannot_decrypt:
911 return "cannot_decrypt";
912 case PEP_rating_have_no_key:
913 return "have_no_key";
914 case PEP_rating_unencrypted:
915 return "unencrypted";
916 case PEP_rating_unreliable:
918 case PEP_rating_reliable:
920 case PEP_rating_trusted:
922 case PEP_rating_trusted_and_anonymized:
923 return "trusted_and_anonymized";
924 case PEP_rating_fully_anonymous:
925 return "fully_anonymous";
926 case PEP_rating_under_attack:
927 return "unter_attack";
928 case PEP_rating_b0rken:
935 static void decorate_message(
937 stringlist_t *keylist,
943 add_opt_field(msg, "X-pEp-Version", "1.0");
944 add_opt_field(msg, "X-EncStatus", color_to_string(color));
946 char *_keylist = keylist_to_string(keylist);
947 add_opt_field(msg, "X-KeyList", _keylist);
951 DYNAMIC_API PEP_STATUS decrypt_message(
955 stringlist_t **keylist,
959 PEP_STATUS status = PEP_STATUS_OK;
960 PEP_STATUS decrypt_status = PEP_CANNOT_DECRYPT_UNKNOWN;
966 stringlist_t *_keylist = NULL;
974 if (!(session && src && dst && keylist && color))
975 return PEP_ILLEGAL_VALUE;
977 import_attached_keys(session, src);
978 PEP_cryptotech crypto = determine_encryption_format(src);
982 *color = PEP_rating_undefined;
984 switch (src->enc_format) {
986 import_attached_keys(session, src);
987 *color = PEP_rating_unencrypted;
988 return PEP_UNENCRYPTED;
990 case PEP_enc_PGP_MIME:
991 ctext = src->attachments->next->value;
992 csize = src->attachments->next->size;
994 status = cryptotech[crypto].decrypt_and_verify(session, ctext,
995 csize, &ptext, &psize, &_keylist);
996 if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
998 decrypt_status = status;
1001 case PEP_enc_pieces:
1002 ctext = src->longmsg;
1003 csize = strlen(ctext);
1005 status = cryptotech[crypto].decrypt_and_verify(session, ctext,
1006 csize, &ptext, &psize, &_keylist);
1007 if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
1009 decrypt_status = status;
1016 *color = decrypt_color(status);
1018 if (*color != PEP_rating_under_attack) {
1019 PEP_color kl_color = PEP_rating_undefined;
1022 kl_color = keylist_color(session, _keylist);
1024 if (kl_color == PEP_rating_under_attack)
1025 *color = PEP_rating_under_attack;
1027 else if (*color >= PEP_rating_reliable &&
1028 kl_color < PEP_rating_reliable)
1029 *color = PEP_rating_unreliable;
1031 else if (*color >= PEP_rating_reliable &&
1032 kl_color >= PEP_rating_trusted)
1037 switch (src->enc_format) {
1038 case PEP_enc_PGP_MIME:
1039 status = mime_decode_message(ptext, psize, &msg);
1040 if (status != PEP_STATUS_OK)
1044 case PEP_enc_pieces:
1045 msg = clone_to_empty_message(src);
1049 msg->longmsg = strdup(ptext);
1050 if (msg->longmsg == NULL)
1053 bloblist_t *_m = msg->attachments;
1055 for (_s = src->attachments; _s; _s = _s->next) {
1056 if (is_encrypted_attachment(_s)) {
1057 stringlist_t *_keylist = NULL;
1061 status = decrypt_and_verify(session, ctext, csize,
1062 &ptext, &psize, &_keylist);
1063 free_stringlist(_keylist);
1066 if (is_encrypted_html_attachment(_s)) {
1067 msg->longmsg_formatted = strdup(ptext);
1068 if (msg->longmsg_formatted == NULL)
1072 char * mime_type = "application/octet-stream";
1074 without_double_ending(_s->filename);
1075 if (filename == NULL)
1078 char *_ptext = malloc(psize);
1082 memcpy(_ptext, ptext, psize);
1084 _m = bloblist_add(_m, _ptext, psize, mime_type,
1089 if (msg->attachments == NULL)
1090 msg->attachments = _m;
1094 _m = bloblist_dup(_s);
1097 if (msg->attachments == NULL)
1098 msg->attachments = _m;
1106 // BUG: must implement more
1110 switch (src->enc_format) {
1111 case PEP_enc_PGP_MIME:
1112 case PEP_enc_pieces:
1113 status = copy_fields(msg, src);
1114 if (status != PEP_STATUS_OK)
1117 if (src->shortmsg == NULL || strcmp(src->shortmsg, "pEp") == 0)
1122 int r = seperate_short_and_long(msg->longmsg, &shortmsg,
1127 free(msg->shortmsg);
1130 msg->shortmsg = shortmsg;
1131 msg->longmsg = longmsg;
1134 msg->shortmsg = strdup(src->shortmsg);
1135 if (msg->shortmsg == NULL)
1141 // BUG: must implement more
1145 import_attached_keys(session, msg);
1149 decorate_message(msg, _keylist, *color);
1152 *keylist = _keylist;
1154 return PEP_STATUS_OK;
1157 status = PEP_OUT_OF_MEMORY;
1161 free_stringlist(_keylist);
1166 static PEP_comm_type _get_comm_type(
1167 PEP_SESSION session,
1168 PEP_comm_type max_comm_type,
1172 PEP_STATUS status = update_identity(session, ident);
1174 if (max_comm_type == PEP_ct_compromized)
1175 return PEP_ct_compromized;
1177 if (status == PEP_STATUS_OK) {
1178 if (ident->comm_type == PEP_ct_compromized)
1179 return PEP_ct_compromized;
1181 return MIN(max_comm_type, ident->comm_type);
1184 return PEP_ct_unknown;
1188 DYNAMIC_API PEP_STATUS outgoing_message_color(
1189 PEP_SESSION session,
1194 PEP_STATUS status = PEP_STATUS_OK;
1195 PEP_comm_type max_comm_type = PEP_ct_pEp;
1196 bool comm_type_determined = false;
1202 assert(msg->dir == PEP_dir_outgoing);
1205 if (!(session && msg && color))
1206 return PEP_ILLEGAL_VALUE;
1208 if (msg->from == NULL || msg->dir != PEP_dir_outgoing)
1209 return PEP_ILLEGAL_VALUE;
1211 *color = PEP_rating_undefined;
1213 status = myself(session, msg->from);
1214 if (status != PEP_STATUS_OK)
1217 for (il = msg->to; il != NULL; il = il->next) {
1219 update_identity(session, il->ident);
1220 max_comm_type = _get_comm_type(session, max_comm_type,
1222 comm_type_determined = true;
1226 for (il = msg->cc; il != NULL; il = il->next) {
1228 update_identity(session, il->ident);
1229 max_comm_type = _get_comm_type(session, max_comm_type,
1231 comm_type_determined = true;
1235 if (comm_type_determined == false)
1236 *color = PEP_rating_undefined;
1238 *color = MAX(_rating(max_comm_type), PEP_rating_unencrypted);
1240 return PEP_STATUS_OK;
1243 DYNAMIC_API PEP_STATUS identity_color(
1244 PEP_SESSION session,
1245 pEp_identity *ident,
1249 PEP_STATUS status = PEP_STATUS_OK;
1255 if (!(session && ident && color))
1256 return PEP_ILLEGAL_VALUE;
1259 status = myself(session, ident);
1261 status = update_identity(session, ident);
1263 if (status == PEP_STATUS_OK)
1264 *color = _rating(ident->comm_type);