~ubuntu-branches/ubuntu/wily/kid3/wily-proposed

« back to all changes in this revision

Viewing changes to src/core/utils/movetotrash.cpp

  • Committer: Package Import Robot
  • Author(s): Ana Beatriz Guerrero Lopez, Patrick Matthäi, Ana Beatriz Guerrero Lopez
  • Date: 2011-11-13 16:34:13 UTC
  • mfrom: (1.1.13) (2.1.11 sid)
  • Revision ID: package-import@ubuntu.com-20111113163413-5y0anlc4dqf511uh
Tags: 2.0.1-1
* New upstream release.

[ Patrick Matthäi ]
* Adjust build system.
* Add build dependency xsltproc.

[ Ana Beatriz Guerrero Lopez ]
* Some more adjustments to the build system taken from upstream's deb/
* directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * \file movetotrash.cpp
 
3
 * Move file or directory to trash.
 
4
 *
 
5
 * \b Project: Kid3
 
6
 * \author Urs Fleisch
 
7
 * \date 22 Aug 2011
 
8
 *
 
9
 * Copyright (C) 2011  Urs Fleisch
 
10
 *
 
11
 * This file is part of Kid3.
 
12
 *
 
13
 * Kid3 is free software; you can redistribute it and/or modify
 
14
 * it under the terms of the GNU General Public License as published by
 
15
 * the Free Software Foundation; either version 2 of the License, or
 
16
 * (at your option) any later version.
 
17
 *
 
18
 * Kid3 is distributed in the hope that it will be useful,
 
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
 * GNU General Public License for more details.
 
22
 *
 
23
 * You should have received a copy of the GNU General Public License
 
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
25
 */
 
26
 
 
27
#include "movetotrash.h"
 
28
#include <QFileInfo>
 
29
#include "config.h"
 
30
 
 
31
#ifdef Q_OS_WIN32  
 
32
 
 
33
#include <QVector>
 
34
#include <windef.h>
 
35
#include <winbase.h>
 
36
#include <shellapi.h>
 
37
 
 
38
bool Utils::moveToTrash(const QString& path)
 
39
{
 
40
  typedef int (WINAPI *SHFileOperationW_t)(LPSHFILEOPSTRUCTW);
 
41
  HMODULE hshell32 = GetModuleHandleA("shell32.dll");
 
42
  SHFileOperationW_t pSHFileOperationW = reinterpret_cast<SHFileOperationW_t>(
 
43
        GetProcAddress(hshell32, "SHFileOperationW"));
 
44
  if (!pSHFileOperationW) {
 
45
    // SHFileOperationW is only available since Windows XP.
 
46
    return false;
 
47
  }
 
48
 
 
49
  QFileInfo fi(path);
 
50
  const QString absPath(fi.absoluteFilePath());
 
51
 
 
52
  QVector<WCHAR> from(absPath.length() + 2);
 
53
  int i;
 
54
  for (i = 0; i < absPath.length(); i++) {
 
55
    from[i] = absPath.at(i).unicode();
 
56
  }
 
57
  from[i++] = 0;
 
58
  from[i++] = 0;
 
59
 
 
60
  SHFILEOPSTRUCTW fileOp;
 
61
  fileOp.hwnd = 0;
 
62
  fileOp.wFunc = FO_DELETE;
 
63
  fileOp.pFrom = from.data();
 
64
  fileOp.pTo = 0;
 
65
  fileOp.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
 
66
  fileOp.fAnyOperationsAborted = 0;
 
67
  fileOp.hNameMappings = 0;
 
68
  fileOp.lpszProgressTitle = 0;
 
69
  return pSHFileOperationW(&fileOp) == 0;
 
70
}
 
71
 
 
72
#elif defined Q_OS_MAC
 
73
 
 
74
#include <CoreServices/CoreServices.h>
 
75
 
 
76
bool Utils::moveToTrash(const QString& path)
 
77
{
 
78
  QFileInfo fi(path);
 
79
  const QString absPath(fi.absoluteFilePath());
 
80
  FSRef fsRef;
 
81
  OSErr err = FSPathMakeRefWithOptions(
 
82
    reinterpret_cast<const UInt8*>(
 
83
      QFile::encodeName(absPath).constData()),
 
84
    kFSPathMakeRefDoNotFollowLeafSymlink, &fsRef, 0);
 
85
  if (err != noErr)
 
86
    return false;
 
87
 
 
88
  return FSMoveObjectToTrashSync(&fsRef, 0, kFSFileOperationDefaultOptions) == noErr;
 
89
}
 
90
 
 
91
#elif defined CONFIG_USE_KDE
 
92
 
 
93
#include <kurl.h>
 
94
#include <kio/copyjob.h>
 
95
#include <kio/netaccess.h>
 
96
 
 
97
bool Utils::moveToTrash(const QString& path)
 
98
{
 
99
  KUrl src;
 
100
  src.setPath(path);
 
101
  KIO::Job* job = KIO::trash(src);
 
102
  return KIO::NetAccess::synchronousRun(job, 0);
 
103
}
 
104
 
 
105
#else
 
106
 
 
107
/*
 
108
 * Implemented according to Desktop Trash Can Specification at
 
109
 * http://www.freedesktop.org/wiki/Specifications/trash-spec
 
110
 */
 
111
 
 
112
#include <QDir>
 
113
#include <QDateTime>
 
114
#include <QTextStream>
 
115
#include <stdlib.h>
 
116
#include <stdio.h>
 
117
#include <sys/types.h>
 
118
#include <sys/stat.h>
 
119
#include <unistd.h>
 
120
#ifdef HAVE_MNTENT_H
 
121
#include <mntent.h>
 
122
#endif
 
123
 
 
124
namespace {
 
125
 
 
126
bool moveToTrashDir(const QFileInfo& fi, const QString& trashDir)
 
127
{
 
128
  QString absPath(fi.absoluteFilePath());
 
129
  QString fileName(fi.fileName());
 
130
  QString filesPath(trashDir + "/files");
 
131
  QString infoPath(trashDir + "/info");
 
132
  QString baseName(fi.baseName());
 
133
  QString suffix(fi.completeSuffix());
 
134
  QString destName(fileName);
 
135
  int counter = 1;
 
136
  while (QFile::exists(filesPath + "/" + destName) ||
 
137
         QFile::exists(infoPath + "/" + destName + ".trashinfo")) {
 
138
    ++counter;
 
139
    destName = QString("%1.%2.%3").arg(baseName).arg(counter).arg(suffix);
 
140
  }
 
141
  if (!(QDir(filesPath).exists() ||
 
142
        QDir().mkpath(filesPath)) ||
 
143
      !(QDir(infoPath).exists() ||
 
144
        QDir().mkpath(infoPath)))
 
145
    return false;
 
146
 
 
147
  QFile file(infoPath + "/" + destName + ".trashinfo");
 
148
  if (!file.open(QIODevice::WriteOnly))
 
149
    return false;
 
150
  QTextStream stream(&file);
 
151
  stream << QString("[Trash Info]\nPath=%1\nDeletionDate=%2\n").
 
152
    arg(absPath).
 
153
    arg(QDateTime::currentDateTime().toString(Qt::ISODate));
 
154
  file.close();
 
155
  return QDir().rename(absPath, filesPath + "/" + destName);
 
156
}
 
157
 
 
158
bool findMountPoint(dev_t dev, QString& mountPoint)
 
159
{
 
160
#ifdef HAVE_MNTENT_H
 
161
  if (FILE* fp = ::setmntent("/proc/mounts", "r")) {
 
162
    struct stat st;
 
163
    struct mntent* mnt;
 
164
    while ((mnt = ::getmntent(fp)) != 0) {
 
165
      if (::stat(mnt->mnt_dir, &st) != 0) {
 
166
        continue;
 
167
      }
 
168
 
 
169
      if (st.st_dev == dev) {
 
170
        ::endmntent(fp);
 
171
        mountPoint = mnt->mnt_dir;
 
172
        return true;
 
173
      }
 
174
    }
 
175
    ::endmntent(fp);
 
176
  }
 
177
#endif
 
178
  return false;
 
179
}
 
180
 
 
181
bool findExtVolumeTrash(const QString& volumeRoot, QString& trashDir)
 
182
{
 
183
  struct stat st;
 
184
  trashDir = volumeRoot + "/.Trash";
 
185
  uid_t uid = ::getuid();
 
186
  if (QDir(trashDir).exists() &&
 
187
      ::lstat(trashDir.toLocal8Bit().data(), &st) == 0 &&
 
188
      (S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) && (st.st_mode & S_ISVTX))) {
 
189
    trashDir += QString("/%1").arg(uid);
 
190
  } else {
 
191
    trashDir += QString("-%1").arg(uid);
 
192
  }
 
193
  if (QDir(trashDir).exists() ||
 
194
      QDir().mkpath(trashDir)) {
 
195
    return true;
 
196
  }
 
197
  return false;
 
198
}
 
199
 
 
200
} // anonymous namespace
 
201
 
 
202
bool Utils::moveToTrash(const QString& path)
 
203
{
 
204
  QFileInfo fi(path);
 
205
  const QString absPath(fi.absoluteFilePath());
 
206
 
 
207
  if (!fi.exists() || !fi.isWritable())
 
208
    return false;
 
209
 
 
210
  struct stat pathStat;
 
211
  struct stat trashStat;
 
212
  if (::lstat(QFile::encodeName(absPath).constData(), &pathStat) != 0 ||
 
213
      ::lstat(QFile::encodeName(QDir::homePath()).constData(), &trashStat) != 0)
 
214
    return false;
 
215
 
 
216
  QString topDir;
 
217
  QString trashDir;
 
218
  if (pathStat.st_dev == trashStat.st_dev) {
 
219
    char* xdhEnv = ::getenv("XDG_DATA_HOME");
 
220
    topDir = xdhEnv ? QString(xdhEnv) : QDir::homePath() + "/.local/share";
 
221
    trashDir = topDir + "/Trash";
 
222
  } else if (!(findMountPoint(pathStat.st_dev, topDir) &&
 
223
               findExtVolumeTrash(topDir, trashDir))) {
 
224
    return false;
 
225
  }
 
226
  return moveToTrashDir(fi, trashDir);
 
227
}
 
228
 
 
229
#endif