33 #include <qdatetime.h>
36 #include <qfileinfo.h>
38 #include <qmetaobject.h>
45 return QString::fromLatin1(
"KConfigIni: In file %2, line %1: ")
46 .arg(line).arg(file.fileName());
62 return parseConfig(currentLocale, entryMap, options,
false);
67 ParseOptions options,
bool merging)
75 QByteArray currentGroup(
"<default>");
78 if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
83 bool fileOptionImmutable =
false;
84 bool groupOptionImmutable =
false;
85 bool groupSkip =
false;
90 QByteArray buffer = file.readAll();
92 unsigned int len = contents.
length();
93 unsigned int startOfLine = 0;
95 while (startOfLine < len) {
104 if (line.
at(0) ==
'[') {
105 groupOptionImmutable = fileOptionImmutable;
112 if (end == line.
length()) {
113 qWarning() <<
warningProlog(file, lineNo) <<
"Invalid group header.";
117 if (line.
at(end) ==
']')
121 if (end + 1 == line.
length() && start + 2 == end &&
122 line.
at(start) ==
'$' && line.
at(start + 1) ==
'i')
124 if (newGroup.isEmpty())
125 fileOptionImmutable = !kde_kiosk_exception;
130 if (!newGroup.isEmpty())
136 }
while ((start = end + 2) <= line.
length() && line.
at(end + 1) ==
'[');
137 currentGroup = newGroup;
141 if (groupSkip && !bDefault)
144 if (groupOptionImmutable)
147 immutableGroups.append(currentGroup);
149 if (groupSkip && !bDefault)
164 qWarning() <<
warningProlog(file, lineNo) <<
"Invalid entry (empty key)";
168 KEntryMap::EntryOptions entryOptions=0;
169 if (groupOptionImmutable)
175 int end = aKey.
indexOf(
']', start);
178 <<
"Invalid entry (missing ']')";
180 }
else if (end > start + 1 && aKey.
at(start + 1) ==
'$') {
183 switch (aKey.
at(i)) {
185 if (!kde_kiosk_exception)
189 if (allowExecutableValues)
194 aKey = aKey.
left(start);
206 <<
"Invalid entry (second locale!?)";
210 locale = aKey.
mid(start + 1,end - start - 1);
215 qWarning() <<
warningProlog(file, lineNo) <<
"Invalid entry (missing '=')";
220 if (locale != currentLocale) {
222 if (locale.
at(0) !=
'C' || currentLocale !=
"en_US") {
241 if (entryOptions & KEntryMap::EntryRawKey) {
256 foreach(
const QByteArray&
group, immutableGroups) {
264 const KEntryMap& map,
bool defaultGroup,
bool &firstEntry)
266 QByteArray currentGroup;
267 bool groupIsImmutable =
false;
268 const KEntryMapConstIterator end = map.constEnd();
269 for (KEntryMapConstIterator it = map.constBegin(); it != end; ++it) {
273 if ((key.
mGroup !=
"<default>") == defaultGroup)
277 if (key.
mKey.isNull()) {
278 groupIsImmutable = it->bImmutable;
282 const KEntry& currentEntry = *it;
283 if (!defaultGroup && currentGroup != key.
mGroup) {
286 currentGroup = key.
mGroup;
287 for (
int start = 0, end;; start = end + 1) {
289 end = currentGroup.indexOf(
'\x1d', start);
291 int cgl = currentGroup.length();
292 if (currentGroup.at(start) ==
'$' && cgl - start <= 10) {
293 for (
int i = start + 1; i < cgl; i++) {
294 char c = currentGroup.at(i);
295 if (c < 'a' || c >
'z')
304 if (groupIsImmutable) {
305 file.write(
"[$i]", 4);
320 file.write(key.
mKey);
323 if (key.
bLocal && locale !=
"C") {
331 file.write(
"[$di]", 5);
333 file.write(
"[$d]", 4);
352 bool firstEntry =
true;
379 const KEntryMapIterator end = entryMap.end();
380 for (KEntryMapIterator it=entryMap.begin(); it != end; ++it) {
381 if (!it.key().mKey.isEmpty() && !it->bDirty)
387 if (it->bGlobal == bGlobal) {
393 if (!entryMap.contains(defaultKey)) {
394 writeMap.remove(key);
409 QFile::Permissions fileMode = QFile::ReadUser | QFile::WriteUser;
410 bool createNew =
true;
415 if (fi.ownerId() == ::getuid())
418 fileMode = fi.permissions();
434 file.setPermissions(fileMode);
436 file.setTextModeEnabled(
true);
446 if (!file.size() && (fileMode == (QFile::ReadUser | QFile::WriteUser))) {
464 int fd = KDE_open(QFile::encodeName(
filePath()), O_WRONLY | O_TRUNC);
468 FILE *fp = KDE_fdopen(fd,
"w");
474 if (!f.open(fp, QIODevice::WriteOnly)) {
484 if (!f.open( QIODevice::WriteOnly | QIODevice::Truncate )) {
487 f.setTextModeEnabled(
true);
504 if (!file.exists()) {
505 QFileInfo dir(file.absolutePath());
506 while (!dir.exists()) {
507 QString parent = dir.absolutePath();
508 if (parent == dir.filePath()) {
514 return dir.isDir() && dir.isWritable();
523 return i18n(
"Configuration file \"%1\" not writable.\n",
filePath());
534 dir.mkpath(QFileInfo(file).absolutePath());
542 Q_ASSERT(QDir::isAbsolutePath(file));
544 const QFileInfo info(file);
590 return lockFile && lockFile->
isLocked();
595 static const char nibbleLookup[] = {
596 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
597 '8',
'9',
'a',
'b',
'c',
'd',
'e',
'f'
600 if (aString.isEmpty())
602 const int l = aString.length();
605 result.resize(l * 4);
606 register const char *s = aString.constData();
608 char *data = result.data();
622 if (((
unsigned char)s[i]) < 32)
658 *data++ = nibbleLookup[((
unsigned char)s[i]) >> 4];
659 *data++ = nibbleLookup[((
unsigned char)s[i]) & 0x0f];
664 result.resize(data - start);
668 result.replace(result.length() - 1, 1,
"\\s");
677 unsigned char ret = 0;
678 for (
int i = 0; i < 2; i++) {
680 quint8 c = quint8(str[i]);
682 if (c >=
'0' && c <=
'9') {
684 }
else if (c >=
'a' && c <=
'f') {
685 ret |= c -
'a' + 0x0a;
686 }
else if (c >=
'A' && c <=
'F') {
687 ret |= c -
'A' + 0x0a;
689 QByteArray e(str, 2);
691 qWarning() <<
warningProlog(file, line) <<
"Invalid hex character " << c
692 <<
" in \\x<nn>-type escape sequence \"" << e.constData() <<
"\".";
704 int l = aString->
length();
705 char *r = aString->
data();
708 for(
int i = 0; i < l; i++, r++) {
747 << QString::fromLatin1(
"Invalid escape sequence \"\\%1\".").arg(str[i]);