From 8a5a5fa2090a81fd18f7ed89920d0a95475bf6ab Mon Sep 17 00:00:00 2001
From: Damyan Mitev <damyan.mitev@vereign.com>
Date: Sat, 14 Dec 2019 21:11:26 +0200
Subject: [PATCH] add header checks, add logs

---
 javascript/src/iframe/viamapi-iframe.js    | 28 ++++++++++---
 javascript/src/utilities/emailUtilities.js | 49 ++++++++++++++++++++--
 2 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/javascript/src/iframe/viamapi-iframe.js b/javascript/src/iframe/viamapi-iframe.js
index 9ae5bb3..5b3e7eb 100644
--- a/javascript/src/iframe/viamapi-iframe.js
+++ b/javascript/src/iframe/viamapi-iframe.js
@@ -1424,7 +1424,7 @@ const connection = Penpal.connectToParent({
     //   body: String if it is a text part (Content-Type = "text/...") or Uint8Array otherwise; filled for leaf MIME nodes
     //   parts: array of instances of the same object; filled for container MIME nodes (Content-Type = "multipart/...")
     // }
-    signVCard: async (passportUUID, senderEmail, attribs, text, html, parts) => {
+    signVCard: async (passportUUID, senderEmail, attribs, textBody, htmlBody, parts) => {
       const authenticationPublicKey = localStorage.getItem(
         "authenticatedIdentity"
       );
@@ -1509,27 +1509,43 @@ const connection = Penpal.connectToParent({
         parts = [];
       }
 
-      if (html) {
+      if (htmlBody) {
+        if (typeof htmlBody !== "string") {
+          throw new Error("htmlBody is not string"); // should not happen
+        }
         const htmlPart = {
           headers: {
             "Content-Type": "text/html"
           },
-          body: html
+          body: htmlBody
         };
         parts.unshift(htmlPart);
+      } else {
+        console.log("Html body is not passed to signVCard, its value is ", {html: htmlBody});
       }
 
-      if (text) {
+      if (textBody) {
+        if (typeof textBody !== "string") {
+          throw new Error("textBody is not string"); // should not happen
+        }
         const textPart = {
           headers: {
             "Content-Type": "text/plain"
           },
-          body: text
+          body: textBody
         };
         parts.unshift(textPart);
+      } else {
+        console.log("Text body is not passed to signVCard, its value is ", {text: textBody});
       }
 
-      prepareVCardParts(parts);
+      const count = prepareVCardParts(parts);
+      if (count.textParts === 0) {
+        return encodeResponse("400", "", "No text parts passed to signVCard");
+      }
+      if (count.htmlParts === 0) {
+        return encodeResponse("400", "", "No html parts passed to signVCard");
+      }
 
       const certResponse = await getCertificateForPassport(passportUUID, true);
 
diff --git a/javascript/src/utilities/emailUtilities.js b/javascript/src/utilities/emailUtilities.js
index d9131fb..988f879 100644
--- a/javascript/src/utilities/emailUtilities.js
+++ b/javascript/src/utilities/emailUtilities.js
@@ -136,11 +136,49 @@ export const extractHtmlBodyFromString = string => {
     .trim();
 };
 
-export const prepareVCardParts = parts => {
+const capitalizeHeaderName = str => {
+  if (!str || typeof str !== 'string') { return; }
+  const strChunks = splitBy(str,'-');
+  return  strChunks.map(capitalizeFirstLetter).join('-');
+};
+const splitBy = (string,separator) =>{
+  if (typeof string !== 'string') { return; }
+  return string.split(separator);
+};
+const capitalizeFirstLetter = (s) => {
+  if (typeof s !== 'string') { return; }
+  return s.charAt(0).toUpperCase() + s.slice(1);
+};
+
+export function prepareVCardParts(parts) {
   if (!parts) {
     return;
   }
+  const count = {
+    textParts: 0,
+    htmlParts: 0
+  };
   for (const part of parts) {
+    if (!part.headers) {
+      part.headers = {
+        "Content-Type": "application/octet-stream"
+      };
+    } else {
+      const capitalizedHeaders = {};
+      for (const key of Object.keys(part.headers)) {
+        capitalizedHeaders[capitalizeHeaderName(key)] = part.headers[key];
+      }
+      part.headers = capitalizedHeaders;
+      try {
+        if (part.headers["Content-Type"].startsWith("text/plain")) {
+          count.textParts++;
+        } else if (part.headers["Content-Type"].startsWith("text/html")) {
+          count.htmlParts++;
+        }
+      } catch (ignore) {
+        //ignore
+      }
+    }
     if (part.body) {
       if (typeof part.body === "string") {
         part.body = stringToUtf8Base64(part.body);
@@ -151,11 +189,14 @@ export const prepareVCardParts = parts => {
       if (part.body instanceof ArrayBuffer) {
         part.body = byteArrayToBase64(new Uint8Array(part.body));
       } else {
-        throw new Error('part body is neither string, nor Uint8Array, nor ArrayBuffer');
+        throw new Error('part body is neither string, nor Uint8Array, nor ArrayBuffer'); // should not happen
       }
     }
     if (part.parts) {
-      prepareVCardParts(part.parts);
+      const subcount = prepareVCardParts(part.parts);
+      count.textParts += subcount.textParts;
+      count.htmlParts += subcount.htmlParts;
     }
   }
-};
+  return count;
+}
-- 
GitLab