2 * shib-ini.h -- INI file handling
4 * Created By: Derek Atkins <derek@ihtfp.com>
9 #include "shib-target.h"
15 #include <log4cpp/Category.hh>
18 using namespace shibtarget;
20 class HeaderIterator : public shibtarget::ShibINI::Iterator {
22 HeaderIterator (ShibINIPriv* ini);
23 ~HeaderIterator () { }
25 const string* begin();
29 map<string, map<string,string> >::const_iterator iter;
33 class TagIterator : public ShibINI::Iterator {
35 TagIterator (ShibINIPriv* ini, const string& header);
38 const string* begin();
43 map<string,string>::const_iterator iter;
47 class shibtarget::ShibINIPriv {
51 log4cpp::Category *log;
53 map<string, map<string, string> > table;
58 ShibINIPriv::ShibINIPriv()
60 string ctx = "shibtarget.ShibINI";
61 log = &(log4cpp::Category::getInstance(ctx));
64 static void trimline (string& s)
66 int end = s.size() - 1, start = 0;
68 // Trim stuff on right.
69 while (end > 0 && !isgraph(s[end])) end--;
71 // Trim stuff on left.
72 while (start < end && !isgraph(s[start])) start++;
75 s = s.substr(start, end - start + 1);
78 static void to_lowercase (string& s)
80 for (int i = 0, sz = s.size(); i < sz; i++)
88 void ShibINI::init (string& f, bool case_sensitive)
90 m_priv = new ShibINIPriv();
92 m_priv->cs = case_sensitive;
93 m_priv->log->info ("initializing INI file: %s (sensitive=%s)", f.c_str(),
94 (case_sensitive ? "true" : "false"));
98 void ShibINI::refresh(void)
100 // clear the existing maps
101 m_priv->table.clear();
103 m_priv->log->info("reading %s", m_priv->file.c_str());
108 ifstream infile (m_priv->file.c_str());
110 m_priv->log->warn("cannot open file: %s", m_priv->file.c_str());
114 const int MAXLEN = 1024;
115 char linebuffer[MAXLEN];
116 string current_header;
117 bool have_header = false;
120 infile.getline (linebuffer, MAXLEN);
121 string line (linebuffer);
123 if (line[0] == '#') continue;
126 if (line.size() <= 1) continue;
128 if (line[0] == '[') {
131 m_priv->log->debug("Found what appears to be a header line");
135 // find the end of the header
136 int endpos = line.find (']');
137 if (endpos == line.npos) {
138 m_priv->log->debug("Weird: no end found.. punting");
139 continue; // HUH? No end?
143 current_header = line.substr (1, endpos-1);
144 trimline (current_header);
146 if (!m_priv->cs) to_lowercase (current_header);
148 m_priv->table[current_header] = map<string,string>();
150 m_priv->log->debug("current header: \"%s\"", current_header.c_str());
152 } else if (have_header) {
155 m_priv->log->debug("Found what appears to be a tag line");
158 int mid = line.find ('=');
160 if (mid == line.npos) {
161 m_priv->log->debug("Weird: no '=' found.. punting");
162 continue; // Can't find the value's setting
165 tag = line.substr (0,mid);
166 setting = line.substr (mid+1, line.size()-mid);
171 if (!m_priv->cs) to_lowercase (tag);
173 // If it already exists, log an error and do not save it
174 if (exists (current_header, tag))
175 m_priv->log->error("Duplicate tag found in section %s: \"%s\"",
176 current_header.c_str(), tag.c_str());
178 (m_priv->table[current_header])[tag] = setting;
180 m_priv->log->debug("new tag: \"%s\" = \"%s\"",
181 tag.c_str(), setting.c_str());
185 } // until the file ends
188 // In case there are exceptions.
192 const std::string& ShibINI::get (const string& header, const string& tag) const
194 static string empty = "";
204 if (!exists(h)) return empty;
206 map<string,string>::const_iterator i = m_priv->table[h].find(t);
207 if (i == m_priv->table[h].end())
212 bool ShibINI::exists(const std::string& header) const
215 if (!m_priv->cs) to_lowercase (h);
217 return (m_priv->table.find(h) != m_priv->table.end());
220 bool ShibINI::exists(const std::string& header, const std::string& tag) const
230 if (!exists(h)) return false;
231 return (m_priv->table[h].find(t) != m_priv->table[h].end());
234 void ShibINI::dump (ostream& os) const
236 os << "File: " << m_priv->file << "\n";
237 os << "Case-Sensitive: " << ( m_priv->cs ? "Yes\n" : "No\n" );
238 os << "File Entries:\n";
240 for (map<string, map<string, string> >::const_iterator i = m_priv->table.begin();
241 i != m_priv->table.end(); i++) {
243 os << "[" << i->first << "]\n";
245 for (map<string,string>::const_iterator j=i->second.begin();
246 j != i->second.end(); j++) {
248 os << " " << j->first << " = " << j->second << "\n";
255 ShibINI::Iterator* ShibINI::header_iterator() const
257 HeaderIterator* iter = new HeaderIterator(m_priv);
258 return (ShibINI::Iterator*) iter;
261 ShibINI::Iterator* ShibINI::tag_iterator(const std::string& header) const
263 TagIterator* iter = new TagIterator(m_priv, header);
264 return (ShibINI::Iterator*) iter;
267 HeaderIterator::HeaderIterator (ShibINIPriv* inip)
273 const string* HeaderIterator::begin ()
275 iter = ini->table.begin();
276 if (iter == ini->table.end()) {
284 const string* HeaderIterator::next ()
289 if (iter == ini->table.end()) {
296 TagIterator::TagIterator (ShibINIPriv* inip, const string& headerp)
303 const string* TagIterator::begin ()
305 iter = ini->table[header].begin();
306 if (iter == ini->table[header].end()) {
314 const string* TagIterator::next ()
319 if (iter == ini->table[header].end()) {