Merge lp:~saviq/qtubuntu/more-robust-desktop-parsing into lp:qtubuntu

Proposed by Michał Sawicz
Status: Superseded
Proposed branch: lp:~saviq/qtubuntu/more-robust-desktop-parsing
Merge into: lp:qtubuntu
Diff against target: 154 lines (+61/-18)
2 files modified
src/modules/application/application_manager.cc (+57/-16)
src/modules/application/application_manager.h (+4/-2)
To merge this branch: bzr merge lp:~saviq/qtubuntu/more-robust-desktop-parsing
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+176930@code.launchpad.net

This proposal has been superseded by a proposal from 2013-07-25.

Commit message

Make desktop file parsing more robust.

Ignore spaces around "=" and error out on malformed lines.

To post a comment you must log in.

Unmerged revisions

158. By Michał Sawicz

Also skip if just the key was provided.

157. By Michał Sawicz

Ignore spaces around "=" in .desktop files.

156. By Michał Sawicz

Scan for a [Desktop Entry] group, don't assume it's on the first line.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/modules/application/application_manager.cc'
2--- src/modules/application/application_manager.cc 2013-07-12 00:21:20 +0000
3+++ src/modules/application/application_manager.cc 2013-07-25 13:00:32 +0000
4@@ -181,16 +181,17 @@
5 this, desktopFile.toLatin1().data());
6 DASSERT(desktopFile != NULL);
7 const struct { const char* const name; int size; unsigned int flag; } kEntryNames[] = {
8- { "Name=", sizeof("Name=") - 1, 1 << DesktopData::kNameIndex },
9- { "Comment=", sizeof("Comment=") - 1, 1 << DesktopData::kCommentIndex },
10- { "Icon=", sizeof("Icon=") - 1, 1 << DesktopData::kIconIndex },
11- { "Exec=", sizeof("Exec=") - 1, 1 << DesktopData::kExecIndex },
12- { "X-Ubuntu-StageHint=", sizeof("X-Ubuntu-StageHint=") - 1, 1 << DesktopData::kStageHintIndex }
13+ { "Name", sizeof("Name") - 1, 1 << DesktopData::kNameIndex },
14+ { "Comment", sizeof("Comment") - 1, 1 << DesktopData::kCommentIndex },
15+ { "Icon", sizeof("Icon") - 1, 1 << DesktopData::kIconIndex },
16+ { "Exec", sizeof("Exec") - 1, 1 << DesktopData::kExecIndex },
17+ { "Path", sizeof("Path") - 1, 1 << DesktopData::kPathIndex },
18+ { "X-Ubuntu-StageHint", sizeof("X-Ubuntu-StageHint") - 1, 1 << DesktopData::kStageHintIndex }
19 };
20 const unsigned int kAllEntriesMask =
21 (1 << DesktopData::kNameIndex) | (1 << DesktopData::kCommentIndex)
22 | (1 << DesktopData::kIconIndex) | (1 << DesktopData::kExecIndex)
23- | (1 << DesktopData::kStageHintIndex);
24+ | (1 << DesktopData::kPathIndex) | (1 << DesktopData::kStageHintIndex);
25 const unsigned int kMandatoryEntriesMask =
26 (1 << DesktopData::kNameIndex) | (1 << DesktopData::kIconIndex)
27 | (1 << DesktopData::kExecIndex);
28@@ -206,11 +207,9 @@
29 }
30
31 // Validate "magic key" (standard group header).
32- if (file.readLine(buffer, kBufferSize) != -1) {
33- if (strncmp(buffer, "[Desktop Entry]", sizeof("[Desktop Entry]" - 1))) {
34- DLOG("not a desktop file");
35- return false;
36- }
37+ while (file.readLine(buffer, kBufferSize) != -1) {
38+ if (!strncmp(buffer, "[Desktop Entry]", sizeof("[Desktop Entry]" - 1)))
39+ break;
40 }
41
42 int length;
43@@ -223,17 +222,50 @@
44 DLOG("reached next group header, leaving loop");
45 break;
46 }
47+ bool validLine = true;
48 // Lookup entries ignoring duplicates if any.
49 for (int i = 0; i < kEntriesCount; i++) {
50 if (!strncmp(buffer, kEntryNames[i].name, kEntryNames[i].size)) {
51 if (~entryFlags & kEntryNames[i].flag) {
52+ int keyLength = kEntryNames[i].size;
53 buffer[length-1] = '\0';
54- entries_[i] = QString::fromLatin1(&buffer[kEntryNames[i].size]);
55+
56+ if (length == keyLength + 1) {
57+ validLine = false;
58+ break;
59+ }
60+
61+ if ((const char)buffer[keyLength] != ' ' && (const char)buffer[keyLength] != '=') {
62+ // Skip, not the key we're looking for.
63+ continue;
64+ }
65+
66+ bool gotEqual = false;
67+ while(keyLength < length) {
68+ if ((const char)buffer[keyLength] == ' ') {
69+ // Ignore spaces.
70+ } else if ((const char)buffer[keyLength] == '=') {
71+ gotEqual = true;
72+ } else {
73+ break;
74+ }
75+ keyLength++;
76+ }
77+ if (!gotEqual) {
78+ validLine = false;
79+ break;
80+ }
81+ entries_[i] = QString::fromLatin1(&buffer[keyLength]);
82 entryFlags |= kEntryNames[i].flag;
83+ DLOG("Found entry for %s: %s", kEntryNames[i].name, entries_[i].toLatin1().data());
84 break;
85 }
86 }
87 }
88+ if (!validLine) {
89+ DLOG("Malformed .desktop file entry, ignoring: %s", buffer);
90+ continue;
91+ }
92 // Stop when matching the right number of entries.
93 if (entryFlags == kAllEntriesMask) {
94 break;
95@@ -243,11 +275,12 @@
96
97 // Check that the mandatory entries are set.
98 if ((entryFlags & kMandatoryEntriesMask) == kMandatoryEntriesMask) {
99- DLOG("loaded desktop file with name='%s', comment='%s', icon='%s', exec='%s', stagehint='%s'",
100+ DLOG("loaded desktop file with name='%s', comment='%s', icon='%s', exec='%s', path='%s', stagehint='%s'",
101 entries_[DesktopData::kNameIndex].toLatin1().data(),
102 entries_[DesktopData::kCommentIndex].toLatin1().data(),
103 entries_[DesktopData::kIconIndex].toLatin1().data(),
104 entries_[DesktopData::kExecIndex].toLatin1().data(),
105+ entries_[DesktopData::kPathIndex].toLatin1().data(),
106 entries_[DesktopData::kStageHintIndex].toLatin1().data());
107 return true;
108 } else {
109@@ -603,11 +636,19 @@
110 // Start process.
111 bool result;
112 qint64 pid = 0;
113- struct passwd* passwd = getpwuid(getuid());
114- DLOG("current working directory: '%s'", passwd ? passwd->pw_dir : "/");
115+ QString path = "/";
116+ // respect Path from .desktop file
117+ if (desktopData->path() != "") {
118+ path = desktopData->path();
119+ } else {
120+ struct passwd* passwd = getpwuid(getuid());
121+ if (passwd)
122+ path = passwd->pw_dir;
123+ }
124+ DLOG("current working directory: '%s'", path.toLatin1().data());
125 QByteArray envSetAppId = QString("APP_ID=%1").arg(appId).toLocal8Bit();
126 putenv(envSetAppId.data()); // envSetAppId must be available and unmodified until the env var is unset
127- result = QProcess::startDetached(exec, arguments, QString(passwd ? passwd->pw_dir : "/"), &pid);
128+ result = QProcess::startDetached(exec, arguments, path, &pid);
129 QByteArray envClearAppId = QString("APP_ID").toLocal8Bit();
130 putenv(envClearAppId.data()); // now it's safe to deallocate envSetAppId.
131 DLOG_IF(result == false, "process failed to start");
132
133=== modified file 'src/modules/application/application_manager.h'
134--- src/modules/application/application_manager.h 2013-05-29 15:50:52 +0000
135+++ src/modules/application/application_manager.h 2013-07-25 13:00:32 +0000
136@@ -44,6 +44,7 @@
137 QString comment() const { return entries_[kCommentIndex]; }
138 QString icon() const { return entries_[kIconIndex]; }
139 QString exec() const { return entries_[kExecIndex]; }
140+ QString path() const { return entries_[kPathIndex]; }
141 QString stageHint() const { return entries_[kStageHintIndex]; }
142 bool loaded() const { return loaded_; }
143
144@@ -52,8 +53,9 @@
145 kCommentIndex = 1,
146 kIconIndex = 2,
147 kExecIndex = 3,
148- kStageHintIndex = 4,
149- kNumberOfEntries = 5;
150+ kPathIndex = 4,
151+ kStageHintIndex = 5,
152+ kNumberOfEntries = 6;
153
154 bool loadDesktopFile(QString desktopFile);
155

Subscribers

People subscribed via source and target branches