~ubuntu-branches/ubuntu/oneiric/suphp/oneiric

« back to all changes in this revision

Viewing changes to src/IniFile.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Emmanuel Lacour
  • Date: 2009-08-03 15:15:38 UTC
  • mfrom: (8.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20090803151538-pv7yhe6w1mqmceas
Tags: 0.7.1-1
* New upstream release (closes: #528379, #520182) 
* debian/NEWS: add information about AddHandler -> AddType change introduced
  in 0.6.2-2 (closes: #517805)
* debian/conf/suphp.conf, debian/patches/01_debian.dpatch: switch from
  application/x-httpd-php to application/x-httpd-suphp to allow
  simultaneous use of mod_suphp and mod_php (closes: #519005, #514725)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
    suPHP - (c)2002-2005 Sebastian Marsching <sebastian@marsching.com>
 
2
    suPHP - (c)2002-2008 Sebastian Marsching <sebastian@marsching.com>
3
3
 
4
4
    This file is part of suPHP.
5
5
 
21
21
#include <string>
22
22
#include <fstream>
23
23
#include <sstream>
 
24
#include <vector>
24
25
 
25
26
#include "KeyNotFoundException.hpp"
26
27
 
28
29
 
29
30
using namespace suPHP;
30
31
 
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;
35
36
    } else {
36
 
        throw KeyNotFoundException("Section " + name + " not found", 
37
 
                                   __FILE__, __LINE__);
 
37
        throw KeyNotFoundException("Section " + name + " not found", 
 
38
                                   __FILE__, __LINE__);
38
39
    }
39
40
}
40
41
 
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()) {
43
 
        return true;
 
44
        return true;
44
45
    } else {
45
 
        return false;
 
46
        return false;
46
47
    }
47
48
    
48
49
}
49
50
 
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);
53
54
}
54
55
 
55
56
 
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()) {
60
 
        std::string line;
61
 
        std::string tstr;
62
 
        char dummy;
63
 
        int startpos = 0;
64
 
        int endpos = 0;
65
 
        
66
 
        // Read line from file
67
 
        getline(*is, line);
68
 
        
69
 
        tstr = line;
70
 
        
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");
75
 
 
76
 
        // Skip empty line, only containing whitespace
77
 
        if (startpos == std::string::npos)
78
 
            continue;
79
 
        
80
 
        // Get trimmed string
81
 
        tstr = tstr.substr(startpos, endpos - startpos + 1);
82
 
 
83
 
        // Is line a comment (starting with ";")?
84
 
        if (tstr[0] == ';') {
85
 
            // Comments are not interessting => skip
86
 
            continue;
 
61
        std::string line;
 
62
        std::string tstr;
 
63
        char dummy;
 
64
        int startpos = 0;
 
65
        int endpos = 0;
 
66
        
 
67
        // Read line from file
 
68
        getline(*is, line);
 
69
        
 
70
        tstr = line;
 
71
        
 
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");
 
76
 
 
77
        // Skip empty line, only containing whitespace
 
78
        if (startpos == std::string::npos)
 
79
            continue;
 
80
        
 
81
        // Get trimmed string
 
82
        tstr = tstr.substr(startpos, endpos - startpos + 1);
 
83
 
 
84
        // Is line a comment (starting with ";")?
 
85
        if (tstr[0] == ';') {
 
86
            // Comments are not interessting => skip
 
87
            continue;
87
88
       
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;
95
 
                IniSection sect;
96
 
                p.first = name;
97
 
                p.second = sect;
98
 
                this->sections.insert(p);
99
 
            }
100
 
            // Set current section
101
 
            current_section = &(this->getSection(name));
102
 
            
103
 
        // Is the line a key-value pair?
104
 
        } else if (tstr.find_first_of('=') != std::string::npos) {
105
 
            std::string name;
106
 
            std::string value;
107
 
            int eqpos = 0;
108
 
            
109
 
            // Check wheter we already have a section
110
 
            if (current_section == NULL) {
111
 
                throw ParsingException("Option line \"" + tstr +
112
 
                                       "\" before first section", 
113
 
                                       __FILE__, __LINE__);
114
 
            }
115
 
            
116
 
            // Extract name
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"));
122
 
            if (value[0] == '"')
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
128
 
        } else {
129
 
            throw ParsingException("Illegal line \"" + tstr + "\"", 
130
 
                                   __FILE__, __LINE__);
131
 
        }
 
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;
 
96
                IniSection sect;
 
97
                p.first = name;
 
98
                p.second = sect;
 
99
                this->sections.insert(p);
 
100
            }
 
101
            // Set current section
 
102
            current_section = &(this->sections.find(name)->second);
 
103
            
 
104
        // Is the line a key-value pair?
 
105
        } else if (tstr.find_first_of('=') != std::string::npos) {
 
106
            std::string name;
 
107
            std::vector<std::string> values;
 
108
            bool append_mode = false;
 
109
            
 
110
            int eqpos = 0;
 
111
            
 
112
            // Check wheter we already have a section
 
113
            if (current_section == NULL) {
 
114
                throw ParsingException("Option line \"" + tstr +
 
115
                                       "\" before first section", 
 
116
                                       __FILE__, __LINE__);
 
117
            }
 
118
            
 
119
            // Extract name
 
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__);
 
123
            }
 
124
            if (tstr[eqpos-1] == '+') {
 
125
                append_mode = true;
 
126
                name = tstr.substr(0, eqpos-1);
 
127
            } else {
 
128
                name = tstr.substr(0, eqpos);
 
129
            }
 
130
            
 
131
            int temppos;
 
132
            temppos = name.find_first_not_of(" \t");
 
133
            if (temppos == std::string::npos) {
 
134
                throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
 
135
            }
 
136
            name = name.substr(0, name.find_last_not_of(" \t") + 1);
 
137
            
 
138
            bool in_quotes = false;
 
139
            bool last_was_backslash = false;
 
140
            int token_start = eqpos + 1;
 
141
            
 
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;
 
147
                    }
 
148
                } else if (tstr[i] == '\\') {
 
149
                    if (!last_was_backslash) {
 
150
                        current_is_backslash = true;
 
151
                    }
 
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);
 
156
                        try {
 
157
                            token = parseValue(token);
 
158
                        } catch (ParsingException e) {
 
159
                            throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
 
160
                        }
 
161
                        if (token.length() == 0) {
 
162
                            throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
 
163
                        }
 
164
                        values.push_back(token);
 
165
                        token_start = i + 1;
 
166
                    }
 
167
                }
 
168
                if (i == tstr.length() - 1) {
 
169
                    if (in_quotes) {
 
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__);
 
173
                    }
 
174
                    std::string token = tstr.substr(token_start, i + 1 - token_start);
 
175
                    try {
 
176
                        token = parseValue(token);
 
177
                    } catch (ParsingException e) {
 
178
                        throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
 
179
                    }
 
180
                    if (token.length() == 0) {
 
181
                        throw ParsingException("Malformed line: " + tstr, __FILE__, __LINE__);
 
182
                    }
 
183
                    values.push_back(token);
 
184
                }
 
185
                last_was_backslash = current_is_backslash;
 
186
            }
 
187
 
 
188
            if (!append_mode) {
 
189
                current_section->removeValues(name);
 
190
            }
 
191
            for (std::vector<std::string>::iterator i = values.begin(); i != values.end(); i++) {
 
192
                current_section->putValue(name, *i);
 
193
            }
 
194
            
 
195
        // Line is something we do not know
 
196
        } else {
 
197
            throw ParsingException("Malformed line \"" + tstr + "\"", 
 
198
                                   __FILE__, __LINE__);
 
199
        }
132
200
    }
133
201
    is->close();
134
202
}
 
203
 
 
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;
 
208
    std::string output;
 
209
    
 
210
    int startpos = value.find_first_not_of(" \t");
 
211
    int endpos = value.find_last_not_of(" \t");
 
212
    if (startpos == std::string::npos) {
 
213
        return "";
 
214
    }
 
215
    if (endpos == std::string::npos) {
 
216
        tempvalue = value;
 
217
    } else {
 
218
        tempvalue = value.substr(startpos, endpos - startpos + 1);
 
219
    }
 
220
    
 
221
    for (int i=0; i<value.length(); i++) {
 
222
        bool current_is_backslash = false;
 
223
        
 
224
        if (tempvalue[i] == '"') {
 
225
            if (last_was_backslash) {
 
226
                output.append("\"");
 
227
            } else {
 
228
                if (!in_quotes && i != 0) {
 
229
                    throw ParsingException("Content preceding quoted content", __FILE__, __LINE__);
 
230
                }
 
231
                if (in_quotes && i != tempvalue.length() - 1) {
 
232
                    throw ParsingException("Content following quoted content", __FILE__, __LINE__);
 
233
                }
 
234
                in_quotes = !in_quotes;
 
235
            }
 
236
        } else if (tempvalue[i] == '\\') {
 
237
            if (last_was_backslash) {
 
238
                output.append("\\");
 
239
            } else {
 
240
                current_is_backslash = true;
 
241
            }
 
242
        } else if (tempvalue[i] == ':') {
 
243
            output.append(":");
 
244
        } else {
 
245
            if (last_was_backslash) {
 
246
                throw ParsingException("Illegal character after backslash", __FILE__, __LINE__);
 
247
            }
 
248
            output.append(tempvalue.substr(i, 1));
 
249
        }
 
250
        
 
251
        last_was_backslash = current_is_backslash;
 
252
    }
 
253
    
 
254
    return output;
 
255
}