29
30
using namespace suPHP;
31
IniSection& suPHP::IniFile::getSection(std::string name)
32
const IniSection& suPHP::IniFile::getSection(const std::string& name) const
32
33
throw (KeyNotFoundException) {
33
34
if (this->sections.find(name) != this->sections.end()) {
34
return this->sections.find(name)->second;
35
return this->sections.find(name)->second;
36
throw KeyNotFoundException("Section " + name + " not found",
37
throw KeyNotFoundException("Section " + name + " not found",
41
bool suPHP::IniFile::hasSection(std::string name) {
42
bool suPHP::IniFile::hasSection(const std::string& name) const {
42
43
if (this->sections.find(name) != this->sections.end()) {
50
IniSection& suPHP::IniFile::operator[](std::string name)
51
const IniSection& suPHP::IniFile::operator[](const std::string& name) const
51
52
throw (KeyNotFoundException) {
52
53
return this->getSection(name);
56
void suPHP::IniFile::parse(File file) throw (IOException, ParsingException) {
57
void suPHP::IniFile::parse(const File& file) throw (IOException, ParsingException) {
57
58
SmartPtr<std::ifstream> is = file.getInputStream();
58
59
IniSection *current_section = NULL;
59
60
while (!is->eof() && !is->bad() && !is->fail()) {
66
// Read line from file
71
// Find first char not being space or tab
72
startpos = tstr.find_first_not_of(" \t");
73
// Find last char not being space or tab
74
endpos = tstr.find_last_not_of(" \t");
76
// Skip empty line, only containing whitespace
77
if (startpos == std::string::npos)
81
tstr = tstr.substr(startpos, endpos - startpos + 1);
83
// Is line a comment (starting with ";")?
85
// Comments are not interessting => skip
67
// Read line from file
72
// Find first char not being space or tab
73
startpos = tstr.find_first_not_of(" \t");
74
// Find last char not being space or tab
75
endpos = tstr.find_last_not_of(" \t");
77
// Skip empty line, only containing whitespace
78
if (startpos == std::string::npos)
82
tstr = tstr.substr(startpos, endpos - startpos + 1);
84
// Is line a comment (starting with ";")?
86
// Comments are not interessting => skip
88
89
// Is line a section mark ("[section]")?
89
} else if (tstr[0] == '[' && tstr[tstr.size()-1] == ']') {
90
// Extract name of section
91
std::string name = tstr.substr(1, tstr.size() - 2);
92
// If section is not yet existing, create it
93
if (!this->hasSection(name)) {
94
std::pair<std::string, IniSection> p;
98
this->sections.insert(p);
100
// Set current section
101
current_section = &(this->getSection(name));
103
// Is the line a key-value pair?
104
} else if (tstr.find_first_of('=') != std::string::npos) {
109
// Check wheter we already have a section
110
if (current_section == NULL) {
111
throw ParsingException("Option line \"" + tstr +
112
"\" before first section",
117
eqpos = tstr.find_first_of('=');
118
name = tstr.substr(0, eqpos);
119
value = tstr.substr(eqpos + 1, tstr.size() - eqpos + 1);
120
name = name.substr(0, name.find_last_not_of(" \t") + 1);
121
value = value.substr(value.find_first_not_of(" \t"));
123
value = value.substr(1);
124
if (value[value.size()-1] == '"')
125
value = value.substr(0, value.size()-1);
126
current_section->putValue(name, value);
127
// Line is something we do not know
129
throw ParsingException("Illegal line \"" + tstr + "\"",
90
} else if (tstr[0] == '[' && tstr[tstr.size()-1] == ']') {
91
// Extract name of section
92
std::string name = tstr.substr(1, tstr.size() - 2);
93
// If section is not yet existing, create it
94
if (!this->hasSection(name)) {
95
std::pair<std::string, IniSection> p;
99
this->sections.insert(p);
101
// Set current section
102
current_section = &(this->sections.find(name)->second);
104
// Is the line a key-value pair?
105
} else if (tstr.find_first_of('=') != std::string::npos) {
107
std::vector<std::string> values;
108
bool append_mode = false;
112
// Check wheter we already have a section
113
if (current_section == NULL) {
114
throw ParsingException("Option line \"" + tstr +
115
"\" before first section",
120
eqpos = tstr.find_first_of('=');
121
if (eqpos == std::string::npos || eqpos < 1 || eqpos == tstr.length()-1) {
122
throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
124
if (tstr[eqpos-1] == '+') {
126
name = tstr.substr(0, eqpos-1);
128
name = tstr.substr(0, eqpos);
132
temppos = name.find_first_not_of(" \t");
133
if (temppos == std::string::npos) {
134
throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
136
name = name.substr(0, name.find_last_not_of(" \t") + 1);
138
bool in_quotes = false;
139
bool last_was_backslash = false;
140
int token_start = eqpos + 1;
142
for (int i=eqpos+1; i<tstr.length(); i++) {
143
bool current_is_backslash = false;
144
if (tstr[i] == '"') {
145
if (!last_was_backslash) {
146
in_quotes = !in_quotes;
148
} else if (tstr[i] == '\\') {
149
if (!last_was_backslash) {
150
current_is_backslash = true;
152
} else if (tstr[i] == ':') {
153
if (!in_quotes && !last_was_backslash) {
154
// Save token and begin new one
155
std::string token = tstr.substr(token_start, i - token_start);
157
token = parseValue(token);
158
} catch (ParsingException e) {
159
throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
161
if (token.length() == 0) {
162
throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
164
values.push_back(token);
168
if (i == tstr.length() - 1) {
170
throw ParsingException("Unended quotes in line: " + tstr, __FILE__, __LINE__);
171
} else if (last_was_backslash) {
172
throw ParsingException("Multiline values are not supported in line: " + tstr, __FILE__, __LINE__);
174
std::string token = tstr.substr(token_start, i + 1 - token_start);
176
token = parseValue(token);
177
} catch (ParsingException e) {
178
throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
180
if (token.length() == 0) {
181
throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
183
values.push_back(token);
185
last_was_backslash = current_is_backslash;
189
current_section->removeValues(name);
191
for (std::vector<std::string>::iterator i = values.begin(); i != values.end(); i++) {
192
current_section->putValue(name, *i);
195
// Line is something we do not know
197
throw ParsingException("Malformed line \"" + tstr + "\"",
204
std::string suPHP::IniFile::parseValue(const std::string& value) const throw (ParsingException) {
205
bool in_quotes = false;
206
bool last_was_backslash = false;
207
std::string tempvalue;
210
int startpos = value.find_first_not_of(" \t");
211
int endpos = value.find_last_not_of(" \t");
212
if (startpos == std::string::npos) {
215
if (endpos == std::string::npos) {
218
tempvalue = value.substr(startpos, endpos - startpos + 1);
221
for (int i=0; i<value.length(); i++) {
222
bool current_is_backslash = false;
224
if (tempvalue[i] == '"') {
225
if (last_was_backslash) {
228
if (!in_quotes && i != 0) {
229
throw ParsingException("Content preceding quoted content", __FILE__, __LINE__);
231
if (in_quotes && i != tempvalue.length() - 1) {
232
throw ParsingException("Content following quoted content", __FILE__, __LINE__);
234
in_quotes = !in_quotes;
236
} else if (tempvalue[i] == '\\') {
237
if (last_was_backslash) {
240
current_is_backslash = true;
242
} else if (tempvalue[i] == ':') {
245
if (last_was_backslash) {
246
throw ParsingException("Illegal character after backslash", __FILE__, __LINE__);
248
output.append(tempvalue.substr(i, 1));
251
last_was_backslash = current_is_backslash;