Merge lp:~ajalkane/ubuntu-filemanager-app/require-screenlock-password into lp:ubuntu-filemanager-app

Proposed by Arto Jalkanen
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
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://people.canonical.com/~dpm/click/com.ubuntu.filemanager_0.3.251_armhf.click
- 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.

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

Tests are failing due to missing depends

file:///usr/share/filemanager/qml/filemanager.qml:26:1: module "com.ubuntu.PamAuthentication" is not installed

Revision history for this message
Arto Jalkanen (ajalkane) wrote :

> Tests are failing due to missing depends
>
> file:///usr/share/filemanager/qml/filemanager.qml:26:1: module
> "com.ubuntu.PamAuthentication" is not installed

What's up with that? It gets packaged into the click package. Can you tell what's the place to fix this?

Revision history for this message
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:///usr/share/filemanager/qml/filemanager.qml:26:1: module
> > "com.ubuntu.PamAuthentication" is not installed
>
> What's up with that? It gets packaged into the click package. Can you tell
> what's the place to fix this?
> --
>
> https://code.launchpad.net/~ajalkane/ubuntu-filemanager-app/require-screenlock-password/+merge/229865
> 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.
>

Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
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.

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

Add qtdeclarative5-pamauthentication0.1 as a depends to ubuntu-filemanager-app. The autopilot package will pull from there.

Revision history for this message
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-
pamauthentication0.1 dependency to debian/control.

On Thu, Aug 7, 2014 at 9:39 PM, Nicholas Skaggs <
<email address hidden>> wrote:

> Add qtdeclarative5-pamauthentication0.1 as a depends to
> ubuntu-filemanager-app. The autopilot package will pull from there.
> --
>
> https://code.launchpad.net/~ajalkane/ubuntu-filemanager-app/require-screenlock-password/+merge/229865
> 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.

Revision history for this message
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-
> pamauthentication0.1 dependency to debian/control.

Yes, I see what you mean. Added and updated.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
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?

Revision history for this message
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-pamauthentication0.1: unknown substitution variable ${shlibs:Depends}
dpkg-gencontrol: warning: Depends field of package qtdeclarative5-pamauthentication0.1: unknown substitution variable ${misc:Pre-Depends}

No idea why suddenly that doesn't work.

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :

Jenkins built the package alright, but look at what's inside it. Nothing.

Revision history for this message
Nicholas Skaggs (nskaggs) wrote :
Revision history for this message
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://91.189.93.70:8080/job/generic-mediumtests-utopic/1409/artifact/work/output/*zip*/output.zip
> --
>
> https://code.launchpad.net/~ajalkane/ubuntu-filemanager-app/require-screenlock-password/+merge/229865
> 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.
>

Revision history for this message
David Planella (dpm) wrote :

Ok, fixed. Arto, could you do another 'bzr lp:~dpm/ubuntu-filemanager-app/add-pamauth-packaging', commit and push?

Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches