p≡p engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1310 lines
33 KiB

2 years ago
6 years ago
6 years ago
4 years ago
4 years ago
4 years ago
4 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
4 years ago
6 years ago
4 years ago
6 years ago
4 years ago
6 years ago
4 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
3 years ago
3 years ago
6 years ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
  1. /**
  2. * @file map_asn1.c
  3. * @brief map asn1 to pEp structs and back
  4. * @license GNU General Public License 3.0 - see LICENSE.txt
  5. */
  6. #include "pEp_internal.h"
  7. #include "map_asn1.h"
  8. #include "message_codec.h"
  9. /* Expand to a statement checking that the given expression evaluates to a
  10. non-NULL result, first using an assert and then an explicit check in C. If
  11. the check fails branch to the given label. */
  12. #define CHECK_NON_NULLITY_OR_GOTO(expr, label) \
  13. do \
  14. { \
  15. assert(expr); \
  16. if (! (expr)) \
  17. goto label; \
  18. } \
  19. while (false)
  20. /* Same as CHECK_NON_NULLITY_OR_GOTO, but in case of failure return the given
  21. expression (evaluated only once after the check) instead of branching. */
  22. #define CHECK_NON_NULLITY_OR_RETURN(expr, result) \
  23. do \
  24. { \
  25. assert(expr); \
  26. if (! (expr)) \
  27. return (result); \
  28. } \
  29. while (false)
  30. /* Expand to a statement which:
  31. - reallocates a new heap buffer of the given size, (as if with realloc),
  32. updating the given pointer lvalue;
  33. - jumps to the given label in case of allocation failure.
  34. The expansion may evaluate parameters multiple times. */
  35. #define ALLOCATE_OR_GOTO(lvalue_pointer, size, label) \
  36. do \
  37. { \
  38. /* Free any previous buffer, and reset to NULL. This is necessary \
  39. for correct deallocation in case of allocation errors later. */ \
  40. if ((lvalue_pointer) != NULL) { \
  41. free (lvalue_pointer); \
  42. lvalue_pointer = NULL; \
  43. } \
  44. (lvalue_pointer) = calloc (1, (size)); \
  45. if ((lvalue_pointer) == NULL) \
  46. goto label; \
  47. } \
  48. while (false)
  49. PIdentity_t *PIdentity_from_Struct(
  50. const pEp_identity *ident,
  51. PIdentity_t *result
  52. )
  53. {
  54. bool allocated = !result;
  55. CHECK_NON_NULLITY_OR_RETURN (ident, NULL);
  56. if (allocated)
  57. result = (PIdentity_t *) calloc(1, sizeof(PIdentity_t));
  58. CHECK_NON_NULLITY_OR_RETURN (result, NULL);
  59. if (ident->address) {
  60. int r = OCTET_STRING_fromBuf(&result->address, ident->address, -1);
  61. if (r)
  62. goto error;
  63. }
  64. if (! EMPTYSTR (ident->fpr)) {
  65. ALLOCATE_OR_GOTO (result->fpr, sizeof (Hash_t), error);
  66. if (OCTET_STRING_fromString(result->fpr, ident->fpr))
  67. goto error;
  68. }
  69. if (ident->user_id) {
  70. int r = OCTET_STRING_fromBuf(&result->user_id, ident->user_id, -1);
  71. if (r)
  72. goto error;
  73. }
  74. if (! EMPTYSTR (ident->username)) {
  75. ALLOCATE_OR_GOTO (result->username, sizeof (PString_t), error);
  76. int r = OCTET_STRING_fromBuf(result->username, ident->username, -1);
  77. if (r)
  78. goto error;
  79. }
  80. if (ident->comm_type != PEP_ct_unknown) {
  81. result->comm_type = ident->comm_type;
  82. }
  83. ALLOCATE_OR_GOTO (result->lang, sizeof (ISO639_1_t), error);
  84. if (! EMPTYSTR (ident->lang)) {
  85. int r = OCTET_STRING_fromBuf(result->lang, ident->lang, 2);
  86. assert(r == 0);
  87. if(r != 0)
  88. goto error;
  89. }
  90. else {
  91. int r = OCTET_STRING_fromBuf(result->lang, "en", 2);
  92. assert(r == 0);
  93. if(r != 0)
  94. goto error;
  95. }
  96. return result;
  97. error:
  98. if (allocated)
  99. ASN_STRUCT_FREE(asn_DEF_PIdentity, result);
  100. return NULL;
  101. }
  102. pEp_identity *PIdentity_to_Struct(PIdentity_t *ident, pEp_identity *result)
  103. {
  104. bool allocated = !result;
  105. assert(ident);
  106. if (!ident)
  107. return NULL;
  108. if (allocated)
  109. result = new_identity(NULL, NULL, NULL, NULL);
  110. CHECK_NON_NULLITY_OR_RETURN (result, NULL);
  111. result->address = strndup((char *) ident->address.buf,
  112. ident->address.size);
  113. CHECK_NON_NULLITY_OR_GOTO (result->address, enomem);
  114. if (ident->fpr && ! EMPTYSTR (ident->fpr->buf)) {
  115. result->fpr = strndup((char *) ident->fpr->buf, ident->fpr->size);
  116. CHECK_NON_NULLITY_OR_GOTO (result->fpr, enomem);
  117. }
  118. result->user_id = strndup((char *) ident->user_id.buf,
  119. ident->user_id.size);
  120. CHECK_NON_NULLITY_OR_GOTO (result->user_id, enomem);
  121. if (ident->username && ! EMPTYSTR (ident->username->buf)) {
  122. result->username = strndup((char *) ident->username->buf,
  123. ident->username->size);
  124. CHECK_NON_NULLITY_OR_GOTO (result->username, enomem);
  125. }
  126. result->comm_type = (PEP_comm_type) ident->comm_type;
  127. if (ident->lang && ident->lang->size == 2) {
  128. result->lang[0] = ident->lang->buf[0];
  129. result->lang[1] = ident->lang->buf[1];
  130. result->lang[2] = 0;
  131. }
  132. return result;
  133. enomem:
  134. if (allocated)
  135. free_identity(result);
  136. return NULL;
  137. }
  138. PIdentityList_t *PIdentityList_from_identity_list(
  139. const identity_list *list,
  140. PIdentityList_t *result
  141. )
  142. {
  143. bool allocated = !result;
  144. if (!(list && list->ident))
  145. return NULL;
  146. if (allocated) {
  147. result = (PIdentityList_t *) calloc(1, sizeof(PIdentityList_t));
  148. assert(result);
  149. if (!result)
  150. return NULL;
  151. }
  152. else {
  153. asn_sequence_empty(result);
  154. }
  155. for (const identity_list *l = list; l && l->ident; l=l->next) {
  156. PIdentity_t *ident = PIdentity_from_Struct(l->ident, NULL);
  157. if (ASN_SEQUENCE_ADD(&result->list, ident)) {
  158. ASN_STRUCT_FREE(asn_DEF_PIdentity, ident);
  159. goto enomem;
  160. }
  161. }
  162. return result;
  163. enomem:
  164. if (allocated)
  165. ASN_STRUCT_FREE(asn_DEF_PIdentityList, result);
  166. return NULL;
  167. }
  168. identity_list *PIdentityList_to_identity_list(PIdentityList_t *list, identity_list *result)
  169. {
  170. bool allocated = !result;
  171. assert(list);
  172. if (!list)
  173. return NULL;
  174. if (allocated)
  175. result = new_identity_list(NULL);
  176. if (!result)
  177. return NULL;
  178. identity_list *r = result;
  179. for (int i=0; i<list->list.count; i++) {
  180. pEp_identity *ident = PIdentity_to_Struct(list->list.array[i], NULL);
  181. r = identity_list_add(r, ident);
  182. if (!r)
  183. goto enomem;
  184. }
  185. return result;
  186. enomem:
  187. if (allocated)
  188. free_identity_list(result);
  189. return NULL;
  190. }
  191. Identity_t *Identity_from_Struct(
  192. const pEp_identity *ident,
  193. Identity_t *result
  194. )
  195. {
  196. bool allocated = !result;
  197. assert(ident);
  198. if (!ident)
  199. return NULL;
  200. if (allocated)
  201. result = (Identity_t *) calloc(1, sizeof(Identity_t));
  202. assert(result);
  203. if (!result)
  204. return NULL;
  205. if (ident->address) {
  206. int r = OCTET_STRING_fromBuf(&result->address, ident->address, -1);
  207. if (r)
  208. goto enomem;
  209. }
  210. if (ident->fpr) {
  211. if (OCTET_STRING_fromString(&result->fpr, ident->fpr))
  212. goto enomem;
  213. }
  214. if (ident->user_id) {
  215. int r = OCTET_STRING_fromBuf(&result->user_id, ident->user_id, -1);
  216. if (r)
  217. goto enomem;
  218. }
  219. if (ident->username) {
  220. int r = OCTET_STRING_fromBuf(&result->username, ident->username, -1);
  221. if (r)
  222. goto enomem;
  223. }
  224. if (ident->comm_type != PEP_ct_unknown) {
  225. result->comm_type = ident->comm_type;
  226. }
  227. if (! EMPTYSTR(ident->lang)) {
  228. int r = OCTET_STRING_fromBuf(&result->lang, ident->lang, 2);
  229. assert(r == 0);
  230. if(r != 0)
  231. goto enomem;
  232. }
  233. else {
  234. int r = OCTET_STRING_fromBuf(&result->lang, "en", 2);
  235. assert(r == 0);
  236. if(r != 0)
  237. goto enomem;
  238. }
  239. return result;
  240. enomem:
  241. if (allocated)
  242. ASN_STRUCT_FREE(asn_DEF_Identity, result);
  243. return NULL;
  244. }
  245. pEp_identity *Identity_to_Struct(Identity_t *ident, pEp_identity *result)
  246. {
  247. bool allocated = !result;
  248. assert(ident);
  249. if (!ident)
  250. return NULL;
  251. if (allocated)
  252. result = new_identity(NULL, NULL, NULL, NULL);
  253. if (!result)
  254. return NULL;
  255. result->address = strndup((char *) ident->address.buf,
  256. ident->address.size);
  257. assert(result->address);
  258. if (!result->address)
  259. goto enomem;
  260. result->fpr = strndup((char *) ident->fpr.buf, ident->fpr.size);
  261. assert(result->fpr);
  262. if (!result->fpr)
  263. goto enomem;
  264. result->user_id = strndup((char *) ident->user_id.buf,
  265. ident->user_id.size);
  266. assert(result->user_id);
  267. if (!result->user_id)
  268. goto enomem;
  269. result->username = strndup((char *) ident->username.buf,
  270. ident->username.size);
  271. assert(result->username);
  272. if (!result->username)
  273. goto enomem;
  274. result->comm_type = (PEP_comm_type) ident->comm_type;
  275. if (ident->lang.size == 2) {
  276. result->lang[0] = ident->lang.buf[0];
  277. result->lang[1] = ident->lang.buf[1];
  278. result->lang[2] = 0;
  279. }
  280. return result;
  281. enomem:
  282. if (allocated)
  283. free_identity(result);
  284. return NULL;
  285. }
  286. IdentityList_t *IdentityList_from_identity_list(
  287. const identity_list *list,
  288. IdentityList_t *result
  289. )
  290. {
  291. bool allocated = !result;
  292. if (!(list && list->ident))
  293. return NULL;
  294. if (allocated) {
  295. result = (IdentityList_t *) calloc(1, sizeof(IdentityList_t));
  296. assert(result);
  297. if (!result)
  298. return NULL;
  299. }
  300. else {
  301. asn_sequence_empty(result);
  302. }
  303. for (const identity_list *l = list; l && l->ident; l=l->next) {
  304. Identity_t *ident = Identity_from_Struct(l->ident, NULL);
  305. if (ASN_SEQUENCE_ADD(&result->list, ident)) {
  306. ASN_STRUCT_FREE(asn_DEF_Identity, ident);
  307. goto enomem;
  308. }
  309. }
  310. return result;
  311. enomem:
  312. if (allocated)
  313. ASN_STRUCT_FREE(asn_DEF_IdentityList, result);
  314. return NULL;
  315. }
  316. identity_list *IdentityList_to_identity_list(IdentityList_t *list, identity_list *result)
  317. {
  318. bool allocated = !result;
  319. assert(list);
  320. if (!list)
  321. return NULL;
  322. if (allocated)
  323. result = new_identity_list(NULL);
  324. if (!result)
  325. return NULL;
  326. identity_list *r = result;
  327. for (int i=0; i<list->list.count; i++) {
  328. pEp_identity *ident = Identity_to_Struct(list->list.array[i], NULL);
  329. r = identity_list_add(r, ident);
  330. if (!r)
  331. goto enomem;
  332. }
  333. return result;
  334. enomem:
  335. if (allocated)
  336. free_identity_list(result);
  337. return NULL;
  338. }
  339. PStringPair_t *PStringPair_from_Struct(
  340. const stringpair_t *value,
  341. PStringPair_t *result
  342. )
  343. {
  344. bool allocated = !result;
  345. assert(value);
  346. if (!value)
  347. return NULL;
  348. if (allocated)
  349. result = (PStringPair_t *) calloc(1, sizeof(PStringPair_t));
  350. assert(result);
  351. if (!result)
  352. return NULL;
  353. if (value->key) {
  354. int r = OCTET_STRING_fromBuf(&result->key, value->key, -1);
  355. if (r)
  356. goto enomem;
  357. }
  358. if (value->value) {
  359. int r = OCTET_STRING_fromBuf(&result->value, value->value, -1);
  360. if (r)
  361. goto enomem;
  362. }
  363. return result;
  364. enomem:
  365. if (allocated)
  366. ASN_STRUCT_FREE(asn_DEF_PStringPair, result);
  367. return NULL;
  368. }
  369. stringpair_t *PStringPair_to_Struct(PStringPair_t *value)
  370. {
  371. assert(value);
  372. if (!value)
  373. return NULL;
  374. stringpair_t *result = (stringpair_t *) calloc(1, sizeof(stringpair_t));
  375. assert(result);
  376. if (!result)
  377. goto enomem;
  378. result->key = strndup((char *) value->key.buf,
  379. value->key.size);
  380. assert(result->key);
  381. if (!result->key)
  382. goto enomem;
  383. result->value = strndup((char *) value->value.buf,
  384. value->value.size);
  385. assert(result->value);
  386. if (!result->value)
  387. goto enomem;
  388. return result;
  389. enomem:
  390. free_stringpair(result);
  391. return NULL;
  392. }
  393. PStringPairList_t *PStringPairList_from_stringpair_list(
  394. const stringpair_list_t *list,
  395. PStringPairList_t *result
  396. )
  397. {
  398. bool allocated = !result;
  399. assert(list);
  400. if (!(list && list->value))
  401. return NULL;
  402. if (allocated) {
  403. result = (PStringPairList_t *) calloc(1, sizeof(PStringPairList_t));
  404. assert(result);
  405. if (!result)
  406. return NULL;
  407. }
  408. else {
  409. asn_sequence_empty(result);
  410. }
  411. for (const stringpair_list_t *l = list; l && l->value; l=l->next) {
  412. PStringPair_t *value = PStringPair_from_Struct(l->value, NULL);
  413. if (ASN_SEQUENCE_ADD(&result->list, value)) {
  414. ASN_STRUCT_FREE(asn_DEF_PStringPair, value);
  415. goto enomem;
  416. }
  417. }
  418. return result;
  419. enomem:
  420. if (allocated)
  421. ASN_STRUCT_FREE(asn_DEF_PStringPairList, result);
  422. return NULL;
  423. }
  424. stringpair_list_t *PStringPairList_to_stringpair_list(
  425. PStringPairList_t *list,
  426. stringpair_list_t *result
  427. )
  428. {
  429. bool allocated = !result;
  430. assert(list);
  431. if (!list)
  432. return NULL;
  433. if (allocated)
  434. result = new_stringpair_list(NULL);
  435. if (!result)
  436. return NULL;
  437. stringpair_list_t *r = result;
  438. for (int i=0; i<list->list.count; i++) {
  439. stringpair_t *value = PStringPair_to_Struct(list->list.array[i]);
  440. r = stringpair_list_add(r, value);
  441. if (!r)
  442. goto enomem;
  443. }
  444. return result;
  445. enomem:
  446. if (allocated)
  447. free_stringpair_list(result);
  448. return NULL;
  449. }
  450. PStringList_t *PStringList_from_stringlist(
  451. const stringlist_t *list,
  452. PStringList_t *result
  453. )
  454. {
  455. bool allocated = !result;
  456. assert(list);
  457. if (!(list && list->value))
  458. return NULL;
  459. if (allocated) {
  460. result = (PStringList_t *) calloc(1, sizeof(PStringList_t));
  461. assert(result);
  462. if (!result)
  463. return NULL;
  464. }
  465. else {
  466. asn_sequence_empty(result);
  467. }
  468. for (const stringlist_t *l = list; l && l->value; l=l->next) {
  469. PString_t *element = (PString_t *) calloc(1, sizeof(PString_t));
  470. assert(element);
  471. if (!element)
  472. goto enomem;
  473. int r = OCTET_STRING_fromBuf(element, l->value, -1);
  474. if (r)
  475. goto enomem;
  476. if (ASN_SEQUENCE_ADD(&result->list, element)) {
  477. ASN_STRUCT_FREE(asn_DEF_PString, element);
  478. goto enomem;
  479. }
  480. }
  481. return result;
  482. enomem:
  483. if (allocated)
  484. ASN_STRUCT_FREE(asn_DEF_PStringList, result);
  485. return NULL;
  486. }
  487. stringlist_t *PStringList_to_stringlist(PStringList_t *list)
  488. {
  489. assert(list);
  490. if (!list)
  491. return NULL;
  492. stringlist_t *result = (stringlist_t *) calloc(1, sizeof(stringlist_t));
  493. assert(result);
  494. if (!result)
  495. goto enomem;
  496. stringlist_t *r = result;
  497. for (int i=0; i<list->list.count; i++) {
  498. char *s = strndup((char *) list->list.array[i]->buf,
  499. list->list.array[i]->size);
  500. assert(s);
  501. if (!s)
  502. goto enomem;
  503. r->value = s;
  504. if (i < list->list.count-1) {
  505. r->next = (stringlist_t *) calloc(1, sizeof(stringlist_t));
  506. assert(r->next);
  507. if (!r->next)
  508. goto enomem;
  509. r = r->next;
  510. }
  511. }
  512. return result;
  513. enomem:
  514. free_stringlist(result);
  515. return NULL;
  516. }
  517. PBlobList_t *PBlobList_from_bloblist(
  518. bloblist_t *list,
  519. PBlobList_t *result,
  520. bool copy,
  521. size_t max_blob_size
  522. )
  523. {
  524. bool allocated = !result;
  525. if (!max_blob_size)
  526. max_blob_size = SIZE_MAX;
  527. assert(list);
  528. if (!(list && list->value))
  529. return NULL;
  530. if (allocated) {
  531. result = (PBlobList_t *) calloc(1, sizeof(PBlobList_t));
  532. assert(result);
  533. if (!result)
  534. return NULL;
  535. }
  536. else {
  537. asn_sequence_empty(result);
  538. }
  539. size_t rest_blob_size = max_blob_size;
  540. for (bloblist_t *l = list; l && l->value; l=l->next) {
  541. PBlob_t *element = (PBlob_t *) calloc(1, sizeof(PBlob_t));
  542. assert(element);
  543. if (!element)
  544. goto enomem;
  545. int r = 0;
  546. if (l->size > rest_blob_size)
  547. goto enomem;
  548. rest_blob_size -= l->size;
  549. if (copy) {
  550. r = OCTET_STRING_fromBuf(&element->value, l->value, l->size);
  551. if (r)
  552. goto enomem;
  553. }
  554. else /* move */ {
  555. #if defined(__CHAR_BIT__) && __CHAR_BIT__ == 8
  556. element->value.buf = (uint8_t *) l->value;
  557. #else
  558. // FIXME: this is problematic on platforms with bytes != octets
  559. // we want this warning
  560. element->value.buf = l->value;
  561. #endif
  562. l->value = NULL;
  563. element->value.size = l->size;
  564. l->size = 0;
  565. }
  566. if (!EMPTYSTR(l->mime_type)) {
  567. PString_t *_mime_type = (PString_t *) calloc(1, sizeof(PString_t));
  568. assert(_mime_type);
  569. if (!_mime_type)
  570. goto enomem;
  571. r = OCTET_STRING_fromBuf(_mime_type, l->mime_type, -1);
  572. if (r)
  573. goto enomem;
  574. element->mime_type = _mime_type;
  575. }
  576. if (!EMPTYSTR(l->filename)) {
  577. PString_t *_filename = (PString_t *) calloc(1, sizeof(PString_t));
  578. assert(_filename);
  579. if (!_filename)
  580. goto enomem;
  581. r = OCTET_STRING_fromBuf(_filename, l->filename, -1);
  582. if (r)
  583. goto enomem;
  584. element->filename = _filename;
  585. }
  586. switch (l->disposition) {
  587. case PEP_CONTENT_DISP_ATTACHMENT:
  588. element->disposition = ContentDisposition_attachment;
  589. break;
  590. case PEP_CONTENT_DISP_INLINE:
  591. element->disposition = ContentDisposition_inline;
  592. break;
  593. case PEP_CONTENT_DISP_OTHER:
  594. element->disposition = ContentDisposition_other;
  595. break;
  596. default:
  597. assert(0); // should not happen; use default
  598. element->disposition = ContentDisposition_attachment;
  599. }
  600. if (ASN_SEQUENCE_ADD(&result->list, element)) {
  601. ASN_STRUCT_FREE(asn_DEF_PBlob, element);
  602. goto enomem;
  603. }
  604. }
  605. return result;
  606. enomem:
  607. if (allocated)
  608. ASN_STRUCT_FREE(asn_DEF_PBlobList, result);
  609. return NULL;
  610. }
  611. bloblist_t *PBlobList_to_bloblist(
  612. PBlobList_t *list,
  613. bloblist_t *result,
  614. bool copy,
  615. size_t max_blob_size
  616. )
  617. {
  618. bool allocated = !result;
  619. if (!max_blob_size)
  620. max_blob_size = SIZE_MAX;
  621. assert(list);
  622. if (!list)
  623. return NULL;
  624. if (allocated)
  625. result = new_bloblist(NULL, 0, NULL, NULL);
  626. if (!result)
  627. return NULL;
  628. size_t rest_blob_size = max_blob_size;
  629. bloblist_t *r = result;
  630. for (int i=0; i<list->list.count; i++) {
  631. // this should not happen
  632. assert(list->list.array[i]);
  633. if (!list->list.array[i])
  634. goto enomem;
  635. if (list->list.array[i]->value.size > rest_blob_size)
  636. goto enomem;
  637. rest_blob_size -= list->list.array[i]->value.size;
  638. char *_mime_type = NULL;
  639. if (list->list.array[i]->mime_type) {
  640. _mime_type = strndup((char *) list->list.array[i]->mime_type->buf,
  641. list->list.array[i]->mime_type->size);
  642. assert(_mime_type);
  643. if (!_mime_type)
  644. goto enomem;
  645. }
  646. char *_filename = NULL;
  647. if (list->list.array[i]->filename) {
  648. _filename = strndup((char *) list->list.array[i]->filename->buf,
  649. list->list.array[i]->filename->size);
  650. assert(_filename);
  651. if (!_filename)
  652. goto enomem;
  653. }
  654. #if defined(__CHAR_BIT__) && __CHAR_BIT__ == 8
  655. char *_data = (char *) list->list.array[i]->value.buf;
  656. #else
  657. // FIXME: this is problematic on platforms with bytes != octets
  658. // we want this warning
  659. char *_data = list->list.array[i]->value.buf;
  660. #endif
  661. if (copy) {
  662. _data = strndup(_data, list->list.array[i]->value.size);
  663. assert(_data);
  664. if (!_data)
  665. goto enomem;
  666. }
  667. // bloblist_add() has move semantics
  668. r = bloblist_add(r, _data, list->list.array[i]->value.size, _mime_type,
  669. _filename);
  670. if (!copy) {
  671. list->list.array[i]->value.buf = NULL;
  672. list->list.array[i]->value.size = 0;
  673. }
  674. if (!r)
  675. goto enomem;
  676. switch (list->list.array[i]->disposition) {
  677. case ContentDisposition_attachment:
  678. r->disposition = PEP_CONTENT_DISP_ATTACHMENT;
  679. break;
  680. case ContentDisposition_inline:
  681. r->disposition = PEP_CONTENT_DISP_INLINE;
  682. break;
  683. case ContentDisposition_other:
  684. r->disposition = PEP_CONTENT_DISP_OTHER;
  685. break;
  686. default:
  687. assert(0); // should not happen; use default
  688. r->disposition = PEP_CONTENT_DISP_ATTACHMENT;
  689. }
  690. }
  691. return result;
  692. enomem:
  693. if (allocated)
  694. free_bloblist(result);
  695. return NULL;
  696. }
  697. ASN1Message_t *ASN1Message_from_message(
  698. message *msg,
  699. ASN1Message_t *result,
  700. bool copy,
  701. size_t max_blob_size
  702. )
  703. {
  704. bool allocated = !result;
  705. if (!max_blob_size)
  706. max_blob_size = SIZE_MAX;
  707. assert(msg);
  708. if (!msg)
  709. return NULL;
  710. if (allocated) {
  711. result = (ASN1Message_t *) calloc(1, sizeof(ASN1Message_t));
  712. assert(result);
  713. if (!result)
  714. return NULL;
  715. }
  716. else {
  717. asn_sequence_empty(result);
  718. }
  719. // direction will be skipped on the line
  720. if (!EMPTYSTR(msg->id)) {
  721. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  722. assert(str);
  723. if (!str)
  724. goto enomem;
  725. int r = OCTET_STRING_fromBuf(str, msg->id, -1);
  726. if (r)
  727. goto enomem;
  728. result->id = str;
  729. }
  730. if (msg->sent) {
  731. GeneralizedTime_t *ts = asn_time2GT(NULL, msg->sent, 1);
  732. if (!ts)
  733. goto enomem;
  734. result->sent = ts;
  735. }
  736. if (msg->recv) {
  737. GeneralizedTime_t *ts = asn_time2GT(NULL, msg->recv, 1);
  738. if (!ts)
  739. goto enomem;
  740. result->recv = ts;
  741. }
  742. if (!msg->from) // from is not optional
  743. goto enomem;
  744. PIdentity_from_Struct(msg->from, &result->from);
  745. if (msg->to && msg->to->ident) {
  746. PIdentityList_t *l = PIdentityList_from_identity_list(msg->to, NULL);
  747. if (!l)
  748. goto enomem;
  749. result->to = l;
  750. }
  751. if (msg->cc && msg->cc->ident) {
  752. PIdentityList_t *l = PIdentityList_from_identity_list(msg->cc, NULL);
  753. if (!l)
  754. goto enomem;
  755. result->cc = l;
  756. }
  757. if (msg->bcc && msg->bcc->ident) {
  758. PIdentityList_t *l = PIdentityList_from_identity_list(msg->bcc, NULL);
  759. if (!l)
  760. goto enomem;
  761. result->bcc = l;
  762. }
  763. if (msg->recv_by) {
  764. PIdentity_t *i = PIdentity_from_Struct(msg->recv_by, NULL);
  765. if (!i)
  766. goto enomem;
  767. result->recv_by = i;
  768. }
  769. if (msg->reply_to && msg->reply_to->ident) {
  770. PIdentityList_t *l = PIdentityList_from_identity_list(msg->reply_to, NULL);
  771. if (!l)
  772. goto enomem;
  773. result->reply_to = l;
  774. }
  775. if (msg->in_reply_to && msg->in_reply_to->value) {
  776. PStringList_t *l = PStringList_from_stringlist(msg->in_reply_to, NULL);
  777. if (!l)
  778. goto enomem;
  779. result->in_reply_to = l;
  780. }
  781. if (msg->references && msg->references->value) {
  782. PStringList_t *l = PStringList_from_stringlist(msg->references, NULL);
  783. if (!l)
  784. goto enomem;
  785. result->references = l;
  786. }
  787. if (msg->keywords && msg->keywords->value) {
  788. PStringList_t *l = PStringList_from_stringlist(msg->keywords, NULL);
  789. if (!l)
  790. goto enomem;
  791. result->keywords = l;
  792. }
  793. if (!EMPTYSTR(msg->comments)) {
  794. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  795. assert(str);
  796. if (!str)
  797. goto enomem;
  798. int r = OCTET_STRING_fromBuf(str, msg->comments, -1);
  799. if (r)
  800. goto enomem;
  801. result->comments = str;
  802. }
  803. if (msg->opt_fields && msg->opt_fields->value) {
  804. PStringPairList_t *l = PStringPairList_from_stringpair_list(msg->opt_fields, NULL);
  805. if (!l)
  806. goto enomem;
  807. result->opt_fields = l;
  808. }
  809. if (!EMPTYSTR(msg->_sender_fpr)) {
  810. Hash_t *str = (Hash_t *) calloc(1, sizeof(Hash_t));
  811. assert(str);
  812. if (!str)
  813. goto enomem;
  814. int r = OCTET_STRING_fromBuf(str, msg->_sender_fpr, -1);
  815. if (r)
  816. goto enomem;
  817. result->sender_fpr = str;
  818. }
  819. if (!EMPTYSTR(msg->shortmsg)) {
  820. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  821. assert(str);
  822. if (!str)
  823. goto enomem;
  824. int r = OCTET_STRING_fromBuf(str, msg->shortmsg, -1);
  825. if (r)
  826. goto enomem;
  827. result->shortmsg = str;
  828. }
  829. size_t rest_blob_size = max_blob_size;
  830. if (!EMPTYSTR(msg->longmsg)) {
  831. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  832. assert(str);
  833. if (!str)
  834. goto enomem;
  835. if (copy) {
  836. int r = OCTET_STRING_fromBuf(str, msg->longmsg, -1);
  837. if (r)
  838. goto enomem;
  839. if (str->size > rest_blob_size)
  840. goto enomem;
  841. }
  842. else /* move */ {
  843. str->size = strlen(msg->longmsg);
  844. if (str->size > rest_blob_size)
  845. goto enomem;
  846. str->buf = (uint8_t *) msg->longmsg;
  847. msg->longmsg = NULL;
  848. }
  849. rest_blob_size -= str->size;
  850. result->longmsg = str;
  851. }
  852. if (!EMPTYSTR(msg->longmsg_formatted)) {
  853. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  854. assert(str);
  855. if (!str)
  856. goto enomem;
  857. if (copy) {
  858. int r = OCTET_STRING_fromBuf(str, msg->longmsg_formatted, -1);
  859. if (r)
  860. goto enomem;
  861. if (str->size > rest_blob_size)
  862. goto enomem;
  863. }
  864. else /* move */ {
  865. str->size = strlen(msg->longmsg_formatted);
  866. if (str->size > rest_blob_size)
  867. goto enomem;
  868. str->buf = (uint8_t *) msg->longmsg_formatted;
  869. msg->longmsg_formatted = NULL;
  870. }
  871. rest_blob_size -= str->size;
  872. result->longmsg_formatted = str;
  873. }
  874. if (msg->attachments && msg->attachments->value) {
  875. PBlobList_t *bl = PBlobList_from_bloblist(msg->attachments, NULL, copy,
  876. rest_blob_size);
  877. if (!bl)
  878. goto enomem;
  879. result->attachments = bl;
  880. }
  881. return result;
  882. enomem:
  883. if (allocated)
  884. free_ASN1Message(result);
  885. return NULL;
  886. }
  887. message *ASN1Message_to_message(
  888. ASN1Message_t *msg,
  889. message *result,
  890. bool copy,
  891. size_t max_blob_size
  892. )
  893. {
  894. bool allocated = !result;
  895. if (!max_blob_size)
  896. max_blob_size = SIZE_MAX;
  897. assert(msg);
  898. if (!msg)
  899. return NULL;
  900. if (allocated) {
  901. result = new_message(PEP_dir_incoming);
  902. if (!result)
  903. goto enomem;
  904. }
  905. if (msg->direction) {
  906. switch (*msg->direction) {
  907. case MessageDirection_incoming:
  908. result->dir = PEP_dir_incoming;
  909. break;
  910. case MessageDirection_outgoing:
  911. result->dir = PEP_dir_outgoing;
  912. break;
  913. default:
  914. assert(0);
  915. }
  916. }
  917. if (msg->id) {
  918. result->id = strndup((char *) msg->id->buf, msg->id->size);
  919. assert(result->id);
  920. if (!result->id)
  921. goto enomem;
  922. }
  923. if (msg->sent) {
  924. timestamp *_sent = new_timestamp(0);
  925. if (!_sent)
  926. goto enomem;
  927. if (asn_GT2time(msg->sent, _sent, 1) == -1)
  928. goto enomem;
  929. result->sent = _sent;
  930. }
  931. if (msg->recv) {
  932. timestamp *_recv = new_timestamp(0);
  933. if (!_recv)
  934. goto enomem;
  935. if (asn_GT2time(msg->recv, _recv, 1) == -1)
  936. goto enomem;
  937. result->recv = _recv;
  938. }
  939. // from is mandatory
  940. result->from = PIdentity_to_Struct(&msg->from, NULL);
  941. if (!result->from)
  942. goto enomem;
  943. if (msg->to) {
  944. identity_list *il = PIdentityList_to_identity_list(msg->to, NULL);
  945. if (!il)
  946. goto enomem;
  947. result->to = il;
  948. }
  949. if (msg->cc) {
  950. identity_list *il = PIdentityList_to_identity_list(msg->cc, NULL);
  951. if (!il)
  952. goto enomem;
  953. result->cc = il;
  954. }
  955. if (msg->bcc) {
  956. identity_list *il = PIdentityList_to_identity_list(msg->bcc, NULL);
  957. if (!il)
  958. goto enomem;
  959. result->bcc = il;
  960. }
  961. if (msg->recv_by) {
  962. pEp_identity *i = PIdentity_to_Struct(msg->recv_by, NULL);
  963. if (!i)
  964. goto enomem;
  965. result->recv_by = i;
  966. }
  967. if (msg->reply_to) {
  968. identity_list *il = PIdentityList_to_identity_list(msg->reply_to, NULL);
  969. if (!il)
  970. goto enomem;
  971. result->reply_to = il;
  972. }
  973. if (msg->in_reply_to) {
  974. stringlist_t *l = PStringList_to_stringlist(msg->in_reply_to);
  975. if (!l)
  976. goto enomem;
  977. result->in_reply_to = l;
  978. }
  979. if (msg->references) {
  980. stringlist_t *l = PStringList_to_stringlist(msg->references);
  981. if (!l)
  982. goto enomem;
  983. result->references = l;
  984. }
  985. if (msg->keywords) {
  986. stringlist_t *l = PStringList_to_stringlist(msg->keywords);
  987. if (!l)
  988. goto enomem;
  989. result->keywords = l;
  990. }
  991. if (msg->comments) {
  992. char *s = strndup((char *) msg->comments->buf, msg->comments->size);
  993. assert(s);
  994. if (!s)
  995. goto enomem;
  996. result->comments = s;
  997. }
  998. if (msg->opt_fields) {
  999. stringpair_list_t *l =
  1000. PStringPairList_to_stringpair_list(msg->opt_fields, NULL);
  1001. if (!l)
  1002. goto enomem;
  1003. result->opt_fields = l;
  1004. }
  1005. if (msg->sender_fpr) {
  1006. char *_sender_fpr = strndup((char *) msg->sender_fpr->buf,
  1007. msg->sender_fpr->size);
  1008. if (!_sender_fpr)
  1009. goto enomem;
  1010. result->_sender_fpr = _sender_fpr;
  1011. }
  1012. if (msg->shortmsg) {
  1013. char *s = strndup((char *) msg->shortmsg->buf, msg->shortmsg->size);
  1014. assert(s);
  1015. if (!s)
  1016. goto enomem;
  1017. result->shortmsg = s;
  1018. }
  1019. size_t rest_blob_size = max_blob_size;
  1020. if (msg->longmsg) {
  1021. if (msg->longmsg->size > rest_blob_size)
  1022. goto enomem;
  1023. char *s = NULL;
  1024. if (copy) {
  1025. s = strndup((char *) msg->longmsg->buf, msg->longmsg->size);
  1026. if (!s)
  1027. goto enomem;
  1028. rest_blob_size -= msg->longmsg->size;
  1029. }
  1030. else /* move */ {
  1031. s = (char *) msg->longmsg->buf;
  1032. msg->longmsg->buf = NULL;
  1033. rest_blob_size -= msg->longmsg->size;
  1034. msg->longmsg->size = 0;
  1035. }
  1036. result->longmsg = s;
  1037. }
  1038. if (msg->longmsg_formatted) {
  1039. if (msg->longmsg_formatted->size > rest_blob_size)
  1040. goto enomem;
  1041. char *s = NULL;
  1042. if (copy) {
  1043. s = strndup((char *) msg->longmsg_formatted->buf,
  1044. msg->longmsg_formatted->size);
  1045. if (!s)
  1046. goto enomem;
  1047. rest_blob_size -= msg->longmsg_formatted->size;
  1048. }
  1049. else /* move */ {
  1050. s = (char *) msg->longmsg_formatted->buf;
  1051. msg->longmsg_formatted->buf = NULL;
  1052. rest_blob_size -= msg->longmsg_formatted->size;
  1053. msg->longmsg_formatted->size = 0;
  1054. }
  1055. result->longmsg_formatted = s;
  1056. }
  1057. if (msg->attachments) {
  1058. bloblist_t *a = PBlobList_to_bloblist(msg->attachments, NULL, copy,
  1059. rest_blob_size);
  1060. if (!a)
  1061. goto enomem;
  1062. result->attachments = a;
  1063. }
  1064. return result;
  1065. enomem:
  1066. if (allocated)
  1067. free_message(result);
  1068. return NULL;
  1069. }