• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KDECore

  • sources
  • kde-4.14
  • kdelibs
  • kdecore
  • config
kconfigini.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the KDE libraries
3  Copyright (c) 2006, 2007 Thomas Braxton <kde.braxton@gmail.com>
4  Copyright (c) 1999 Preston Brown <pbrown@kde.org>
5  Copyright (C) 1997-1999 Matthias Kalle Dalheimer (kalle@kde.org)
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include "kconfigini_p.h"
24 
25 #include "kconfig.h"
26 #include "kconfigbackend.h"
27 #include "bufferfragment_p.h"
28 #include "kconfigdata.h"
29 #include <ksavefile.h>
30 #include <kde_file.h>
31 #include "kstandarddirs.h"
32 
33 #include <qdatetime.h>
34 #include <qdir.h>
35 #include <qfile.h>
36 #include <qfileinfo.h>
37 #include <qdebug.h>
38 #include <qmetaobject.h>
39 #include <qregexp.h>
40 
41 extern bool kde_kiosk_exception;
42 
43 static QByteArray lookup(const KConfigIniBackend::BufferFragment& fragment, QHash<KConfigIniBackend::BufferFragment, QByteArray>* cache)
44 {
45  QHash<KConfigIniBackend::BufferFragment, QByteArray>::iterator it = cache->find(fragment);
46  if (it == cache->end()) {
47  it = cache->insert(fragment, fragment.toByteArray());
48  }
49  return it.value();
50 }
51 
52 QString KConfigIniBackend::warningProlog(const QFile &file, int line)
53 {
54  return QString::fromLatin1("KConfigIni: In file %2, line %1: ")
55  .arg(line).arg(file.fileName());
56 }
57 
58 KConfigIniBackend::KConfigIniBackend()
59  : KConfigBackend()
60 {
61 }
62 
63 KConfigIniBackend::~KConfigIniBackend()
64 {
65 }
66 
67 KConfigBackend::ParseInfo
68  KConfigIniBackend::parseConfig(const QByteArray& currentLocale, KEntryMap& entryMap,
69  ParseOptions options)
70 {
71  return parseConfig(currentLocale, entryMap, options, false);
72 }
73 
74 // merging==true is the merging that happens at the beginning of writeConfig:
75 // merge changes in the on-disk file with the changes in the KConfig object.
76 KConfigBackend::ParseInfo
77 KConfigIniBackend::parseConfig(const QByteArray& currentLocale, KEntryMap& entryMap,
78  ParseOptions options, bool merging)
79 {
80  if (filePath().isEmpty() || !QFile::exists(filePath()))
81  return ParseOk;
82 
83  bool bDefault = options&ParseDefaults;
84  bool allowExecutableValues = options&ParseExpansions;
85 
86  QByteArray currentGroup("<default>");
87 
88  QFile file(filePath());
89  if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
90  return ParseOpenError;
91 
92  QList<QByteArray> immutableGroups;
93 
94  bool fileOptionImmutable = false;
95  bool groupOptionImmutable = false;
96  bool groupSkip = false;
97 
98  int lineNo = 0;
99  // on systems using \r\n as end of line, \r will be taken care of by
100  // trim() below
101  QByteArray buffer = file.readAll();
102  BufferFragment contents(buffer.data(), buffer.size());
103  unsigned int len = contents.length();
104  unsigned int startOfLine = 0;
105 
106  // Reduce memory overhead by making use of implicit sharing
107  // This assumes that config files contain only a small amount of
108  // different fragments which are repeated often.
109  // This is often the case, especially sub groups will all have
110  // the same list of keys and similar values as well.
111  QHash<BufferFragment, QByteArray> cache;
112  cache.reserve(4096);
113 
114  while (startOfLine < len) {
115  BufferFragment line = contents.split('\n', &startOfLine);
116  line.trim();
117  lineNo++;
118 
119  // skip empty lines and lines beginning with '#'
120  if (line.isEmpty() || line.at(0) == '#')
121  continue;
122 
123  if (line.at(0) == '[') { // found a group
124  groupOptionImmutable = fileOptionImmutable;
125 
126  QByteArray newGroup;
127  int start = 1, end;
128  do {
129  end = start;
130  for (;;) {
131  if (end == line.length()) {
132  qWarning() << warningProlog(file, lineNo) << "Invalid group header.";
133  // XXX maybe reset the current group here?
134  goto next_line;
135  }
136  if (line.at(end) == ']')
137  break;
138  end++;
139  }
140  if (end + 1 == line.length() && start + 2 == end &&
141  line.at(start) == '$' && line.at(start + 1) == 'i')
142  {
143  if (newGroup.isEmpty())
144  fileOptionImmutable = !kde_kiosk_exception;
145  else
146  groupOptionImmutable = !kde_kiosk_exception;
147  }
148  else {
149  if (!newGroup.isEmpty())
150  newGroup += '\x1d';
151  BufferFragment namePart=line.mid(start, end - start);
152  printableToString(&namePart, file, lineNo);
153  newGroup += namePart.toByteArray();
154  }
155  } while ((start = end + 2) <= line.length() && line.at(end + 1) == '[');
156  currentGroup = newGroup;
157 
158  groupSkip = entryMap.getEntryOption(currentGroup, 0, 0, KEntryMap::EntryImmutable);
159 
160  if (groupSkip && !bDefault)
161  continue;
162 
163  if (groupOptionImmutable)
164  // Do not make the groups immutable until the entries from
165  // this file have been added.
166  immutableGroups.append(currentGroup);
167  } else {
168  if (groupSkip && !bDefault)
169  continue; // skip entry
170 
171  BufferFragment aKey;
172  int eqpos = line.indexOf('=');
173  if (eqpos < 0) {
174  aKey = line;
175  line.clear();
176  } else {
177  BufferFragment temp = line.left(eqpos);
178  temp.trim();
179  aKey = temp;
180  line.truncateLeft(eqpos + 1);
181  }
182  if (aKey.isEmpty()) {
183  qWarning() << warningProlog(file, lineNo) << "Invalid entry (empty key)";
184  continue;
185  }
186 
187  KEntryMap::EntryOptions entryOptions=0;
188  if (groupOptionImmutable)
189  entryOptions |= KEntryMap::EntryImmutable;
190 
191  BufferFragment locale;
192  int start;
193  while ((start = aKey.lastIndexOf('[')) >= 0) {
194  int end = aKey.indexOf(']', start);
195  if (end < 0) {
196  qWarning() << warningProlog(file, lineNo)
197  << "Invalid entry (missing ']')";
198  goto next_line;
199  } else if (end > start + 1 && aKey.at(start + 1) == '$') { // found option(s)
200  int i = start + 2;
201  while (i < end) {
202  switch (aKey.at(i)) {
203  case 'i':
204  if (!kde_kiosk_exception)
205  entryOptions |= KEntryMap::EntryImmutable;
206  break;
207  case 'e':
208  if (allowExecutableValues)
209  entryOptions |= KEntryMap::EntryExpansion;
210  break;
211  case 'd':
212  entryOptions |= KEntryMap::EntryDeleted;
213  aKey = aKey.left(start);
214  printableToString(&aKey, file, lineNo);
215  entryMap.setEntry(currentGroup, aKey.toByteArray(), QByteArray(), entryOptions);
216  goto next_line;
217  default:
218  break;
219  }
220  i++;
221  }
222  } else { // found a locale
223  if (!locale.isNull()) {
224  qWarning() << warningProlog(file, lineNo)
225  << "Invalid entry (second locale!?)";
226  goto next_line;
227  }
228 
229  locale = aKey.mid(start + 1,end - start - 1);
230  }
231  aKey.truncate(start);
232  }
233  if (eqpos < 0) { // Do this here after [$d] was checked
234  qWarning() << warningProlog(file, lineNo) << "Invalid entry (missing '=')";
235  continue;
236  }
237  printableToString(&aKey, file, lineNo);
238  if (!locale.isEmpty()) {
239  if (locale != currentLocale) {
240  // backward compatibility. C == en_US
241  if (locale.at(0) != 'C' || currentLocale != "en_US") {
242  if (merging)
243  entryOptions |= KEntryMap::EntryRawKey;
244  else
245  goto next_line; // skip this entry if we're not merging
246  }
247  }
248  }
249 
250  if (!(entryOptions & KEntryMap::EntryRawKey))
251  printableToString(&aKey, file, lineNo);
252 
253  if (options&ParseGlobal)
254  entryOptions |= KEntryMap::EntryGlobal;
255  if (bDefault)
256  entryOptions |= KEntryMap::EntryDefault;
257  if (!locale.isNull())
258  entryOptions |= KEntryMap::EntryLocalized;
259  printableToString(&line, file, lineNo);
260  if (entryOptions & KEntryMap::EntryRawKey) {
261  QByteArray rawKey;
262  rawKey.reserve(aKey.length() + locale.length() + 2);
263  rawKey.append(aKey.toVolatileByteArray());
264  rawKey.append('[').append(locale.toVolatileByteArray()).append(']');
265  entryMap.setEntry(currentGroup, rawKey, lookup(line, &cache), entryOptions);
266  } else {
267  entryMap.setEntry(currentGroup, lookup(aKey, &cache), lookup(line, &cache), entryOptions);
268  }
269  }
270 next_line:
271  continue;
272  }
273 
274  // now make sure immutable groups are marked immutable
275  foreach(const QByteArray& group, immutableGroups) {
276  entryMap.setEntry(group, QByteArray(), QByteArray(), KEntryMap::EntryImmutable);
277  }
278 
279  return fileOptionImmutable ? ParseImmutable : ParseOk;
280 }
281 
282 void KConfigIniBackend::writeEntries(const QByteArray& locale, QFile& file,
283  const KEntryMap& map, bool defaultGroup, bool &firstEntry)
284 {
285  QByteArray currentGroup;
286  bool groupIsImmutable = false;
287  const KEntryMapConstIterator end = map.constEnd();
288  for (KEntryMapConstIterator it = map.constBegin(); it != end; ++it) {
289  const KEntryKey& key = it.key();
290 
291  // Either process the default group or all others
292  if ((key.mGroup != "<default>") == defaultGroup)
293  continue; // skip
294 
295  // the only thing we care about groups is, is it immutable?
296  if (key.mKey.isNull()) {
297  groupIsImmutable = it->bImmutable;
298  continue; // skip
299  }
300 
301  const KEntry& currentEntry = *it;
302  if (!defaultGroup && currentGroup != key.mGroup) {
303  if (!firstEntry)
304  file.putChar('\n');
305  currentGroup = key.mGroup;
306  for (int start = 0, end;; start = end + 1) {
307  file.putChar('[');
308  end = currentGroup.indexOf('\x1d', start);
309  if (end < 0) {
310  int cgl = currentGroup.length();
311  if (currentGroup.at(start) == '$' && cgl - start <= 10) {
312  for (int i = start + 1; i < cgl; i++) {
313  char c = currentGroup.at(i);
314  if (c < 'a' || c > 'z')
315  goto nope;
316  }
317  file.write("\\x24");
318  start++;
319  }
320  nope:
321  file.write(stringToPrintable(currentGroup.mid(start), GroupString));
322  file.putChar(']');
323  if (groupIsImmutable) {
324  file.write("[$i]", 4);
325  }
326  file.putChar('\n');
327  break;
328  } else {
329  file.write(stringToPrintable(currentGroup.mid(start, end - start), GroupString));
330  file.putChar(']');
331  }
332  }
333  }
334 
335  firstEntry = false;
336  // it is data for a group
337 
338  if (key.bRaw) // unprocessed key with attached locale from merge
339  file.write(key.mKey);
340  else {
341  file.write(stringToPrintable(key.mKey, KeyString)); // Key
342  if (key.bLocal && locale != "C") { // 'C' locale == untranslated
343  file.putChar('[');
344  file.write(locale); // locale tag
345  file.putChar(']');
346  }
347  }
348  if (currentEntry.bDeleted) {
349  if (currentEntry.bImmutable)
350  file.write("[$di]", 5); // Deleted + immutable
351  else
352  file.write("[$d]", 4); // Deleted
353  } else {
354  if (currentEntry.bImmutable || currentEntry.bExpand) {
355  file.write("[$", 2);
356  if (currentEntry.bImmutable)
357  file.putChar('i');
358  if (currentEntry.bExpand)
359  file.putChar('e');
360  file.putChar(']');
361  }
362  file.putChar('=');
363  file.write(stringToPrintable(currentEntry.mValue, ValueString));
364  }
365  file.putChar('\n');
366  }
367 }
368 
369 void KConfigIniBackend::writeEntries(const QByteArray& locale, QFile& file, const KEntryMap& map)
370 {
371  bool firstEntry = true;
372 
373  // write default group
374  writeEntries(locale, file, map, true, firstEntry);
375 
376  // write all other groups
377  writeEntries(locale, file, map, false, firstEntry);
378 }
379 
380 bool KConfigIniBackend::writeConfig(const QByteArray& locale, KEntryMap& entryMap,
381  WriteOptions options, const KComponentData &data)
382 {
383  Q_ASSERT(!filePath().isEmpty());
384 
385  KEntryMap writeMap;
386  const bool bGlobal = options & WriteGlobal;
387 
388  // First, reparse the file on disk, to merge our changes with the ones done by other apps
389  // Store the result into writeMap.
390  {
391  ParseOptions opts = ParseExpansions;
392  if (bGlobal)
393  opts |= ParseGlobal;
394  ParseInfo info = parseConfig(locale, writeMap, opts, true);
395  if (info != ParseOk) // either there was an error or the file became immutable
396  return false;
397  }
398 
399  const KEntryMapIterator end = entryMap.end();
400  for (KEntryMapIterator it=entryMap.begin(); it != end; ++it) {
401  if (!it.key().mKey.isEmpty() && !it->bDirty) // not dirty, doesn't overwrite entry in writeMap. skips default entries, too.
402  continue;
403 
404  const KEntryKey& key = it.key();
405 
406  // only write entries that have the same "globality" as the file
407  if (it->bGlobal == bGlobal) {
408  if (it->bReverted) {
409  writeMap.remove(key);
410  } else if (!it->bDeleted) {
411  writeMap[key] = *it;
412  } else {
413  KEntryKey defaultKey = key;
414  defaultKey.bDefault = true;
415  if (!entryMap.contains(defaultKey)) {
416  writeMap.remove(key); // remove the deleted entry if there is no default
417  //qDebug() << "Detected as deleted=>removed:" << key.mGroup << key.mKey << "global=" << bGlobal;
418  } else {
419  writeMap[key] = *it; // otherwise write an explicitly deleted entry
420  //qDebug() << "Detected as deleted=>[$d]:" << key.mGroup << key.mKey << "global=" << bGlobal;
421  }
422  }
423  it->bDirty = false;
424  }
425  }
426 
427  // now writeMap should contain only entries to be written
428  // so write it out to disk
429 
430  // check if file exists
431  QFile::Permissions fileMode = QFile::ReadUser | QFile::WriteUser;
432  bool createNew = true;
433 
434  QFileInfo fi(filePath());
435  if (fi.exists())
436  {
437  if (fi.ownerId() == ::getuid())
438  {
439  // Preserve file mode if file exists and is owned by user.
440  fileMode = fi.permissions();
441  }
442  else
443  {
444  // File is not owned by user:
445  // Don't create new file but write to existing file instead.
446  createNew = false;
447  }
448  }
449 
450  if (createNew) {
451  KSaveFile file( filePath(), data );
452  if (!file.open()) {
453  return false;
454  }
455 
456  file.setPermissions(fileMode);
457 
458  file.setTextModeEnabled(true); // to get eol translation
459  writeEntries(locale, file, writeMap);
460 
461  if (!file.flush()) {
462  // Couldn't write. Disk full?
463  kWarning() << "Couldn't write" << filePath() << ". Disk full?";
464  file.abort();
465  return false;
466  }
467 
468  if (!file.size() && (fileMode == (QFile::ReadUser | QFile::WriteUser))) {
469  // File is empty and doesn't have special permissions: delete it.
470  file.abort();
471 
472  if (fi.exists()) {
473  // also remove the old file in case it existed. this can happen
474  // when we delete all the entries in an existing config file.
475  // if we don't do this, then deletions and revertToDefault's
476  // will mysteriously fail
477  QFile::remove(filePath());
478  }
479  } else {
480  // Normal case: Close the file
481  return file.finalize();
482  }
483  } else {
484  // Open existing file. *DON'T* create it if it suddenly does not exist!
485 #ifdef Q_OS_UNIX
486  int fd = KDE_open(QFile::encodeName(filePath()), O_WRONLY | O_TRUNC);
487  if (fd < 0) {
488  return false;
489  }
490  FILE *fp = KDE_fdopen(fd, "w");
491  if (!fp) {
492  close(fd);
493  return false;
494  }
495  QFile f;
496  if (!f.open(fp, QIODevice::WriteOnly)) {
497  fclose(fp);
498  return false;
499  }
500  writeEntries(locale, f, writeMap);
501  f.close();
502  fclose(fp);
503 #else
504  QFile f( filePath() );
505  // XXX This is broken - it DOES create the file if it is suddenly gone.
506  if (!f.open( QIODevice::WriteOnly | QIODevice::Truncate )) {
507  return false;
508  }
509  f.setTextModeEnabled(true);
510  writeEntries(locale, f, writeMap);
511 #endif
512  }
513  return true;
514 }
515 
516 bool KConfigIniBackend::isWritable() const
517 {
518  if (!filePath().isEmpty()) {
519  if (KStandardDirs::checkAccess(filePath(), W_OK)) {
520  return true;
521  }
522  // The check might have failed because any of the containing dirs
523  // did not exist. If the file does not exist, check if the deepest
524  // existing dir is writable.
525  QFileInfo file(filePath());
526  if (!file.exists()) {
527  QFileInfo dir(file.absolutePath());
528  while (!dir.exists()) {
529  QString parent = dir.absolutePath(); // Go up. Can't use cdUp() on non-existing dirs.
530  if (parent == dir.filePath()) {
531  // no parent
532  return false;
533  }
534  dir.setFile(parent);
535  }
536  return dir.isDir() && dir.isWritable();
537  }
538  }
539 
540  return false;
541 }
542 
543 QString KConfigIniBackend::nonWritableErrorMessage() const
544 {
545  return i18n("Configuration file \"%1\" not writable.\n", filePath());
546 }
547 
548 void KConfigIniBackend::createEnclosing()
549 {
550  const QString file = filePath();
551  if (file.isEmpty())
552  return; // nothing to do
553 
554  // Create the containing dir, maybe it wasn't there
555  QDir dir;
556  dir.mkpath(QFileInfo(file).absolutePath());
557 }
558 
559 void KConfigIniBackend::setFilePath(const QString& file)
560 {
561  if (file.isEmpty())
562  return;
563 
564  Q_ASSERT(QDir::isAbsolutePath(file));
565 
566  const QFileInfo info(file);
567  if (info.exists()) {
568  setLocalFilePath(info.canonicalFilePath());
569  setLastModified(info.lastModified());
570  setSize(info.size());
571  } else {
572  setLocalFilePath(file);
573  setSize(0);
574  QDateTime dummy;
575  dummy.setTime_t(0);
576  setLastModified(dummy);
577  }
578 }
579 
580 KConfigBase::AccessMode KConfigIniBackend::accessMode() const
581 {
582  if (filePath().isEmpty())
583  return KConfigBase::NoAccess;
584 
585  if (isWritable())
586  return KConfigBase::ReadWrite;
587 
588  return KConfigBase::ReadOnly;
589 }
590 
591 bool KConfigIniBackend::lock(const KComponentData& componentData)
592 {
593  Q_ASSERT(!filePath().isEmpty());
594 
595  if (!lockFile) {
596  lockFile = new KLockFile(filePath() + QLatin1String(".lock"), componentData);
597  }
598 
599  if (lockFile->lock() == KLockFile::LockStale) // attempt to break the lock
600  lockFile->lock(KLockFile::ForceFlag);
601  return lockFile->isLocked();
602 }
603 
604 void KConfigIniBackend::unlock()
605 {
606  lockFile->unlock();
607  lockFile.clear();
608 }
609 
610 bool KConfigIniBackend::isLocked() const
611 {
612  return lockFile && lockFile->isLocked();
613 }
614 
615 QByteArray KConfigIniBackend::stringToPrintable(const QByteArray& aString, StringType type)
616 {
617  static const char nibbleLookup[] = {
618  '0', '1', '2', '3', '4', '5', '6', '7',
619  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
620  };
621 
622  if (aString.isEmpty())
623  return aString;
624  const int l = aString.length();
625 
626  QByteArray result; // Guesstimated that it's good to avoid data() initialization for a length of l*4
627  result.resize(l * 4); // Maximum 4x as long as source string due to \x<ab> escape sequences
628  register const char *s = aString.constData();
629  int i = 0;
630  char *data = result.data();
631  char *start = data;
632 
633  // Protect leading space
634  if (s[0] == ' ' && type != GroupString) {
635  *data++ = '\\';
636  *data++ = 's';
637  i++;
638  }
639 
640  for (; i < l; ++i/*, r++*/) {
641  switch (s[i]) {
642  default:
643  // The \n, \t, \r cases (all < 32) are handled below; we can ignore them here
644  if (((unsigned char)s[i]) < 32)
645  goto doEscape;
646  *data++ = s[i];
647  break;
648  case '\n':
649  *data++ = '\\';
650  *data++ = 'n';
651  break;
652  case '\t':
653  *data++ = '\\';
654  *data++ = 't';
655  break;
656  case '\r':
657  *data++ = '\\';
658  *data++ = 'r';
659  break;
660  case '\\':
661  *data++ = '\\';
662  *data++ = '\\';
663  break;
664  case '=':
665  if (type != KeyString) {
666  *data++ = s[i];
667  break;
668  }
669  goto doEscape;
670  case '[':
671  case ']':
672  // Above chars are OK to put in *value* strings as plaintext
673  if (type == ValueString) {
674  *data++ = s[i];
675  break;
676  }
677  doEscape:
678  *data++ = '\\';
679  *data++ = 'x';
680  *data++ = nibbleLookup[((unsigned char)s[i]) >> 4];
681  *data++ = nibbleLookup[((unsigned char)s[i]) & 0x0f];
682  break;
683  }
684  }
685  *data = 0;
686  result.resize(data - start);
687 
688  // Protect trailing space
689  if (result.endsWith(' ') && type != GroupString) {
690  result.replace(result.length() - 1, 1, "\\s");
691  }
692  result.squeeze();
693 
694  return result;
695 }
696 
697 char KConfigIniBackend::charFromHex(const char *str, const QFile& file, int line)
698 {
699  unsigned char ret = 0;
700  for (int i = 0; i < 2; i++) {
701  ret <<= 4;
702  quint8 c = quint8(str[i]);
703 
704  if (c >= '0' && c <= '9') {
705  ret |= c - '0';
706  } else if (c >= 'a' && c <= 'f') {
707  ret |= c - 'a' + 0x0a;
708  } else if (c >= 'A' && c <= 'F') {
709  ret |= c - 'A' + 0x0a;
710  } else {
711  QByteArray e(str, 2);
712  e.prepend("\\x");
713  qWarning() << warningProlog(file, line) << "Invalid hex character " << c
714  << " in \\x<nn>-type escape sequence \"" << e.constData() << "\".";
715  return 'x';
716  }
717  }
718  return char(ret);
719 }
720 
721 void KConfigIniBackend::printableToString(BufferFragment* aString, const QFile& file, int line)
722 {
723  if (aString->isEmpty() || aString->indexOf('\\')==-1)
724  return;
725  aString->trim();
726  int l = aString->length();
727  char *r = aString->data();
728  char *str=r;
729 
730  for(int i = 0; i < l; i++, r++) {
731  if (str[i]!= '\\') {
732  *r=str[i];
733  } else {
734  // Probable escape sequence
735  i++;
736  if (i >= l) { // Line ends after backslash - stop.
737  *r = '\\';
738  break;
739  }
740 
741  switch(str[i]) {
742  case 's':
743  *r = ' ';
744  break;
745  case 't':
746  *r = '\t';
747  break;
748  case 'n':
749  *r = '\n';
750  break;
751  case 'r':
752  *r = '\r';
753  break;
754  case '\\':
755  *r = '\\';
756  break;
757  case 'x':
758  if (i + 2 < l) {
759  *r = charFromHex(str + i + 1, file, line);
760  i += 2;
761  } else {
762  *r = 'x';
763  i = l - 1;
764  }
765  break;
766  default:
767  *r = '\\';
768  qWarning() << warningProlog(file, line)
769  << QString::fromLatin1("Invalid escape sequence \"\\%1\".").arg(str[i]);
770  }
771  }
772  }
773  aString->truncate(r - aString->constData());
774 }
i18n
QString i18n(const char *text)
Returns a localized version of a string.
Definition: klocalizedstring.h:630
QByteArray::squeeze
void squeeze()
KEntryMap::EntryDeleted
Definition: kconfigdata.h:165
KConfigIniBackend::BufferFragment::constData
const char * constData() const
Definition: bufferfragment_p.h:65
KConfigIniBackend::BufferFragment::trim
void trim()
Definition: bufferfragment_p.h:75
QFile::flush
bool flush()
KConfigIniBackend::BufferFragment::left
BufferFragment left(unsigned int size) const
Definition: bufferfragment_p.h:104
QHash::insert
iterator insert(const Key &key, const T &value)
KConfigIniBackend::parseConfig
ParseInfo parseConfig(const QByteArray &locale, KEntryMap &entryMap, ParseOptions options)
Read persistent storage.
Definition: kconfigini.cpp:68
QMap::contains
bool contains(const Key &key) const
bufferfragment_p.h
kconfigini_p.h
KEntryMap
Definition: kconfigdata.h:152
KEntry::bDeleted
bool bDeleted
Entry has been deleted.
Definition: kconfigdata.h:58
KEntryMap::EntryImmutable
Definition: kconfigdata.h:164
KConfigIniBackend::BufferFragment
Definition: bufferfragment_p.h:36
QByteArray::reserve
void reserve(int size)
QByteArray
QByteArray::at
char at(int i) const
KConfigBackend::ParseOpenError
the configuration is immutable
Definition: kconfigbackend.h:112
KEntry
map/dict/list config node entry.
Definition: kconfigdata.h:35
KMacroExpander::group
Definition: kmacroexpander_unix.cpp:34
KConfigIniBackend::accessMode
KConfigBase::AccessMode accessMode() const
Definition: kconfigini.cpp:580
KConfigIniBackend::BufferFragment::data
char * data() const
Definition: bufferfragment_p.h:70
QFile::remove
bool remove()
KConfigIniBackend::KConfigIniBackend
KConfigIniBackend()
Definition: kconfigini.cpp:58
KEntryMap::EntryRawKey
Definition: kconfigdata.h:167
KConfigBackend::setLocalFilePath
void setLocalFilePath(const QString &file)
Definition: kconfigbackend.cpp:128
QFileInfo::permissions
QFile::Permissions permissions() const
KSharedPtr::clear
void clear()
Clear the pointer, i.e.
Definition: ksharedptr.h:220
kconfig.h
KConfigIniBackend::nonWritableErrorMessage
QString nonWritableErrorMessage() const
When isWritable() returns false, return an error message to explain to the user why saving configurat...
Definition: kconfigini.cpp:543
ksavefile.h
QMap::constBegin
const_iterator constBegin() const
KEntryKey::bDefault
bool bDefault
Entry indicates if this is a default value.
Definition: kconfigdata.h:111
QByteArray::isNull
bool isNull() const
QFile::fileName
QString fileName() const
KSaveFile
Class to allow for atomic file I/O, as well as utility functions.
Definition: ksavefile.h:96
KSaveFile::open
virtual bool open(OpenMode flags=QIODevice::ReadWrite)
Open the save file.
Definition: ksavefile.cpp:81
QByteArray::isEmpty
bool isEmpty() const
QHash::reserve
void reserve(int size)
KStandardDirs::checkAccess
static bool checkAccess(const QString &pathname, int mode)
Check, if a file may be accessed in a given mode.
Definition: kstandarddirs.cpp:2114
KConfigIniBackend::writeEntries
void writeEntries(const QByteArray &locale, QFile &file, const KEntryMap &map)
Definition: kconfigini.cpp:369
KConfigIniBackend::BufferFragment::at
char at(unsigned int i) const
Definition: bufferfragment_p.h:54
KConfigIniBackend::stringToPrintable
static QByteArray stringToPrintable(const QByteArray &aString, StringType type)
Definition: kconfigini.cpp:615
QFile::setPermissions
bool setPermissions(QFlags< QFile::Permission > permissions)
KLockFile::ForceFlag
Automatically remove a lock when a lock is detected that is stale for more than staleTime() seconds...
Definition: klockfile.h:84
QByteArray::length
int length() const
QFile::exists
bool exists() const
KSaveFile::abort
void abort()
Discard changes without affecting the target file.
Definition: ksavefile.cpp:204
KLockFile::lock
LockResult lock(LockFlags flags=LockFlags())
Attempt to acquire the lock.
Definition: klockfile_unix.cpp:386
KConfigBackend::WriteGlobal
Definition: kconfigbackend.h:103
KEntryMap::EntryExpansion
Definition: kconfigdata.h:166
QFile
KConfigIniBackend::BufferFragment::truncate
void truncate(unsigned int pos)
Definition: bufferfragment_p.h:116
KConfigIniBackend::BufferFragment::toByteArray
QByteArray toByteArray() const
Definition: bufferfragment_p.h:171
KConfigBase::ReadOnly
Definition: kconfigbase.h:133
KConfigIniBackend::BufferFragment::mid
BufferFragment mid(unsigned int pos, int length=-1) const
Definition: bufferfragment_p.h:126
QByteArray::resize
void resize(int size)
QHash::iterator
KLockFile
The KLockFile class provides NFS safe lockfiles.
Definition: klockfile.h:36
KConfigIniBackend::ValueString
Definition: kconfigini_p.h:64
QByteArray::indexOf
int indexOf(char ch, int from) const
kconfigbackend.h
QFileInfo::canonicalFilePath
QString canonicalFilePath() const
KConfigIniBackend::lock
bool lock(const KComponentData &componentData)
Lock the file.
Definition: kconfigini.cpp:591
KEntryMap::EntryLocalized
Definition: kconfigdata.h:169
KEntry::bImmutable
bool bImmutable
Entry can not be modified.
Definition: kconfigdata.h:54
QList::append
void append(const T &value)
KConfigBackend::ParseGlobal
Definition: kconfigbackend.h:94
KEntryKey
key structure holding both the actual key and the group to which it belongs.
Definition: kconfigdata.h:89
KEntryKey::mGroup
QByteArray mGroup
The "group" to which this EntryKey belongs.
Definition: kconfigdata.h:99
KConfigBackend::ParseInfo
ParseInfo
Return value from parseConfig()
Definition: kconfigbackend.h:109
kde_kiosk_exception
bool kde_kiosk_exception
Definition: kcomponentdata.cpp:162
KConfigIniBackend::KeyString
Definition: kconfigini_p.h:63
KConfigIniBackend::warningProlog
static QString warningProlog(const QFile &file, int line)
Definition: kconfigini.cpp:52
QHash
Definition: ksycocafactory.h:28
QByteArray::prepend
QByteArray & prepend(char ch)
QString::isEmpty
bool isEmpty() const
KConfigIniBackend::charFromHex
static char charFromHex(const char *str, const QFile &file, int line)
Definition: kconfigini.cpp:697
QMap::constEnd
const_iterator constEnd() const
QByteArray::constData
const char * constData() const
KLockFile::LockStale
A stale lock has been detected.
Definition: klockfile.h:70
QIODevice::readAll
QByteArray readAll()
QByteArray::replace
QByteArray & replace(int pos, int len, const char *after)
KEntryKey::bLocal
bool bLocal
Entry is localised or not.
Definition: kconfigdata.h:107
KConfigBackend
Provides the implementation for accessing configuration sources.
Definition: kconfigbackend.h:55
QString
QList< QByteArray >
QMap::end
iterator end()
QFileInfo::lastModified
QDateTime lastModified() const
QByteArray::mid
QByteArray mid(int pos, int len) const
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
KConfigIniBackend::unlock
void unlock()
Release the lock on the file.
Definition: kconfigini.cpp:604
QFile::Permissions
typedef Permissions
QMap::begin
iterator begin()
kconfigdata.h
KConfigIniBackend::~KConfigIniBackend
~KConfigIniBackend()
Definition: kconfigini.cpp:63
KConfigBackend::filePath
QString filePath() const
Definition: kconfigbackend.cpp:123
QByteArray::append
QByteArray & append(char ch)
QFileInfo
QFileInfo::size
qint64 size() const
QFileInfo::exists
bool exists() const
QHash::find
iterator find(const Key &key)
QFile::size
virtual qint64 size() const
KConfigIniBackend::BufferFragment::isNull
bool isNull() const
Definition: bufferfragment_p.h:121
QIODevice::putChar
bool putChar(char c)
KSaveFile::finalize
bool finalize()
Finalize changes to the file.
Definition: ksavefile.cpp:219
KEntryMap::setEntry
bool setEntry(const QByteArray &group, const QByteArray &key, const QByteArray &value, EntryOptions options)
Returns true if the entry gets dirtied or false in other case.
KConfigBackend::setLastModified
void setLastModified(const QDateTime &dt)
Definition: kconfigbackend.cpp:108
kWarning
#define kWarning
Definition: kdebug.h:322
QFile::close
virtual void close()
KConfigIniBackend::setFilePath
void setFilePath(const QString &path)
Set the file path.
Definition: kconfigini.cpp:559
KGlobal::locale
KLocale * locale()
Returns the global locale object.
Definition: kglobal.cpp:170
lookup
static QByteArray lookup(const KConfigIniBackend::BufferFragment &fragment, QHash< KConfigIniBackend::BufferFragment, QByteArray > *cache)
Definition: kconfigini.cpp:43
QDir
KConfigBackend::ParseImmutable
the configuration was opened read/write
Definition: kconfigbackend.h:111
KConfigBase::ReadWrite
Definition: kconfigbase.h:133
KConfigIniBackend::printableToString
static void printableToString(BufferFragment *aString, const QFile &file, int line)
Definition: kconfigini.cpp:721
KConfigIniBackend::BufferFragment::split
BufferFragment split(char c, unsigned int *start)
Definition: bufferfragment_p.h:87
KConfigBase::NoAccess
Definition: kconfigbase.h:133
QDir::isAbsolutePath
bool isAbsolutePath(const QString &path)
KLockFile::isLocked
bool isLocked() const
Returns whether the lock is held or not.
Definition: klockfile_unix.cpp:482
KConfigIniBackend::isLocked
bool isLocked() const
Definition: kconfigini.cpp:610
KConfigIniBackend::BufferFragment::truncateLeft
void truncateLeft(unsigned int size)
Definition: bufferfragment_p.h:109
QLatin1String
KConfigBackend::ParseOk
Definition: kconfigbackend.h:110
KConfigIniBackend::BufferFragment::indexOf
int indexOf(char c, unsigned int from=0) const
Definition: bufferfragment_p.h:150
KConfigIniBackend::BufferFragment::clear
void clear()
Definition: bufferfragment_p.h:60
KEntry::mValue
QByteArray mValue
Definition: kconfigdata.h:42
kstandarddirs.h
KConfigIniBackend::BufferFragment::toVolatileByteArray
QByteArray toVolatileByteArray() const
Definition: bufferfragment_p.h:177
KEntryKey::mKey
QByteArray mKey
The actual key of the entry in question.
Definition: kconfigdata.h:103
KConfigIniBackend::BufferFragment::lastIndexOf
int lastIndexOf(char c) const
Definition: bufferfragment_p.h:160
KConfigIniBackend::BufferFragment::length
int length() const
Definition: bufferfragment_p.h:49
QFileInfo::ownerId
uint ownerId() const
KConfigIniBackend::GroupString
Definition: kconfigini_p.h:62
KConfigBase::AccessMode
AccessMode
Possible return values for accessMode().
Definition: kconfigbase.h:133
QByteArray::data
char * data()
QIODevice::setTextModeEnabled
void setTextModeEnabled(bool enabled)
KEntryKey::bRaw
bool bRaw
Definition: kconfigdata.h:116
KLockFile::unlock
void unlock()
Release the lock.
Definition: klockfile_unix.cpp:487
KEntryMap::getEntryOption
bool getEntryOption(const ConstIterator &it, EntryOption option) const
QIODevice::write
qint64 write(const char *data, qint64 maxSize)
QString::fromLatin1
QString fromLatin1(const char *str, int size)
KConfigIniBackend::createEnclosing
void createEnclosing()
Create the enclosing object of the configuration object.
Definition: kconfigini.cpp:548
QHash::end
iterator end()
KConfigBackend::setSize
void setSize(qint64 sz)
Definition: kconfigbackend.cpp:118
KConfigBackend::ParseDefaults
entries should be marked as global
Definition: kconfigbackend.h:95
QFileInfo::absolutePath
QString absolutePath() const
QByteArray::size
int size() const
QObject::parent
QObject * parent() const
KEntryMap::EntryGlobal
Definition: kconfigdata.h:163
KConfigIniBackend::StringType
StringType
Definition: kconfigini_p.h:61
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
KEntry::bExpand
bool bExpand
Whether to apply dollar expansion or not.
Definition: kconfigdata.h:62
KConfigIniBackend::isWritable
bool isWritable() const
If isWritable() returns false, writeConfig() will always fail.
Definition: kconfigini.cpp:516
KComponentData
Per component data.
Definition: kcomponentdata.h:46
KConfigIniBackend::BufferFragment::isEmpty
bool isEmpty() const
Definition: bufferfragment_p.h:99
QByteArray::endsWith
bool endsWith(const QByteArray &ba) const
QFile::encodeName
QByteArray encodeName(const QString &fileName)
KEntryMap::EntryDefault
Definition: kconfigdata.h:168
QDir::mkpath
bool mkpath(const QString &dirPath) const
QDateTime
QDateTime::setTime_t
void setTime_t(uint seconds)
KConfigBackend::ParseExpansions
entries should be marked as default
Definition: kconfigbackend.h:96
QMap::remove
int remove(const Key &key)
KConfigIniBackend::writeConfig
bool writeConfig(const QByteArray &locale, KEntryMap &entryMap, WriteOptions options, const KComponentData &data)
Write the dirty entries to permanent storage.
Definition: kconfigini.cpp:380
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:22:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDECore

Skip menu "KDECore"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal