CPPXT-104 - Add exception handling to integer conversions
[shibboleth/cpp-xmltooling.git] / xmltooling / util / TemplateEngine.cpp
index 2333c8c..ca9ca71 100644 (file)
@@ -1,17 +1,21 @@
-/*
- *  Copyright 2001-2009 Internet2
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * UCAID licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the
+ * License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the License.
  */
 
 /**
  */
 
 #include "internal.h"
+#include "io/GenericRequest.h"
 #include "util/TemplateEngine.h"
 
+#include <boost/algorithm/string/trim.hpp>
+
 using namespace xmltooling;
 using namespace std;
+using boost::trim;
+
+namespace {
+    static const pair<const string,string> emptyPair;
+}
+
+TemplateEngine::TemplateEngine()
+{
+    setTagPrefix("mlp");
+}
+
+TemplateEngine::~TemplateEngine()
+{
+}
+
+TemplateEngine::TemplateParameters::TemplateParameters() : m_request(nullptr)
+{
+}
+
+TemplateEngine::TemplateParameters::~TemplateParameters()
+{
+}
+
+const char* TemplateEngine::TemplateParameters::getParameter(const char* name) const
+{
+    map<string,string>::const_iterator i=m_map.find(name);
+    return (i!=m_map.end() ? i->second.c_str() : (m_request ? m_request->getParameter(name) : nullptr));
+}
+
+const multimap<string,string>* TemplateEngine::TemplateParameters::getLoopCollection(const char* name) const
+{
+    map< string,multimap<string,string> >::const_iterator i=m_collectionMap.find(name);
+    return (i!=m_collectionMap.end() ? &(i->second) : nullptr);
+}
 
 void TemplateEngine::setTagPrefix(const char* tagPrefix)
 {
@@ -74,33 +115,20 @@ void TemplateEngine::html_encode(ostream& os, const char* start) const
     }
 }
 
-void TemplateEngine::trimspace(string& s) const
-{
-  string::size_type end = s.size() - 1, start = 0;
-
-  // Trim stuff on right.
-  while (end > 0 && !isgraph(s[end])) end--;
-
-  // Trim stuff on left.
-  while (start < end && !isgraph(s[start])) start++;
-
-  // Modify the string.
-  s = s.substr(start, end - start + 1);
-}
-
 void TemplateEngine::process(
     bool visible,
     const string& buf,
     const char*& lastpos,
     ostream& os,
     const TemplateParameters& parameters,
+    const pair<const string,string>& loopentry,
     const XMLToolingException* e
     ) const
 {
     const char* line = buf.c_str();
     const char* thispos;
 
-    while ((thispos = strchr(lastpos, '<')) != NULL) {
+    while ((thispos = strchr(lastpos, '<')) != nullptr) {
         // Output the string up to this token.
         if (visible)
             os << buf.substr(lastpos-line, thispos-lastpos);
@@ -116,15 +144,21 @@ void TemplateEngine::process(
             lastpos = thispos + keytag.length();
 
             // search for the end-tag
-            if ((thispos = strstr(lastpos, "/>")) != NULL) {
+            if ((thispos = strstr(lastpos, "/>")) != nullptr) {
                 string key = buf.substr(lastpos-line, thispos-lastpos);
-                trimspace(key);
+                trim(key);
 
-                const char* p = parameters.getParameter(key.c_str());
-                if (!p && e)
-                    p = e->getProperty(key.c_str());
-                if (p)
-                    html_encode(os,p);
+                if (key == "$name" && !loopentry.first.empty())
+                    html_encode(os,loopentry.first.c_str());
+                else if (key == "$value" && !loopentry.second.empty())
+                    html_encode(os,loopentry.second.c_str());
+                else {
+                    const char* p = parameters.getParameter(key.c_str());
+                    if (!p && e)
+                        p = e->getProperty(key.c_str());
+                    if (p)
+                        html_encode(os,p);
+                }
                 lastpos = thispos + 2; // strlen("/>")
             }
         }
@@ -138,14 +172,14 @@ void TemplateEngine::process(
             lastpos = thispos + iftag.length();
 
             // search for the end of this tag
-            if ((thispos = strchr(lastpos, '>')) != NULL) {
+            if ((thispos = strchr(lastpos, '>')) != nullptr) {
                 string key = buf.substr(lastpos-line, thispos-lastpos);
-                trimspace(key);
+                trim(key);
                 bool cond=false;
                 if (visible)
                     cond = parameters.getParameter(key.c_str()) || (e && e->getProperty(key.c_str()));
                 lastpos = thispos + 1; // strlen(">")
-                process(cond, buf, lastpos, os, parameters, e);
+                process(cond, buf, lastpos, os, parameters, loopentry, e);
             }
         }
 #ifdef HAVE_STRCASECMP
@@ -168,14 +202,14 @@ void TemplateEngine::process(
             lastpos = thispos + ifnottag.length();
 
             // search for the end of this tag
-            if ((thispos = strchr(lastpos, '>')) != NULL) {
+            if ((thispos = strchr(lastpos, '>')) != nullptr) {
                 string key = buf.substr(lastpos-line, thispos-lastpos);
-                trimspace(key);
+                trim(key);
                 bool cond=visible;
                 if (visible)
                     cond = !(parameters.getParameter(key.c_str()) || (e && e->getProperty(key.c_str())));
                 lastpos = thispos + 1; // strlen(">")
-                process(cond, buf, lastpos, os, parameters, e);
+                process(cond, buf, lastpos, os, parameters, loopentry, e);
             }
         }
 #ifdef HAVE_STRCASECMP
@@ -201,26 +235,23 @@ void TemplateEngine::process(
             bool cond = visible;
 
             // search for the end of this tag
-            if ((thispos = strchr(lastpos, '>')) != NULL) {
+            if ((thispos = strchr(lastpos, '>')) != nullptr) {
                 key = buf.substr(lastpos-line, thispos-lastpos);
-                trimspace(key);
+                trim(key);
                 lastpos = thispos + 1; // strlen(">")
             }
 
-            const vector<TemplateParameters>& forParams = parameters.getParameterCollection(key.c_str());
-            vector<TemplateParameters>::size_type forend = forParams.size();
-            if (forend == 0) {  // have to go through at least once to match end tags
-               cond = false;
-               forend = 1;
+            const multimap<string,string>* forParams = parameters.getLoopCollection(key.c_str());
+            if (!forParams || forParams->size() == 0) {
+                process(false, buf, lastpos, os, parameters, emptyPair, e);
             }
-
-            const char *savlastpos = lastpos;
-            for (vector<TemplateParameters>::size_type i=0; i<forend; ++i) {
-                static TemplateParameters nullp;
-                lastpos = savlastpos;
-                process(cond, buf, lastpos, os, (forParams.size()>0 ? forParams[i] : nullp), e);
+            else {
+                const char* savlastpos = lastpos;
+                for (multimap<string,string>::const_iterator i=forParams->begin(); i!=forParams->end(); ++i) {
+                    lastpos = savlastpos;
+                    process(cond, buf, lastpos, os, parameters, *i, e);
+                }
             }
-
         }
 
 #ifdef HAVE_STRCASECMP
@@ -252,5 +283,5 @@ void TemplateEngine::run(istream& is, ostream& os, const TemplateParameters& par
         buf += line + '\n';
 
     const char* pos=buf.c_str();
-    process(true, buf, pos, os, parameters, e);
+    process(true, buf, pos, os, parameters, emptyPair, e);
 }