Merge lp:~ajalkane/ubuntu-filemanager-app/require-screenlock-password into lp:ubuntu-filemanager-app
- require-screenlock-password
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~ajalkane/ubuntu-filemanager-app/require-screenlock-password |
Merge into: | lp:ubuntu-filemanager-app |
Diff against target: |
902 lines (+574/-14) 15 files modified
README (+6/-4) debian/control (+12/-0) src/app/qml/filemanager.qml (+6/-0) src/app/qml/ui/AuthenticationDialog.qml (+80/-0) src/app/qml/ui/FolderListPage.qml (+29/-5) src/plugin/CMakeLists.txt (+1/-0) src/plugin/folderlistmodel/dirmodel.cpp (+92/-3) src/plugin/folderlistmodel/dirmodel.h (+11/-1) src/plugin/pamauthentication/CMakeLists.txt (+37/-0) src/plugin/pamauthentication/pamauthentication.cpp (+153/-0) src/plugin/pamauthentication/pamauthentication.h (+71/-0) src/plugin/pamauthentication/pamauthentication_plugin.cpp (+34/-0) src/plugin/pamauthentication/pamauthentication_plugin.h (+39/-0) src/plugin/pamauthentication/qmldir (+2/-0) ubuntu-filemanager-app.json (+1/-1) |
To merge this branch: | bzr merge lp:~ajalkane/ubuntu-filemanager-app/require-screenlock-password |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Needs Fixing | |
Ubuntu File Manager Developers | Pending | ||
Review via email: mp+229865@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-08-08.
Commit message
Only show files and allow operating in non-MTP folders unless password explicitly given.
Description of the change
Only show files and allow operating in non-MTP folders unless password explicitly given.
# Notes:
- Click package available for testing at: http://
- It seems querying the device security over D-BUS only works if "Passphrase" is selected. When choosing from "Swipe (no security)" into "4-digit passcode", then the call still returns "false". We're assuming this is a bug in the backend.
- Some operations need to be guarded against operating in non-MTP folders (deleting, renaming, pasting into non-allowed directory). That's implemented in this branch, but in the future it should be improved to show some error when the user tries to do such operations. But at least now nothing destructive should be possible even though File Manager silently refuses what's asked.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Nicholas Skaggs (nskaggs) wrote : | # |
Tests are failing due to missing depends
file://
Arto Jalkanen (ajalkane) wrote : | # |
> Tests are failing due to missing depends
>
> file://
> "com.ubuntu.
What's up with that? It gets packaged into the click package. Can you tell what's the place to fix this?
David Planella (dpm) wrote : | # |
That's probably because the branch does not package up the PAM plugin as a
.deb package. Jenkins runs the tests on the desktop, and expects to install
everything as a debian package. Let me have a quick look at it.
On Thu, Aug 7, 2014 at 5:36 PM, Arto Jalkanen <email address hidden> wrote:
> > Tests are failing due to missing depends
> >
> > file://
> > "com.ubuntu.
>
> What's up with that? It gets packaged into the click package. Can you tell
> what's the place to fix this?
> --
>
> https:/
> Your team Ubuntu File Manager Developers is requested to review the
> proposed merge of
> lp:~ajalkane/ubuntu-filemanager-app/require-screenlock-password into
> lp:ubuntu-filemanager-app.
>
David Planella (dpm) wrote : | # |
Arto, I've fixed this in a branch you can merge into yours, could you do a:
bzr merge lp:~dpm/ubuntu-filemanager-app/add-pamauth-packaging
Followed by a push? This should resolve the packaging dependency, but I'm guessing that the tests might need tweaking to press the button to show all files?
- 252. By Arto Jalkanen
-
PamAuthentication deb dependency.
Arto Jalkanen (ajalkane) wrote : | # |
> Arto, I've fixed this in a branch you can merge into yours, could you do a:
>
> bzr merge lp:~dpm/ubuntu-filemanager-app/add-pamauth-packaging
>
> Followed by a push? This should resolve the packaging dependency, but I'm
> guessing that the tests might need tweaking to press the button to show all
> files?
Thank you! I've done the merge and updated the branch.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:252
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Arto Jalkanen (ajalkane) wrote : | # |
> Followed by a push? This should resolve the packaging dependency, but I'm
> guessing that the tests might need tweaking to press the button to show all
> files?
This depends on if the test environment has UnityGreeter to answer the DBus queries about authentication required. If it has, and it's set to "Swipe unlock", then the tests might just work. Otherwise they no doubt have to be modified.
Nicholas Skaggs (nskaggs) wrote : | # |
Add qtdeclarative5-
David Planella (dpm) wrote : | # |
Argh, yes, I forgot to add the dependency. It should be just a one-line
change. Arto, I could prepare a branch, but I think it might be easier if
you just add the qtdeclarative5-
pamauthenticati
On Thu, Aug 7, 2014 at 9:39 PM, Nicholas Skaggs <
<email address hidden>> wrote:
> Add qtdeclarative5-
> ubuntu-
> --
>
> https:/
> Your team Ubuntu File Manager Developers is requested to review the
> proposed merge of
> lp:~ajalkane/ubuntu-filemanager-app/require-screenlock-password into
> lp:ubuntu-filemanager-app.
>
- 253. By Arto Jalkanen
-
Added pamauthentication plugin dependency to filemanager deb build.
Arto Jalkanen (ajalkane) wrote : | # |
> Argh, yes, I forgot to add the dependency. It should be just a one-line
> change. Arto, I could prepare a branch, but I think it might be easier if
> you just add the qtdeclarative5-
> pamauthenticati
Yes, I see what you mean. Added and updated.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:253
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
David Planella (dpm) wrote : | # |
Now I'm confused by the failing test. Did Jenkins not install the required package? Or perhaps I made a mistake in the packaging?
Arto Jalkanen (ajalkane) wrote : | # |
> Now I'm confused by the failing test. Did Jenkins not install the required
> package? Or perhaps I made a mistake in the packaging?
To me the depends blocks seem just the same as for placesmodel that is used without problems. Yet in the output for pamauthentication it shows this:
dpkg-gencontrol: warning: Depends field of package qtdeclarative5-
dpkg-gencontrol: warning: Depends field of package qtdeclarative5-
No idea why suddenly that doesn't work.
Nicholas Skaggs (nskaggs) wrote : | # |
Jenkins built the package alright, but look at what's inside it. Nothing.
Nicholas Skaggs (nskaggs) wrote : | # |
Download this zip and have a look at the package contents:
http://
David Planella (dpm) wrote : | # |
Argh, that's what happens when you do coding between phone calls. I tested
the package to build and have the right contents, but I bet I failed to
commit the .install file. I'll prepare another branch in about 1 h.
El dia 08/08/2014 0.24, "Nicholas Skaggs" <email address hidden>
va escriure:
> Download this zip and have a look at the package contents:
>
>
> http://
> --
>
> https:/
> Your team Ubuntu File Manager Developers is requested to review the
> proposed merge of
> lp:~ajalkane/ubuntu-filemanager-app/require-screenlock-password into
> lp:ubuntu-filemanager-app.
>
David Planella (dpm) wrote : | # |
Ok, fixed. Arto, could you do another 'bzr lp:~dpm/ubuntu-filemanager-app/add-pamauth-packaging', commit and push?
Arto Jalkanen (ajalkane) wrote : | # |
> Ok, fixed. Arto, could you do another 'bzr lp:~dpm/ubuntu-filemanager-app/add-
> pamauth-packaging', commit and push?
I'm at work so can't do that anytime soon, but I tried to do a merge proposal from launchpad and hopefully it goes well.
Unmerged revisions
Preview Diff
1 | === modified file 'README' |
2 | --- README 2014-04-26 06:35:52 +0000 |
3 | +++ README 2014-08-07 20:04:19 +0000 |
4 | @@ -8,7 +8,7 @@ |
5 | |
6 | Install the following build dependencies: |
7 | |
8 | - sudo apt-get install libtag1-dev |
9 | + sudo apt-get install libtag1-dev libpam0g-dev python3 |
10 | |
11 | Then open the CMakeLists.txt file in Qt Creator, and ensure that the kit |
12 | selected on the left sidebar (just above the green "Run" button) is "Desktop" |
13 | @@ -16,7 +16,9 @@ |
14 | ### For a device |
15 | |
16 | If you don't have one already, you'll need to create an armhf chroot to |
17 | -cross-compile the app. Here's how: |
18 | +cross-compile the app (also do this if you have an older armhf chroot, for |
19 | +example 14.04 and current target is 14.10. You can first delete the old target |
20 | +and then create a current one). Here's how: |
21 | |
22 | 1. In Qt Creator, open the CMakeLists.txt file |
23 | 2. Go to Tools > Options > Ubuntu > Click |
24 | @@ -26,7 +28,7 @@ |
25 | 4. Once created, you'll need to add the build dependencies for the app: |
26 | - Click on the Maintain button on your chroot |
27 | - On the terminal prompt that is started, type |
28 | - apt-get install libtag1-dev:armhf' |
29 | + apt-get install libtag1-dev:armhf libpam0g-dev:armhf python3 |
30 | - Close the terminal when the installation finishes |
31 | 5. Now you can either do a clean checkout and wait to be prompted by Qt Creator |
32 | to add the armhf kit, or alternatively: |
33 | @@ -112,7 +114,7 @@ |
34 | Run the following commands to manually install the click package (replace 0.5 |
35 | with the version of your package): |
36 | |
37 | - adb push /home/phablet com.ubuntu.filemanager_0.3_armhf.click |
38 | + adb push com.ubuntu.filemanager_0.3.latest_armhf.click /home/phablet/ |
39 | adb shell |
40 | sudo -H -u phablet pkcon install-local /home/phablet/com.ubuntu.filemanager_0.3_armhf.click |
41 | |
42 | |
43 | === modified file 'debian/control' |
44 | --- debian/control 2014-07-28 12:52:31 +0000 |
45 | +++ debian/control 2014-08-07 20:04:19 +0000 |
46 | @@ -9,6 +9,7 @@ |
47 | pkg-kde-tools, |
48 | python3-all, |
49 | libtag1-dev, |
50 | + libpam0g-dev, |
51 | Standards-Version: 3.9.5 |
52 | Section: misc |
53 | Homepage: https://launchpad.net/ubuntu-filemanager-app |
54 | @@ -22,6 +23,7 @@ |
55 | qtdeclarative5-hud1.0, |
56 | qtdeclarative5-nemo-qml-plugin-folderlistmodel, |
57 | qtdeclarative5-placesmodel0.1, |
58 | + qtdeclarative5-pamauthentication0.1, |
59 | qtdeclarative5-qtquick2-plugin, |
60 | qtdeclarative5-u1db1.0, |
61 | qtdeclarative5-ubuntu-ui-toolkit-plugin | qt-components-ubuntu, |
62 | @@ -52,6 +54,16 @@ |
63 | This package contains a plugin that enables QML apps to list and |
64 | modify a set of places (bookmarks) in the file system. |
65 | |
66 | +Package: qtdeclarative5-pamauthentication0.1 |
67 | +Architecture: any |
68 | +Multi-Arch: same |
69 | +Depends: ${misc:Depends}, |
70 | + ${shlibs:Depends}, |
71 | + ${misc:Pre-Depends}, |
72 | +Description: PAM authentication QML plugin |
73 | + This package contains a plugin that enables QML apps to do |
74 | + password authentication via the PAM API. |
75 | + |
76 | Package: ubuntu-filemanager-app-autopilot |
77 | Architecture: all |
78 | Depends: ${misc:Depends}, |
79 | |
80 | === modified file 'src/app/qml/filemanager.qml' |
81 | --- src/app/qml/filemanager.qml 2014-07-01 22:41:29 +0000 |
82 | +++ src/app/qml/filemanager.qml 2014-08-07 20:04:19 +0000 |
83 | @@ -23,6 +23,7 @@ |
84 | import U1db 1.0 as U1db |
85 | import Ubuntu.Content 0.1 |
86 | import com.ubuntu.PlacesModel 0.1 |
87 | +import com.ubuntu.PamAuthentication 0.1 |
88 | |
89 | import "ui" |
90 | |
91 | @@ -77,6 +78,11 @@ |
92 | id: userplaces |
93 | } |
94 | |
95 | + PamAuthentication { |
96 | + id: pamAuthentication |
97 | + serviceName: "filemanager" |
98 | + } |
99 | + |
100 | // HUD Actions |
101 | Action { |
102 | id: settingsAction |
103 | |
104 | === added file 'src/app/qml/ui/AuthenticationDialog.qml' |
105 | --- src/app/qml/ui/AuthenticationDialog.qml 1970-01-01 00:00:00 +0000 |
106 | +++ src/app/qml/ui/AuthenticationDialog.qml 2014-08-07 20:04:19 +0000 |
107 | @@ -0,0 +1,80 @@ |
108 | +/* |
109 | + * Copyright (C) 2014 Canonical Ltd |
110 | + * |
111 | + * This program is free software: you can redistribute it and/or modify |
112 | + * it under the terms of the GNU General Public License version 3 as |
113 | + * published by the Free Software Foundation. |
114 | + * |
115 | + * This program is distributed in the hope that it will be useful, |
116 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
117 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
118 | + * GNU General Public License for more details. |
119 | + * |
120 | + * You should have received a copy of the GNU General Public License |
121 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
122 | + * |
123 | + * Authored by: Arto Jalkanen <ajalkane@gmail.com> |
124 | + */ |
125 | +import QtQuick 2.0 |
126 | +import Ubuntu.Components 0.1 |
127 | +import Ubuntu.Components.Popups 0.1 |
128 | + |
129 | +Dialog { |
130 | + id: root |
131 | + |
132 | + title: i18n.tr("Authentication required") |
133 | + |
134 | + text: i18n.tr("Enter password:") |
135 | + |
136 | + signal passwordEntered(string password) |
137 | + |
138 | + Component.onCompleted: { |
139 | + passwordField.forceActiveFocus() |
140 | + } |
141 | + |
142 | + TextField { |
143 | + id: passwordField |
144 | + objectName: "inputField" |
145 | + |
146 | + placeholderText: i18n.tr("password") |
147 | + echoMode: TextInput.Password |
148 | + |
149 | + onAccepted: okButton.clicked(text) |
150 | + } |
151 | + |
152 | + Button { |
153 | + id: okButton |
154 | + objectName: "okButton" |
155 | + |
156 | + text: i18n.tr("Ok") |
157 | + |
158 | + onClicked: { |
159 | + console.log("Ok clicked with password " + passwordField.text) |
160 | + |
161 | + passwordEntered(passwordField.text) |
162 | + PopupUtils.close(root) |
163 | + } |
164 | + } |
165 | + |
166 | + Button { |
167 | + id: cancelButton |
168 | + objectName: "cancelButton" |
169 | + text: i18n.tr("Cancel") |
170 | + |
171 | + gradient: Gradient { |
172 | + GradientStop { |
173 | + position: 0 |
174 | + color: "gray" |
175 | + } |
176 | + |
177 | + GradientStop { |
178 | + position: 1 |
179 | + color: "lightgray" |
180 | + } |
181 | + } |
182 | + |
183 | + onClicked: { |
184 | + PopupUtils.close(root) |
185 | + } |
186 | + } |
187 | +} |
188 | |
189 | === modified file 'src/app/qml/ui/FolderListPage.qml' |
190 | --- src/app/qml/ui/FolderListPage.qml 2014-07-28 17:26:29 +0000 |
191 | +++ src/app/qml/ui/FolderListPage.qml 2014-08-07 20:04:19 +0000 |
192 | @@ -86,6 +86,7 @@ |
193 | id: pageModel |
194 | path: folderListPage.folder |
195 | enableExternalFSWatcher: true |
196 | + showNonMTPPaths: !pamAuthentication.requireAuthentication() |
197 | |
198 | // Properties to emulate a model entry for use by FileDetailsPopover |
199 | property bool isDir: true |
200 | @@ -355,21 +356,21 @@ |
201 | left: sidebar.right |
202 | right: parent.right |
203 | } |
204 | - height: fileSelectorMode ? bottomBarFileSelectorButtons.height : 0 |
205 | + height: bottomBarButtons.visible ? bottomBarButtons.height : 0 |
206 | visible: fileSelectorMode |
207 | - |
208 | } |
209 | |
210 | Row { |
211 | - id: bottomBarFileSelectorButtons |
212 | + id: bottomBarButtons |
213 | anchors.horizontalCenter: parent.horizontalCenter |
214 | anchors.bottom: bottomBar.bottom |
215 | spacing: units.gu(5) |
216 | - visible: fileSelectorMode |
217 | + visible: fileSelectorMode || !pageModel.showNonMTPPaths |
218 | |
219 | Button { |
220 | text: i18n.tr("Select") |
221 | enabled: selectionManager.counter > 0 |
222 | + visible: fileSelectorMode |
223 | onClicked: { |
224 | var selectedAbsPaths = selectionManager.selectedAbsFilePaths(); |
225 | // For now support only selection in filesystem |
226 | @@ -383,14 +384,37 @@ |
227 | } |
228 | Button { |
229 | text: i18n.tr("Cancel") |
230 | + visible: fileSelectorMode |
231 | onClicked: { |
232 | console.log("FileSelector cancelled") |
233 | cancelFileSelector() |
234 | } |
235 | } |
236 | + Button { |
237 | + text: i18n.tr("Unlock full access") |
238 | + visible: !pageModel.showNonMTPPaths |
239 | + onClicked: { |
240 | + console.log("Full access clicked") |
241 | + var authDialog = PopupUtils.open(Qt.resolvedUrl("AuthenticationDialog.qml"), |
242 | + folderListPage) |
243 | + |
244 | + authDialog.passwordEntered.connect(function(password) { |
245 | + if (pamAuthentication.validatePasswordToken(password)) { |
246 | + console.log("Authenticated for full access") |
247 | + pageModel.showNonMTPPaths = true |
248 | + } else { |
249 | + PopupUtils.open(Qt.resolvedUrl("NotifyDialog.qml"), folderListPage, |
250 | + { |
251 | + title: i18n.tr("Authentication failed") |
252 | + }) |
253 | + |
254 | + console.log("Could not authenticate") |
255 | + } |
256 | + }) |
257 | + } |
258 | + } |
259 | } |
260 | |
261 | - |
262 | FolderIconView { |
263 | id: folderIconView |
264 | |
265 | |
266 | === modified file 'src/plugin/CMakeLists.txt' |
267 | --- src/plugin/CMakeLists.txt 2014-06-21 21:59:52 +0000 |
268 | +++ src/plugin/CMakeLists.txt 2014-08-07 20:04:19 +0000 |
269 | @@ -6,3 +6,4 @@ |
270 | |
271 | add_subdirectory(folderlistmodel) |
272 | add_subdirectory(placesmodel) |
273 | +add_subdirectory(pamauthentication) |
274 | |
275 | === modified file 'src/plugin/folderlistmodel/dirmodel.cpp' |
276 | --- src/plugin/folderlistmodel/dirmodel.cpp 2014-06-17 21:41:59 +0000 |
277 | +++ src/plugin/folderlistmodel/dirmodel.cpp 2014-08-07 20:04:19 +0000 |
278 | @@ -61,13 +61,14 @@ |
279 | #include <QMetaType> |
280 | #include <QDateTime> |
281 | #include <QMimeType> |
282 | +#include <QStandardPaths> |
283 | |
284 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) |
285 | # include <QColor> |
286 | # include <QBrush> |
287 | #endif |
288 | |
289 | - |
290 | +#include <array> |
291 | |
292 | |
293 | |
294 | @@ -80,6 +81,26 @@ |
295 | |
296 | namespace { |
297 | QHash<QByteArray, int> roleMapping; |
298 | + QList<QString> mtpDirectories; |
299 | + |
300 | + std::array<QStandardPaths::StandardLocation, 5> mtpStandardLocations = { |
301 | + QStandardPaths::DocumentsLocation, |
302 | + QStandardPaths::DownloadLocation, |
303 | + QStandardPaths::MusicLocation, |
304 | + QStandardPaths::PicturesLocation, |
305 | + QStandardPaths::MoviesLocation |
306 | + }; |
307 | + |
308 | + void buildMTPDirectories() { |
309 | + mtpDirectories.clear(); |
310 | + foreach (const QStandardPaths::StandardLocation &standardLocation, mtpStandardLocations) { |
311 | + QStringList locations = QStandardPaths::standardLocations(standardLocation); |
312 | + |
313 | + foreach (const QString &location, locations) { |
314 | + mtpDirectories << location; |
315 | + } |
316 | + } |
317 | + } |
318 | } |
319 | |
320 | |
321 | @@ -106,6 +127,7 @@ |
322 | , mIsRecursive(false) |
323 | , mReadsMediaMetadata(false) |
324 | , mShowHiddenFiles(false) |
325 | + , mShowNonMTPPaths(true) |
326 | , mSortBy(SortByName) |
327 | , mSortOrder(SortAscending) |
328 | , mCompareFunction(0) |
329 | @@ -452,6 +474,28 @@ |
330 | } |
331 | } |
332 | |
333 | + |
334 | +bool DirModel::isMTPPath(const QString &path) const { |
335 | + if (mtpDirectories.isEmpty()) { |
336 | + buildMTPDirectories(); |
337 | + } |
338 | + foreach (const QString &mtpDirectory, mtpDirectories) { |
339 | + if (path == mtpDirectory) return true; |
340 | + // Returns true for any file/folder inside MTP directory |
341 | + if (path.startsWith(mtpDirectory + "/")) return true; |
342 | + } |
343 | + |
344 | + return false; |
345 | +} |
346 | + |
347 | +bool DirModel::allowAccess(const DirItemInfo &fi) const { |
348 | + return allowAccess(fi.absoluteFilePath()); |
349 | +} |
350 | + |
351 | +bool DirModel::allowAccess(const QString &absoluteFilePath) const { |
352 | + return mShowNonMTPPaths || isMTPPath(absoluteFilePath); |
353 | +} |
354 | + |
355 | void DirModel::onItemsAdded(const DirItemInfoList &newFiles) |
356 | { |
357 | #if DEBUG_MESSAGES |
358 | @@ -463,6 +507,7 @@ |
359 | mDirectoryContents.reserve(newFiles.count()) ; |
360 | } |
361 | foreach (const DirItemInfo &fi, newFiles) { |
362 | + if (!allowAccess(fi)) continue; |
363 | |
364 | bool doAdd = false; |
365 | foreach (const QString &nameFilter, mNameFilters) { |
366 | @@ -483,6 +528,11 @@ |
367 | |
368 | void DirModel::rm(const QStringList &paths) |
369 | { |
370 | + if (!allowAccess(mCurrentDir)) { |
371 | + qDebug() << Q_FUNC_INFO << "Access denied in current path" << mCurrentDir; |
372 | + return; |
373 | + } |
374 | + |
375 | //if current location is Trash only in the root is allowed to remove Items |
376 | if (mCurLocation->type() == LocationsFactory::TrashDisk) |
377 | { |
378 | @@ -509,13 +559,17 @@ |
379 | #if DEBUG_MESSAGES |
380 | qDebug() << Q_FUNC_INFO << this << "Renaming " << row << " to " << newName; |
381 | #endif |
382 | - |
383 | if (!IS_VALID_ROW(row)) { |
384 | WARN_ROW_OUT_OF_RANGE(row); |
385 | return false; |
386 | } |
387 | |
388 | const DirItemInfo &fi = mDirectoryContents.at(row); |
389 | + if (!allowAccess(mCurrentDir)) { |
390 | + qDebug() << Q_FUNC_INFO << "Access denied in current path" << mCurrentDir; |
391 | + return false; |
392 | + } |
393 | + |
394 | QString newFullFilename(fi.absolutePath() + QDir::separator() + newName); |
395 | |
396 | //QFile::rename() works for File and Dir |
397 | @@ -539,6 +593,11 @@ |
398 | |
399 | void DirModel::mkdir(const QString &newDir) |
400 | { |
401 | + if (!allowAccess(mCurrentDir)) { |
402 | + qDebug() << Q_FUNC_INFO << "Access denied in current path" << mCurrentDir; |
403 | + return; |
404 | + } |
405 | + |
406 | QDir dir(mCurrentDir); |
407 | bool retval = dir.mkdir(newDir); |
408 | if (!retval) { |
409 | @@ -748,12 +807,23 @@ |
410 | |
411 | void DirModel::cutPaths(const QStringList &items) |
412 | { |
413 | - mClipboard->cut(items, mCurrentDir); |
414 | + if (!allowAccess(mCurrentDir)) { |
415 | + qDebug() << Q_FUNC_INFO << "Access denied in current path" << mCurrentDir; |
416 | + return; |
417 | + } |
418 | + |
419 | + mClipboard->cut(items, mCurrentDir); |
420 | } |
421 | |
422 | |
423 | void DirModel::paste() |
424 | { |
425 | + // Restrict pasting if in restricted directory |
426 | + if (!allowAccess(mCurrentDir)) { |
427 | + qDebug() << Q_FUNC_INFO << "access not allowed, pasting not done" << mCurrentDir; |
428 | + return; |
429 | + } |
430 | + |
431 | ClipboardOperation operation; |
432 | QStringList items = mClipboard->paste(operation); |
433 | if (operation == ClipboardCut) |
434 | @@ -886,6 +956,9 @@ |
435 | */ |
436 | int DirModel::addItem(const DirItemInfo &fi) |
437 | { |
438 | + if (!allowAccess(fi)) { |
439 | + return -1; |
440 | + } |
441 | DirItemInfoList::Iterator it = qLowerBound(mDirectoryContents.begin(), |
442 | mDirectoryContents.end(), |
443 | fi, |
444 | @@ -990,6 +1063,22 @@ |
445 | } |
446 | } |
447 | |
448 | +bool DirModel::getShowNonMTPPaths() const |
449 | +{ |
450 | + return mShowNonMTPPaths; |
451 | +} |
452 | + |
453 | + |
454 | +void DirModel::setShowNonMTPPaths(bool show) |
455 | +{ |
456 | + if (show != mShowNonMTPPaths) |
457 | + { |
458 | + mShowNonMTPPaths = show; |
459 | + refresh(); |
460 | + emit showNonMTPPathsChanged(); |
461 | + } |
462 | +} |
463 | + |
464 | |
465 | void DirModel::toggleShowDirectories() |
466 | { |
467 | |
468 | === modified file 'src/plugin/folderlistmodel/dirmodel.h' |
469 | --- src/plugin/folderlistmodel/dirmodel.h 2014-06-17 21:41:59 +0000 |
470 | +++ src/plugin/folderlistmodel/dirmodel.h 2014-08-07 20:04:19 +0000 |
471 | @@ -179,6 +179,10 @@ |
472 | Q_PROPERTY(bool showHiddenFiles READ getShowHiddenFiles WRITE setShowHiddenFiles NOTIFY showHiddenFilesChanged) |
473 | bool getShowHiddenFiles() const; |
474 | |
475 | + // IMPROVE: should be something like onlyMTPPaths (negation of current property) since this affects also deleting/creating directories/moving etc. modifying operations |
476 | + Q_PROPERTY(bool showNonMTPPaths READ getShowNonMTPPaths WRITE setShowNonMTPPaths NOTIFY showNonMTPPathsChanged) |
477 | + bool getShowNonMTPPaths() const; |
478 | + |
479 | Q_ENUMS(SortBy) |
480 | enum SortBy |
481 | { |
482 | @@ -371,6 +375,7 @@ |
483 | void setFilterDirectories(bool filterDirectories); |
484 | void setShowDirectories(bool showDirectories); |
485 | void setShowHiddenFiles(bool show); |
486 | + void setShowNonMTPPaths(bool show); |
487 | void setSortBy(SortBy field); |
488 | void setSortOrder(SortOrder order); |
489 | void setEnabledExternalFSWatcher(bool enable); |
490 | @@ -402,6 +407,7 @@ |
491 | void progress(int curItem, int totalItems, int percent); |
492 | |
493 | void showHiddenFilesChanged(); |
494 | + void showNonMTPPathsChanged(); |
495 | void sortByChanged(); |
496 | void sortOrderChanged(); |
497 | void clipboardChanged(); |
498 | @@ -442,6 +448,7 @@ |
499 | |
500 | private: |
501 | bool mShowHiddenFiles; |
502 | + bool mShowNonMTPPaths; |
503 | SortBy mSortBy; |
504 | SortOrder mSortOrder; |
505 | CompareFunction mCompareFunction; |
506 | @@ -451,7 +458,6 @@ |
507 | LocationsFactory * mLocationFactory; |
508 | Location * mCurLocation; |
509 | |
510 | - |
511 | private: |
512 | FileSystemAction * m_fsAction; //!< it does file system recursive remove/copy/move |
513 | QString fileSize(qint64 size) const; |
514 | @@ -466,6 +472,10 @@ |
515 | virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; |
516 | friend class TestDirModel; |
517 | #endif |
518 | + |
519 | + bool allowAccess(const DirItemInfo &fi) const; |
520 | + bool allowAccess(const QString &path) const; |
521 | + bool isMTPPath(const QString &path) const; |
522 | }; |
523 | |
524 | |
525 | |
526 | === added directory 'src/plugin/pamauthentication' |
527 | === added file 'src/plugin/pamauthentication/CMakeLists.txt' |
528 | --- src/plugin/pamauthentication/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
529 | +++ src/plugin/pamauthentication/CMakeLists.txt 2014-08-07 20:04:19 +0000 |
530 | @@ -0,0 +1,37 @@ |
531 | +include_directories( |
532 | + ${CMAKE_CURRENT_SOURCE_DIR} |
533 | +) |
534 | + |
535 | +set(PLUGIN_DIR com/ubuntu/PamAuthentication) |
536 | + |
537 | +set(pamauthentication_SRCS |
538 | + pamauthentication.cpp |
539 | + pamauthentication.h |
540 | + pamauthentication_plugin.cpp |
541 | + pamauthentication_plugin.h |
542 | +) |
543 | + |
544 | +add_library(PamAuthentication MODULE |
545 | + ${pamauthentication_SRCS} |
546 | +) |
547 | + |
548 | +target_link_libraries(PamAuthentication pam) |
549 | + |
550 | +qt5_use_modules(PamAuthentication Gui Qml Quick Widgets DBus) |
551 | + |
552 | +# Copy the plugin, the qmldir file and other assets to the build dir for running in QtCreator |
553 | +if(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") |
554 | + add_custom_command(TARGET PamAuthentication POST_BUILD |
555 | + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
556 | + COMMENT "Creating plugin directory layout in the build directory" |
557 | + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/qmldir ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
558 | + COMMENT "Copying the qmldir file to the build directory" |
559 | + COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:PamAuthentication> ${CMAKE_CURRENT_BINARY_DIR}/../${PLUGIN_DIR} |
560 | + COMMENT "Copying the plugin binary to the build directory" |
561 | + ) |
562 | +endif(NOT "${CMAKE_CURRENT_SOURCE_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") |
563 | + |
564 | +# Install plugin file |
565 | +install(TARGETS PamAuthentication DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR}) |
566 | +install(FILES qmldir DESTINATION ${QT_IMPORTS_DIR}/${PLUGIN_DIR}) |
567 | + |
568 | |
569 | === added file 'src/plugin/pamauthentication/pamauthentication.cpp' |
570 | --- src/plugin/pamauthentication/pamauthentication.cpp 1970-01-01 00:00:00 +0000 |
571 | +++ src/plugin/pamauthentication/pamauthentication.cpp 2014-08-07 20:04:19 +0000 |
572 | @@ -0,0 +1,153 @@ |
573 | +/* |
574 | + * Copyright (C) 2014 Canonical Ltd |
575 | + * |
576 | + * This program is free software: you can redistribute it and/or modify |
577 | + * it under the terms of the GNU General Public License version 3 as |
578 | + * published by the Free Software Foundation. |
579 | + * |
580 | + * This program is distributed in the hope that it will be useful, |
581 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
582 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
583 | + * GNU General Public License for more details. |
584 | + * |
585 | + * You should have received a copy of the GNU General Public License |
586 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
587 | + * |
588 | + * Author : Arto Jalkanen <ajalkane@gmail.com> |
589 | + */ |
590 | + |
591 | +#include "pamauthentication.h" |
592 | + |
593 | +#include <QDebug> |
594 | +#include <QtDBus/QtDBus> |
595 | + |
596 | +#include <security/pam_appl.h> |
597 | + |
598 | +#define UNITYGREETER_SERVICE "com.canonical.UnityGreeter" |
599 | +#define UNITYGREETER_PATH "/list" |
600 | +#define UNITYGREETER_INTERFACE "com.canonical.UnityGreeter.List" |
601 | +#define UNITYGREETER_PROPERTY_ENTRY_IS_LOCKED "EntryIsLocked" |
602 | + |
603 | + |
604 | +PamAuthentication::PamAuthentication(QObject *parent) : |
605 | + QObject(parent) |
606 | +{ |
607 | + m_userLogin = qgetenv("USER"); |
608 | +} |
609 | + |
610 | +PamAuthentication::~PamAuthentication() { |
611 | + |
612 | +} |
613 | + |
614 | +void |
615 | +PamAuthentication::setServiceName(const QString &serviceName) { |
616 | + if (serviceName != m_serviceName) { |
617 | + m_serviceName = serviceName; |
618 | + emit serviceNameChanged(); |
619 | + } |
620 | +} |
621 | + |
622 | +bool |
623 | +PamAuthentication::requireAuthentication() { |
624 | + QDBusInterface dbus_iface(UNITYGREETER_SERVICE, UNITYGREETER_PATH, UNITYGREETER_INTERFACE); |
625 | + |
626 | + qDebug() << Q_FUNC_INFO << "Querying if authentication required"; |
627 | + |
628 | + if (!dbus_iface.isValid()) { |
629 | + qDebug() << Q_FUNC_INFO << "Not a valid dbus interface"; |
630 | + qDebug() << Q_FUNC_INFO << "Last error: " + dbus_iface.lastError().message(); |
631 | + // By default be cautious and require authentication |
632 | + return true; |
633 | + } |
634 | + QVariant isLockedVariant = dbus_iface.property(UNITYGREETER_PROPERTY_ENTRY_IS_LOCKED); |
635 | + if (isLockedVariant.isValid()) { |
636 | + bool replyValue = isLockedVariant.toBool(); |
637 | + qDebug() << Q_FUNC_INFO << "Return value" << replyValue; |
638 | + return isLockedVariant.toBool(); |
639 | + } else { |
640 | + qDebug() << Q_FUNC_INFO << "Failed getting value for EntryIsLocked property"; |
641 | + } |
642 | + // By default be cautious and require authentication |
643 | + return true; |
644 | +} |
645 | + |
646 | +bool |
647 | +PamAuthentication::validatePasswordToken(const QString &token) { |
648 | + pam_handle *pamHandle = 0; |
649 | + if (!initPam(&pamHandle)) { |
650 | + qDebug() << Q_FUNC_INFO << "Pam init failed"; |
651 | + return false; |
652 | + } |
653 | + |
654 | + m_passwordToken = token; |
655 | + |
656 | + int status = pam_authenticate(pamHandle, 0); |
657 | + qDebug() << Q_FUNC_INFO << "Pam authenticate status" << status; |
658 | + |
659 | + pam_end(pamHandle, status); |
660 | + |
661 | + m_passwordToken.clear(); |
662 | + |
663 | + return status == PAM_SUCCESS; |
664 | +} |
665 | + |
666 | +bool |
667 | +PamAuthentication::initPam(pam_handle **pamHandle) |
668 | +{ |
669 | + pam_conv conversation; |
670 | + conversation.conv = ConversationFunction; |
671 | + conversation.appdata_ptr = static_cast<void *>(this); |
672 | + |
673 | + return pam_start(m_serviceName.toLatin1().data(), m_userLogin.toLatin1().data(), |
674 | + &conversation, pamHandle) == PAM_SUCCESS; |
675 | +} |
676 | + |
677 | +int PamAuthentication::ConversationFunction(int num_msg, |
678 | + const pam_message **msg, |
679 | + pam_response **resp, |
680 | + void* appdata_ptr) |
681 | +{ |
682 | + if (num_msg <= 0) { |
683 | + return PAM_CONV_ERR; |
684 | + } |
685 | + |
686 | + *resp = static_cast<pam_response*>(calloc(num_msg, sizeof(pam_response))); |
687 | + |
688 | + PamAuthentication *self = static_cast<PamAuthentication*>(appdata_ptr); |
689 | + |
690 | + for (int count = 0; count < num_msg; ++count) { |
691 | + switch (msg[count]->msg_style) { |
692 | + case PAM_PROMPT_ECHO_ON: |
693 | + { |
694 | + qDebug() << Q_FUNC_INFO << "PAM_PROMPT_ECHO_ON received"; |
695 | + resp[count]->resp = strdup(self->m_passwordToken.toLatin1().data()); |
696 | + resp[count]->resp_retcode = 0; |
697 | + break; |
698 | + } |
699 | + case PAM_PROMPT_ECHO_OFF: |
700 | + { |
701 | + qDebug() << Q_FUNC_INFO << "PAM_PROMPT_ECHO_OFF received"; |
702 | + resp[count]->resp = strdup(self->m_passwordToken.toLatin1().data()); |
703 | + resp[count]->resp_retcode = 0; |
704 | + break; |
705 | + } |
706 | + case PAM_TEXT_INFO: |
707 | + { |
708 | + QString message(msg[count]->msg); |
709 | + qDebug() << Q_FUNC_INFO << "PAM_TEXT_INFO received" << message; |
710 | + break; |
711 | + } |
712 | + case PAM_AUTHTOK: |
713 | + { |
714 | + qDebug() << Q_FUNC_INFO << "PAM_AUTHTOK received"; |
715 | + break; |
716 | + } |
717 | + default: |
718 | + { |
719 | + qDebug() << Q_FUNC_INFO << "Other PAM msg received: " << msg[count]->msg_style; |
720 | + } |
721 | + } |
722 | + } |
723 | + |
724 | + return PAM_SUCCESS; |
725 | +} |
726 | |
727 | === added file 'src/plugin/pamauthentication/pamauthentication.h' |
728 | --- src/plugin/pamauthentication/pamauthentication.h 1970-01-01 00:00:00 +0000 |
729 | +++ src/plugin/pamauthentication/pamauthentication.h 2014-08-07 20:04:19 +0000 |
730 | @@ -0,0 +1,71 @@ |
731 | +/* |
732 | + * Copyright (C) 2014 Canonical Ltd |
733 | + * |
734 | + * This program is free software: you can redistribute it and/or modify |
735 | + * it under the terms of the GNU General Public License version 3 as |
736 | + * published by the Free Software Foundation. |
737 | + * |
738 | + * This program is distributed in the hope that it will be useful, |
739 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
740 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
741 | + * GNU General Public License for more details. |
742 | + * |
743 | + * You should have received a copy of the GNU General Public License |
744 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
745 | + * |
746 | + * Author : Arto Jalkanen <ajalkane@gmail.com> |
747 | + */ |
748 | + |
749 | +#ifndef PAMAUTHENTICATION_H |
750 | +#define PAMAUTHENTICATION_H |
751 | + |
752 | +#include <QObject> |
753 | +#include <QAbstractListModel> |
754 | +#include <QStandardPaths> |
755 | +#include <QSettings> |
756 | + |
757 | +// Forward declarations |
758 | +struct pam_handle; |
759 | +struct pam_message; |
760 | +struct pam_response; |
761 | + |
762 | +// TODO: documentation |
763 | +class PamAuthentication : public QObject |
764 | +{ |
765 | + Q_OBJECT |
766 | + |
767 | +public: |
768 | + explicit PamAuthentication(QObject *parent = 0); |
769 | + ~PamAuthentication(); |
770 | + |
771 | + Q_INVOKABLE bool requireAuthentication(); |
772 | + |
773 | + Q_INVOKABLE bool validatePasswordToken(const QString &token); |
774 | + |
775 | + Q_PROPERTY(QString serviceName READ serviceName WRITE setServiceName NOTIFY serviceNameChanged) |
776 | + inline const QString &serviceName() const { |
777 | + return m_serviceName; |
778 | + } |
779 | + |
780 | + void setServiceName(const QString &serviceName); |
781 | +signals: |
782 | + void serviceNameChanged(); |
783 | + |
784 | +public slots: |
785 | +private: |
786 | + static int ConversationFunction(int num_msg, |
787 | + const pam_message** msg, |
788 | + pam_response** resp, |
789 | + void* appdata_ptr); |
790 | + |
791 | + bool initPam(pam_handle **pamHandle); |
792 | + |
793 | + QString m_passwordToken; |
794 | + QString m_serviceName; |
795 | + QString m_userLogin; |
796 | +}; |
797 | + |
798 | +#endif // PAMAUTHENTICATION_H |
799 | + |
800 | + |
801 | + |
802 | |
803 | === added file 'src/plugin/pamauthentication/pamauthentication_plugin.cpp' |
804 | --- src/plugin/pamauthentication/pamauthentication_plugin.cpp 1970-01-01 00:00:00 +0000 |
805 | +++ src/plugin/pamauthentication/pamauthentication_plugin.cpp 2014-08-07 20:04:19 +0000 |
806 | @@ -0,0 +1,34 @@ |
807 | +/* |
808 | + * Copyright (C) 2014 Canonical Ltd |
809 | + * |
810 | + * This program is free software: you can redistribute it and/or modify |
811 | + * it under the terms of the GNU General Public License version 3 as |
812 | + * published by the Free Software Foundation. |
813 | + * |
814 | + * This program is distributed in the hope that it will be useful, |
815 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
816 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
817 | + * GNU General Public License for more details. |
818 | + * |
819 | + * You should have received a copy of the GNU General Public License |
820 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
821 | + * |
822 | + * Author : Arto Jalkanen <ajalkane@gmail.com> |
823 | + */ |
824 | + |
825 | +#include <QtQml> |
826 | +#include <QtQml/QQmlContext> |
827 | +#include "pamauthentication_plugin.h" |
828 | +#include "pamauthentication.h" |
829 | + |
830 | +void BackendPlugin::registerTypes(const char *uri) |
831 | +{ |
832 | + Q_ASSERT(uri == QLatin1String(QUOTES(PLUGIN_URI))); |
833 | + |
834 | + qmlRegisterType<PamAuthentication>(uri, 0, 1, "PamAuthentication"); |
835 | +} |
836 | + |
837 | +void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
838 | +{ |
839 | + QQmlExtensionPlugin::initializeEngine(engine, uri); |
840 | +} |
841 | |
842 | === added file 'src/plugin/pamauthentication/pamauthentication_plugin.h' |
843 | --- src/plugin/pamauthentication/pamauthentication_plugin.h 1970-01-01 00:00:00 +0000 |
844 | +++ src/plugin/pamauthentication/pamauthentication_plugin.h 2014-08-07 20:04:19 +0000 |
845 | @@ -0,0 +1,39 @@ |
846 | +/* |
847 | + * Copyright (C) 2014 Canonical Ltd |
848 | + * |
849 | + * This program is free software: you can redistribute it and/or modify |
850 | + * it under the terms of the GNU General Public License version 3 as |
851 | + * published by the Free Software Foundation. |
852 | + * |
853 | + * This program is distributed in the hope that it will be useful, |
854 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
855 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
856 | + * GNU General Public License for more details. |
857 | + * |
858 | + * You should have received a copy of the GNU General Public License |
859 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
860 | + * |
861 | + * Author : Arto Jalkanen <ajalkane@gmail.com> |
862 | + */ |
863 | + |
864 | +#ifndef PAMAUTHENTICATION_PLUGIN_H |
865 | +#define PAMAUTHENTICATION_PLUGIN_H |
866 | + |
867 | +#include <QtQml/QQmlEngine> |
868 | +#include <QtQml/QQmlExtensionPlugin> |
869 | + |
870 | +class BackendPlugin : public QQmlExtensionPlugin |
871 | +{ |
872 | + Q_OBJECT |
873 | + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") |
874 | + |
875 | +public: |
876 | + void registerTypes(const char *uri); |
877 | + void initializeEngine(QQmlEngine *engine, const char *uri); |
878 | +}; |
879 | +#endif // PAMAUTHENTICATION_PLUGIN_H |
880 | + |
881 | + |
882 | + |
883 | + |
884 | + |
885 | |
886 | === added file 'src/plugin/pamauthentication/qmldir' |
887 | --- src/plugin/pamauthentication/qmldir 1970-01-01 00:00:00 +0000 |
888 | +++ src/plugin/pamauthentication/qmldir 2014-08-07 20:04:19 +0000 |
889 | @@ -0,0 +1,2 @@ |
890 | +module com.ubuntu.PamAuthentication |
891 | +plugin PamAuthentication |
892 | |
893 | === modified file 'ubuntu-filemanager-app.json' |
894 | --- ubuntu-filemanager-app.json 2014-05-13 19:46:32 +0000 |
895 | +++ ubuntu-filemanager-app.json 2014-08-07 20:04:19 +0000 |
896 | @@ -5,4 +5,4 @@ |
897 | "content_exchange" |
898 | ], |
899 | "policy_version": 1 |
900 | -} |
901 | +} |
902 | \ No newline at end of file |
FAILED: Continuous integration, rev:251 91.189. 93.70:8080/ job/ubuntu- filemanager- app-ci/ 291/ 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 1327 91.189. 93.70:8080/ job/generic- mediumtests- utopic/ 1327/artifact/ work/output/ *zip*/output. zip 91.189. 93.70:8080/ job/ubuntu- filemanager- app-utopic- amd64-ci/ 89
http://
Executed test runs:
UNSTABLE: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.70:8080/ job/ubuntu- filemanager- app-ci/ 291/rebuild
http://