Imported Upstream version 2.2.1+dfsg
[shibboleth/sp.git] / shibsp / attribute / ExtensibleAttribute.cpp
1 /*
2  *  Copyright 2009 Internet2
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * shibsp/attribute/ExtensibleAttribute.cpp
19  *
20  * An Attribute whose values are arbitrary structures.
21  */
22
23 #include "internal.h"
24 #include "SPConfig.h"
25 #include "attribute/ExtensibleAttribute.h"
26 #include "util/SPConstants.h"
27
28 using namespace shibsp;
29 using namespace xmltooling;
30 using namespace std;
31
32 const vector<string>& ExtensibleAttribute::getSerializedValues() const
33 {
34     if (m_serialized.empty()) {
35         const char* formatter = m_obj["_formatter"].string();
36         if (formatter) {
37             string msg = formatter;
38             DDF val = m_obj.first().first();
39             while (!val.isnull()) {
40
41                 static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_.[]";
42
43                 m_serialized.push_back(string());
44                 string& processed = m_serialized.back();
45
46                 string::size_type i=0,start=0;
47                 while (start!=string::npos && start<msg.length() && (i=msg.find("$",start))!=string::npos) {
48                     if (i>start)
49                         processed += msg.substr(start,i-start); // append everything in between
50                     start=i+1;                                  // move start to the beginning of the token name
51                     i=msg.find_first_not_of(legal,start);       // find token delimiter
52                     if (i==start) {                             // append a non legal character
53                        processed+=msg[start++];
54                        continue;
55                     }
56                     
57                     string tag = msg.substr(start,(i==string::npos) ? i : i-start);
58                     if (tag == "_string" && val.string()) {
59                         processed += val.string();
60                         start=i;
61                     }
62                     else {
63                         DDF child = val.getmember(tag.c_str());
64                         if (child.string())
65                             processed += child.string();
66                         else if (child.isstruct() && child["_string"].string())
67                             processed += child["_string"].string();
68                         start=i;
69                     }
70                 }
71                 if (start!=string::npos && start<msg.length())
72                     processed += msg.substr(start,i);    // append rest of string
73
74                 val = m_obj.first().next();
75             }
76         }
77     }
78     return Attribute::getSerializedValues();
79 }