- Update to Xerces-2.1 support
[shibboleth/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 <strstream>
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
19 class shibtarget::ShibMLPPriv {
20 public:
21   ShibMLPPriv();
22   ~ShibMLPPriv() {}
23   log4cpp::Category *log;
24 };  
25
26 ShibMLPPriv::ShibMLPPriv()
27 {
28   string ctx = "shibtarget.ShibMLP";
29   log = &(log4cpp::Category::getInstance(ctx));
30 }
31
32
33 static void trimspace (string& s)
34 {
35   int end = s.size() - 1, start = 0;
36
37   // Trim stuff on right.
38   while (end > 0 && !isgraph(s[end])) end--;
39
40   // Trim stuff on left.
41   while (start < end && !isgraph(s[start])) start++;
42
43   // Modify the string.
44   s = s.substr(start, end - start + 1);
45 }
46
47 ShibMLP::ShibMLP ()
48 {
49   m_priv = new ShibMLPPriv ();
50 }
51
52 ShibMLP::~ShibMLP ()
53 {
54   delete m_priv;
55 }
56
57 string ShibMLP::run (const string& is) const
58 {
59   string res;
60
61   const char* line = is.c_str();
62   const char* lastpos = line;
63   const char* thispos;
64
65   m_priv->log->info("Processing string");
66
67   //
68   // Search for SHIBMLP tags.  These are of the form:
69   //    <shibmlp key />
70   // Note that there MUST be white-space after "<shibmlp" but
71   // there does not need to be white space between the key and
72   // the close-tag.
73   //
74   while ((thispos = strstr(lastpos, "<")) != NULL) {
75     // save the string up to this token
76     res += is.substr(lastpos-line, thispos-lastpos);
77
78     // Make sure this token matches our token.
79     if (strnicmp (thispos, "<shibmlp ", 9)) {
80       res += "<";
81       lastpos = thispos + 1;
82       continue;
83     }
84
85     // Save this position off.
86     lastpos = thispos + 9;      // strlen("<shibmlp ")
87
88     // search for the end-tag
89     if ((thispos = strstr(lastpos, "/>")) != NULL) {
90       string key = is.substr(lastpos-line, thispos-lastpos);
91       trimspace(key);
92
93       m_priv->log->debug("found key: \"%s\"", key.c_str());
94
95       map<string,string>::const_iterator i=m_map.find(key);
96       if (i == m_map.end()) {
97         static string s1 = "<!-- Unknown SHIBMLP key: ";
98         static string s2 = "/>";
99         res += s1 + key + s2;
100         m_priv->log->debug("key unknown");
101       } else {
102         res += i->second;
103         m_priv->log->debug("key maps to \"%s\"", i->second.c_str());
104       }
105
106       lastpos = thispos + 2;    // strlen("/>")
107     }
108   }
109   res += is.substr(lastpos-line);
110
111   return res;
112 }
113
114 string ShibMLP::run (istream& is) const
115 {
116   static string eol = "\r\n";
117   string str, line;
118
119   m_priv->log->info("processing stream");
120
121   while (getline(is, line))
122     str += line + eol;
123
124   return run(str);
125 }
126
127 void ShibMLP::insert (RPCError& e)
128 {
129   insert ("errorType", e.toString());
130   insert ("errorText", (e.m_except ? e.m_except->what() : e.error_msg));
131 }