Add support for the originErrorURL, originContactName, and originContactEmail
[shibboleth/cpp-sp.git] / shib-target / shib-mlp.cpp
1 /*
2  * shib-mlp.cpp -- The ShibTarget Markup Language processor
3  *
4  * Created by:  Derek Atkins <derek@ihtfp.com>
5  *
6  * $Id$
7  */
8
9 #include "shib-target.h"
10 #include <sstream>
11 #include <ctype.h>
12 #include <xercesc/util/XercesDefs.hpp>
13
14 #include <log4cpp/Category.hh>
15
16 using namespace std;
17 using namespace shibtarget;
18 using namespace saml;
19
20 class shibtarget::ShibMLPPriv {
21 public:
22   ShibMLPPriv();
23   ~ShibMLPPriv() {}
24   log4cpp::Category *log;
25 };  
26
27 ShibMLPPriv::ShibMLPPriv()
28 {
29   string ctx = "shibtarget.ShibMLP";
30   log = &(log4cpp::Category::getInstance(ctx));
31 }
32
33
34 static void trimspace (string& s)
35 {
36   int end = s.size() - 1, start = 0;
37
38   // Trim stuff on right.
39   while (end > 0 && !isgraph(s[end])) end--;
40
41   // Trim stuff on left.
42   while (start < end && !isgraph(s[start])) start++;
43
44   // Modify the string.
45   s = s.substr(start, end - start + 1);
46 }
47
48 ShibMLP::ShibMLP ()
49 {
50   m_priv = new ShibMLPPriv ();
51 }
52
53 ShibMLP::~ShibMLP ()
54 {
55   delete m_priv;
56 }
57
58 string ShibMLP::run (const string& is) const
59 {
60   string res;
61
62   const char* line = is.c_str();
63   const char* lastpos = line;
64   const char* thispos;
65
66   m_priv->log->info("Processing string");
67
68   //
69   // Search for SHIBMLP tags.  These are of the form:
70   //    <shibmlp key />
71   // Note that there MUST be white-space after "<shibmlp" but
72   // there does not need to be white space between the key and
73   // the close-tag.
74   //
75   while ((thispos = strstr(lastpos, "<")) != NULL) {
76     // save the string up to this token
77     res += is.substr(lastpos-line, thispos-lastpos);
78
79     // Make sure this token matches our token.
80     if (strnicmp (thispos, "<shibmlp ", 9)) {
81       res += "<";
82       lastpos = thispos + 1;
83       continue;
84     }
85
86     // Save this position off.
87     lastpos = thispos + 9;      // strlen("<shibmlp ")
88
89     // search for the end-tag
90     if ((thispos = strstr(lastpos, "/>")) != NULL) {
91       string key = is.substr(lastpos-line, thispos-lastpos);
92       trimspace(key);
93
94       m_priv->log->debug("found key: \"%s\"", key.c_str());
95
96       map<string,string>::const_iterator i=m_map.find(key);
97       if (i == m_map.end()) {
98         static string s1 = "<!-- Unknown SHIBMLP key: ";
99         static string s2 = "/>";
100         res += s1 + key + s2;
101         m_priv->log->debug("key unknown");
102       } else {
103         res += i->second;
104         m_priv->log->debug("key maps to \"%s\"", i->second.c_str());
105       }
106
107       lastpos = thispos + 2;    // strlen("/>")
108     }
109   }
110   res += is.substr(lastpos-line);
111
112   return res;
113 }
114
115 string ShibMLP::run (istream& is) const
116 {
117   static string eol = "\r\n";
118   string str, line;
119
120   m_priv->log->info("processing stream");
121
122   while (getline(is, line))
123     str += line + eol;
124
125   return run(str);
126 }
127
128 void ShibMLP::insert (RPCError& e)
129 {
130   insert ("errorType", e.getType());
131   insert ("errorText", e.getText());
132   insert ("errorDesc", e.getDesc());
133   insert ("originErrorURL", e.getOriginErrorURL());
134   insert ("originContactName", e.getOriginContactName());
135   insert ("originContactEmail", e.getOriginContactEmail());
136 }