From 0c681d645f77f5d355c6ef2446e58bb95236fa0e Mon Sep 17 00:00:00 2001
From: Lazlo Westerhof <l.r.westerhof@uu.nl>
Date: Fri, 28 Sep 2018 11:03:24 +0200
Subject: [PATCH] Escape URL's for ePIC JSON payload.

---
 CMakeLists.txt            |  2 +-
 src/msiRegisterEpicPID.cc | 36 ++++++++++++++++++++++++++++--------
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2251b12..320fb47 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -119,7 +119,7 @@ set(CPACK_GENERATOR "RPM")
 set(CPACK_PACKAGE_NAME "irods-uu-microservices")
 set(CPACK_PACKAGE_VENDOR "Utrecht University <fbyoda@uu.nl>")
 set(CPACK_PACKAGE_CONTACT "Utrecht University <fbyoda@uu.nl>")
-set(CPACK_PACKAGE_VERSION "4.2.4_0.7.8")
+set(CPACK_PACKAGE_VERSION "4.2.4_0.7.9")
 
 set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/package/description.txt")
 set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Miscellaneous iRODS microservices developed or modified by Utrecht University.")
diff --git a/src/msiRegisterEpicPID.cc b/src/msiRegisterEpicPID.cc
index 44ea797..d96fd8e 100644
--- a/src/msiRegisterEpicPID.cc
+++ b/src/msiRegisterEpicPID.cc
@@ -2,6 +2,7 @@
  * \file
  * \brief     iRODS microservice to register a PID with EPIC.
  * \author    Felix Croes
+ * \author    Lazlo Westerhof
  * \copyright Copyright (c) 2018, Utrecht University
  *
  * This file is part of irods-uu-microservices.
@@ -27,13 +28,37 @@
 #include <string>
 #include <fstream>
 #include <streambuf>
+#include <sstream>
+#include <iomanip>
 #include <curl/curl.h>
 
 static CredentialsStore credentials;
 static size_t length;
 
-extern "C" {
+std::string escapeJson(const std::string &s) {
+    std::ostringstream o;
+    for (auto c = s.cbegin(); c != s.cend(); c++) {
+        switch (*c) {
+        case '"': o << "\\\""; break;
+        case '\\': o << "\\\\"; break;
+        case '\b': o << "\\b"; break;
+        case '\f': o << "\\f"; break;
+        case '\n': o << "\\n"; break;
+        case '\r': o << "\\r"; break;
+        case '\t': o << "\\t"; break;
+        default:
+            if ('\x00' <= *c && *c <= '\x1f') {
+                o << "\\u"
+                  << std::hex << std::setw(4) << std::setfill('0') << (int)*c;
+            } else {
+                o << *c;
+            }
+        }
+    }
+    return o.str();
+}
 
+extern "C" {
   /* Curl requires a static callback function to read the input of a PUT request from.
    * This callback simply copies the payload. */
   static size_t readCallback(void *buffer, size_t size, size_t nmemb, void *userp)
@@ -84,11 +109,6 @@ extern "C" {
     std::string value       = parseMspForStr(valueIn);
     std::string uuid        = parseMspForStr(idInOut);
 
-    /* Minimally verify that these will embed nicely in a payload. */
-    if (value.find('"') != std::string::npos) {
-      return SYS_INVALID_INPUT_PARAM;
-    }
-
     /* Retriece parameters from the credentials store. */
     std::string url(credentials.get("epic_url"));
     std::string prefix(credentials.get("epic_handle_prefix"));
@@ -118,7 +138,7 @@ extern "C" {
 
       /* Create payload. */
       std::string payload = "{\"values\":[{\"index\":1,\"type\":\"URL\",\"data\":{\"format\":\"string\",\"value\":\"" +
-			    value +
+			    escapeJson(value) +
 			    "\"}},{\"index\":100,\"type\":\"HS_ADMIN\",\"data\":{\"format\":\"admin\",\"value\":{\"handle\":\"0.NA/" +
 			    prefix +
 			    "\",\"index\":200,\"permissions\":\"011111110011\"}}}]}";
@@ -127,7 +147,7 @@ extern "C" {
       length = payload.length();
       curl_easy_setopt(curl, CURLOPT_INFILESIZE, (long) length);
       curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, discard);
-	
+
       /* Don't verify the server certificate. */
       curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
       curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
-- 
GitLab