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

ark

  • sources
  • kde-4.14
  • kdeutils
  • ark
  • kerfuffle
cliinterface.cpp
Go to the documentation of this file.
1 /*
2  * ark -- archiver for the KDE project
3  *
4  * Copyright (C) 2009 Harald Hvaal <haraldhv@stud.ntnu.no>
5  * Copyright (C) 2009-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "cliinterface.h"
30 #include "queries.h"
31 
32 #ifdef Q_OS_WIN
33 # include <KProcess>
34 #else
35 # include <KPtyDevice>
36 # include <KPtyProcess>
37 #endif
38 
39 #include <KStandardDirs>
40 #include <KDebug>
41 #include <KLocale>
42 
43 #include <QApplication>
44 #include <QDateTime>
45 #include <QDir>
46 #include <QEventLoop>
47 #include <QFile>
48 #include <QProcess>
49 #include <QThread>
50 #include <QTimer>
51 
52 namespace Kerfuffle
53 {
54 CliInterface::CliInterface(QObject *parent, const QVariantList & args)
55  : ReadWriteArchiveInterface(parent, args),
56  m_process(0),
57  m_listEmptyLines(false),
58  m_abortingOperation(false)
59 {
60  //because this interface uses the event loop
61  setWaitForFinishedSignal(true);
62 
63  if (QMetaType::type("QProcess::ExitStatus") == 0) {
64  qRegisterMetaType<QProcess::ExitStatus>("QProcess::ExitStatus");
65  }
66 }
67 
68 void CliInterface::cacheParameterList()
69 {
70  m_param = parameterList();
71  Q_ASSERT(m_param.contains(ExtractProgram));
72  Q_ASSERT(m_param.contains(ListProgram));
73  Q_ASSERT(m_param.contains(PreservePathSwitch));
74  Q_ASSERT(m_param.contains(FileExistsExpression));
75  Q_ASSERT(m_param.contains(FileExistsInput));
76 }
77 
78 CliInterface::~CliInterface()
79 {
80  Q_ASSERT(!m_process);
81 }
82 
83 void CliInterface::setListEmptyLines(bool emptyLines)
84 {
85  m_listEmptyLines = emptyLines;
86 }
87 
88 bool CliInterface::list()
89 {
90  cacheParameterList();
91  m_operationMode = List;
92 
93  QStringList args = m_param.value(ListArgs).toStringList();
94  substituteListVariables(args);
95 
96  if (!runProcess(m_param.value(ListProgram).toStringList(), args)) {
97  failOperation();
98  return false;
99  }
100 
101  return true;
102 }
103 
104 bool CliInterface::copyFiles(const QList<QVariant> & files, const QString & destinationDirectory, ExtractionOptions options)
105 {
106  kDebug();
107  cacheParameterList();
108 
109  m_operationMode = Copy;
110 
111  //start preparing the argument list
112  QStringList args = m_param.value(ExtractArgs).toStringList();
113 
114  //now replace the various elements in the list
115  for (int i = 0; i < args.size(); ++i) {
116  QString argument = args.at(i);
117  kDebug() << "Processing argument " << argument;
118 
119  if (argument == QLatin1String( "$Archive" )) {
120  args[i] = filename();
121  }
122 
123  if (argument == QLatin1String( "$PreservePathSwitch" )) {
124  QStringList replacementFlags = m_param.value(PreservePathSwitch).toStringList();
125  Q_ASSERT(replacementFlags.size() == 2);
126 
127  bool preservePaths = options.value(QLatin1String( "PreservePaths" )).toBool();
128  QString theReplacement;
129  if (preservePaths) {
130  theReplacement = replacementFlags.at(0);
131  } else {
132  theReplacement = replacementFlags.at(1);
133  }
134 
135  if (theReplacement.isEmpty()) {
136  args.removeAt(i);
137  --i; //decrement to compensate for the variable we removed
138  } else {
139  //but in this case we don't have to decrement, we just
140  //replace it
141  args[i] = theReplacement;
142  }
143  }
144 
145  if (argument == QLatin1String( "$PasswordSwitch" )) {
146  //if the PasswordSwitch argument has been added, we at least
147  //assume that the format of the switch has been added as well
148  Q_ASSERT(m_param.contains(PasswordSwitch));
149 
150  //we will decrement i afterwards
151  args.removeAt(i);
152 
153  //if we get a hint about this being a password protected archive, ask about
154  //the password in advance.
155  if ((options.value(QLatin1String("PasswordProtectedHint")).toBool()) &&
156  (password().isEmpty())) {
157  kDebug() << "Password hint enabled, querying user";
158 
159  Kerfuffle::PasswordNeededQuery query(filename());
160  emit userQuery(&query);
161  query.waitForResponse();
162 
163  if (query.responseCancelled()) {
164  failOperation();
165  return false;
166  }
167  setPassword(query.password());
168  }
169 
170  QString pass = password();
171 
172  if (!pass.isEmpty()) {
173  QStringList theSwitch = m_param.value(PasswordSwitch).toStringList();
174  for (int j = 0; j < theSwitch.size(); ++j) {
175  //get the argument part
176  QString newArg = theSwitch.at(j);
177 
178  //substitute the $Path
179  newArg.replace(QLatin1String( "$Password" ), pass);
180 
181  //put it in the arg list
182  args.insert(i + j, newArg);
183  ++i;
184 
185  }
186  }
187  --i; //decrement to compensate for the variable we replaced
188  }
189 
190  if (argument == QLatin1String( "$RootNodeSwitch" )) {
191  //if the RootNodeSwitch argument has been added, we at least
192  //assume that the format of the switch has been added as well
193  Q_ASSERT(m_param.contains(RootNodeSwitch));
194 
195  //we will decrement i afterwards
196  args.removeAt(i);
197 
198  QString rootNode;
199  if (options.contains(QLatin1String( "RootNode" ))) {
200  rootNode = options.value(QLatin1String( "RootNode" )).toString();
201  kDebug() << "Set root node " << rootNode;
202  }
203 
204  if (!rootNode.isEmpty()) {
205  QStringList theSwitch = m_param.value(RootNodeSwitch).toStringList();
206  for (int j = 0; j < theSwitch.size(); ++j) {
207  //get the argument part
208  QString newArg = theSwitch.at(j);
209 
210  //substitute the $Path
211  newArg.replace(QLatin1String( "$Path" ), rootNode);
212 
213  //put it in the arg list
214  args.insert(i + j, newArg);
215  ++i;
216 
217  }
218  }
219  --i; //decrement to compensate for the variable we replaced
220  }
221 
222  if (argument == QLatin1String( "$Files" )) {
223  args.removeAt(i);
224  for (int j = 0; j < files.count(); ++j) {
225  args.insert(i + j, escapeFileName(files.at(j).toString()));
226  ++i;
227  }
228  --i;
229  }
230  }
231 
232  kDebug() << "Setting current dir to " << destinationDirectory;
233  QDir::setCurrent(destinationDirectory);
234 
235  if (!runProcess(m_param.value(ExtractProgram).toStringList(), args)) {
236  failOperation();
237  return false;
238  }
239 
240  return true;
241 }
242 
243 bool CliInterface::addFiles(const QStringList & files, const CompressionOptions& options)
244 {
245  cacheParameterList();
246 
247  m_operationMode = Add;
248 
249  const QString globalWorkDir = options.value(QLatin1String( "GlobalWorkDir" )).toString();
250  const QDir workDir = globalWorkDir.isEmpty() ? QDir::current() : QDir(globalWorkDir);
251  if (!globalWorkDir.isEmpty()) {
252  kDebug() << "GlobalWorkDir is set, changing dir to " << globalWorkDir;
253  QDir::setCurrent(globalWorkDir);
254  }
255 
256  //start preparing the argument list
257  QStringList args = m_param.value(AddArgs).toStringList();
258 
259  //now replace the various elements in the list
260  for (int i = 0; i < args.size(); ++i) {
261  const QString argument = args.at(i);
262  kDebug() << "Processing argument " << argument;
263 
264  if (argument == QLatin1String( "$Archive" )) {
265  args[i] = filename();
266  }
267 
268  if (argument == QLatin1String( "$Files" )) {
269  args.removeAt(i);
270  for (int j = 0; j < files.count(); ++j) {
271  // #191821: workDir must be used instead of QDir::current()
272  // so that symlinks aren't resolved automatically
273  // TODO: this kind of call should be moved upwards in the
274  // class hierarchy to avoid code duplication
275  const QString relativeName =
276  workDir.relativeFilePath(files.at(j));
277 
278  args.insert(i + j, relativeName);
279  ++i;
280  }
281  --i;
282  }
283  }
284 
285  if (!runProcess(m_param.value(AddProgram).toStringList(), args)) {
286  failOperation();
287  return false;
288  }
289 
290  return true;
291 }
292 
293 bool CliInterface::deleteFiles(const QList<QVariant> & files)
294 {
295  cacheParameterList();
296  m_operationMode = Delete;
297 
298  //start preparing the argument list
299  QStringList args = m_param.value(DeleteArgs).toStringList();
300 
301  //now replace the various elements in the list
302  for (int i = 0; i < args.size(); ++i) {
303  QString argument = args.at(i);
304  kDebug() << "Processing argument " << argument;
305 
306  if (argument == QLatin1String( "$Archive" )) {
307  args[i] = filename();
308  } else if (argument == QLatin1String( "$Files" )) {
309  args.removeAt(i);
310  for (int j = 0; j < files.count(); ++j) {
311  args.insert(i + j, escapeFileName(files.at(j).toString()));
312  ++i;
313  }
314  --i;
315  }
316  }
317 
318  m_removedFiles = files;
319 
320  if (!runProcess(m_param.value(DeleteProgram).toStringList(), args)) {
321  failOperation();
322  return false;
323  }
324 
325  return true;
326 }
327 
328 bool CliInterface::runProcess(const QStringList& programNames, const QStringList& arguments)
329 {
330  QString programPath;
331  for (int i = 0; i < programNames.count(); i++) {
332  programPath = KStandardDirs::findExe(programNames.at(i));
333  if (!programPath.isEmpty())
334  break;
335  }
336  if (programPath.isEmpty()) {
337  const QString names = programNames.join(QLatin1String(", "));
338  emit error(i18ncp("@info", "Failed to locate program <filename>%2</filename> on disk.",
339  "Failed to locate programs <filename>%2</filename> on disk.", programNames.count(), names));
340  emit finished(false);
341  return false;
342  }
343 
344  kDebug() << "Executing" << programPath << arguments;
345 
346  if (m_process) {
347  m_process->waitForFinished();
348  delete m_process;
349  }
350 
351 #ifdef Q_OS_WIN
352  m_process = new KProcess;
353 #else
354  m_process = new KPtyProcess;
355  m_process->setPtyChannels(KPtyProcess::StdinChannel);
356  QEventLoop loop;
357  connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), &loop, SLOT(quit()), Qt::DirectConnection);
358 #endif
359 
360  m_process->setOutputChannelMode(KProcess::MergedChannels);
361  m_process->setNextOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered | QIODevice::Text);
362  m_process->setProgram(programPath, arguments);
363 
364  connect(m_process, SIGNAL(readyReadStandardOutput()), SLOT(readStdout()), Qt::DirectConnection);
365  connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(processFinished(int,QProcess::ExitStatus)), Qt::DirectConnection);
366 
367  m_stdOutData.clear();
368 
369  m_process->start();
370 
371 #ifdef Q_OS_WIN
372  bool ret = m_process->waitForFinished(-1);
373 #else
374  bool ret = (loop.exec(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents) == 0);
375 #endif
376 
377  Q_ASSERT(!m_process);
378 
379  return ret;
380 }
381 
382 void CliInterface::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
383 {
384  kDebug() << exitCode << exitStatus;
385 
386  //if the m_process pointer is gone, then there is nothing to worry
387  //about here
388  if (!m_process) {
389  return;
390  }
391 
392  if (m_operationMode == Delete) {
393  foreach(const QVariant& v, m_removedFiles) {
394  emit entryRemoved(v.toString());
395  }
396  }
397 
398  //handle all the remaining data in the process
399  readStdout(true);
400 
401  delete m_process;
402  m_process = 0;
403 
404  emit progress(1.0);
405 
406  if (m_operationMode == Add) {
407  list();
408  return;
409  }
410 
411  //and we're finished
412  emit finished(true);
413 }
414 
415 void CliInterface::failOperation()
416 {
417  // TODO: Would be good to unit test #304764/#304178.
418  kDebug();
419  doKill();
420 }
421 
422 void CliInterface::readStdout(bool handleAll)
423 {
424  //when hacking this function, please remember the following:
425  //- standard output comes in unpredictable chunks, this is why
426  //you can never know if the last part of the output is a complete line or not
427  //- console applications are not really consistent about what
428  //characters they send out (newline, backspace, carriage return,
429  //etc), so keep in mind that this function is supposed to handle
430  //all those special cases and be the lowest common denominator
431 
432  if (m_abortingOperation)
433  return;
434 
435  Q_ASSERT(m_process);
436 
437  if (!m_process->bytesAvailable()) {
438  //if process has no more data, we can just bail out
439  return;
440  }
441 
442  //if the process is still not finished (m_process is appearantly not
443  //set to NULL if here), then the operation should definitely not be in
444  //the main thread as this would freeze everything. assert this.
445  Q_ASSERT(QThread::currentThread() != QApplication::instance()->thread());
446 
447  QByteArray dd = m_process->readAllStandardOutput();
448  m_stdOutData += dd;
449 
450  QList<QByteArray> lines = m_stdOutData.split('\n');
451 
452  //The reason for this check is that archivers often do not end
453  //queries (such as file exists, wrong password) on a new line, but
454  //freeze waiting for input. So we check for errors on the last line in
455  //all cases.
456  // TODO: QLatin1String() might not be the best choice here.
457  // The call to handleLine() at the end of the method uses
458  // QString::fromLocal8Bit(), for example.
459  // TODO: The same check methods are called in handleLine(), this
460  // is suboptimal.
461  bool foundErrorMessage =
462  (checkForErrorMessage(QLatin1String( lines.last() ), WrongPasswordPatterns) ||
463  checkForErrorMessage(QLatin1String( lines.last() ), ExtractionFailedPatterns) ||
464  checkForPasswordPromptMessage(QLatin1String(lines.last())) ||
465  checkForFileExistsMessage(QLatin1String( lines.last() )));
466 
467  if (foundErrorMessage) {
468  handleAll = true;
469  }
470 
471  //this is complex, here's an explanation:
472  //if there is no newline, then there is no guaranteed full line to
473  //handle in the output. The exception is that it is supposed to handle
474  //all the data, OR if there's been an error message found in the
475  //partial data.
476  if (lines.size() == 1 && !handleAll) {
477  return;
478  }
479 
480  if (handleAll) {
481  m_stdOutData.clear();
482  } else {
483  //because the last line might be incomplete we leave it for now
484  //note, this last line may be an empty string if the stdoutdata ends
485  //with a newline
486  m_stdOutData = lines.takeLast();
487  }
488 
489  foreach(const QByteArray& line, lines) {
490  if (!line.isEmpty() || (m_listEmptyLines && m_operationMode == List)) {
491  handleLine(QString::fromLocal8Bit(line));
492  }
493  }
494 }
495 
496 void CliInterface::handleLine(const QString& line)
497 {
498  // TODO: This should be implemented by each plugin; the way progress is
499  // shown by each CLI application is subject to a lot of variation.
500  if ((m_operationMode == Copy || m_operationMode == Add) && m_param.contains(CaptureProgress) && m_param.value(CaptureProgress).toBool()) {
501  //read the percentage
502  int pos = line.indexOf(QLatin1Char( '%' ));
503  if (pos != -1 && pos > 1) {
504  int percentage = line.mid(pos - 2, 2).toInt();
505  emit progress(float(percentage) / 100);
506  return;
507  }
508  }
509 
510  if (m_operationMode == Copy) {
511  if (checkForPasswordPromptMessage(line)) {
512  kDebug() << "Found a password prompt";
513 
514  Kerfuffle::PasswordNeededQuery query(filename());
515  emit userQuery(&query);
516  query.waitForResponse();
517 
518  if (query.responseCancelled()) {
519  failOperation();
520  return;
521  }
522 
523  setPassword(query.password());
524 
525  const QString response(password() + QLatin1Char('\n'));
526  writeToProcess(response.toLocal8Bit());
527 
528  return;
529  }
530 
531  if (checkForErrorMessage(line, WrongPasswordPatterns)) {
532  kDebug() << "Wrong password!";
533  emit error(i18n("Incorrect password."));
534  failOperation();
535  return;
536  }
537 
538  if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
539  kDebug() << "Error in extraction!!";
540  emit error(i18n("Extraction failed because of an unexpected error."));
541  failOperation();
542  return;
543  }
544 
545  if (handleFileExistsMessage(line)) {
546  return;
547  }
548  }
549 
550  if (m_operationMode == List) {
551  if (checkForPasswordPromptMessage(line)) {
552  kDebug() << "Found a password prompt";
553 
554  Kerfuffle::PasswordNeededQuery query(filename());
555  emit userQuery(&query);
556  query.waitForResponse();
557 
558  if (query.responseCancelled()) {
559  failOperation();
560  return;
561  }
562 
563  setPassword(query.password());
564 
565  const QString response(password() + QLatin1Char('\n'));
566  writeToProcess(response.toLocal8Bit());
567 
568  return;
569  }
570 
571  if (checkForErrorMessage(line, WrongPasswordPatterns)) {
572  kDebug() << "Wrong password!";
573  emit error(i18n("Incorrect password."));
574  failOperation();
575  return;
576  }
577 
578  if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
579  kDebug() << "Error in extraction!!";
580  emit error(i18n("Extraction failed because of an unexpected error."));
581  failOperation();
582  return;
583  }
584 
585  if (handleFileExistsMessage(line)) {
586  return;
587  }
588 
589  readListLine(line);
590  return;
591  }
592 }
593 
594 bool CliInterface::checkForPasswordPromptMessage(const QString& line)
595 {
596  const QString passwordPromptPattern(m_param.value(PasswordPromptPattern).toString());
597 
598  if (passwordPromptPattern.isEmpty())
599  return false;
600 
601  if (m_passwordPromptPattern.isEmpty()) {
602  m_passwordPromptPattern.setPattern(m_param.value(PasswordPromptPattern).toString());
603  }
604 
605  if (m_passwordPromptPattern.indexIn(line) != -1) {
606  return true;
607  }
608 
609  return false;
610 }
611 
612 bool CliInterface::checkForFileExistsMessage(const QString& line)
613 {
614  if (m_existsPattern.isEmpty()) {
615  m_existsPattern.setPattern(m_param.value(FileExistsExpression).toString());
616  }
617  if (m_existsPattern.indexIn(line) != -1) {
618  kDebug() << "Detected file existing!! Filename " << m_existsPattern.cap(1);
619  return true;
620  }
621 
622  return false;
623 }
624 
625 bool CliInterface::handleFileExistsMessage(const QString& line)
626 {
627  if (!checkForFileExistsMessage(line)) {
628  return false;
629  }
630 
631  const QString filename = m_existsPattern.cap(1);
632 
633  Kerfuffle::OverwriteQuery query(QDir::current().path() + QLatin1Char( '/' ) + filename);
634  query.setNoRenameMode(true);
635  emit userQuery(&query);
636  kDebug() << "Waiting response";
637  query.waitForResponse();
638 
639  kDebug() << "Finished response";
640 
641  QString responseToProcess;
642  const QStringList choices = m_param.value(FileExistsInput).toStringList();
643 
644  if (query.responseOverwrite()) {
645  responseToProcess = choices.at(0);
646  } else if (query.responseSkip()) {
647  responseToProcess = choices.at(1);
648  } else if (query.responseOverwriteAll()) {
649  responseToProcess = choices.at(2);
650  } else if (query.responseAutoSkip()) {
651  responseToProcess = choices.at(3);
652  } else if (query.responseCancelled()) {
653  if (choices.count() < 5) { // If the program has no way to cancel the extraction, we resort to killing it
654  return doKill();
655  }
656  responseToProcess = choices.at(4);
657  }
658 
659  Q_ASSERT(!responseToProcess.isEmpty());
660 
661  responseToProcess += QLatin1Char( '\n' );
662 
663  writeToProcess(responseToProcess.toLocal8Bit());
664 
665  return true;
666 }
667 
668 bool CliInterface::checkForErrorMessage(const QString& line, int parameterIndex)
669 {
670  QList<QRegExp> patterns;
671 
672  if (m_patternCache.contains(parameterIndex)) {
673  patterns = m_patternCache.value(parameterIndex);
674  } else {
675  if (!m_param.contains(parameterIndex)) {
676  return false;
677  }
678 
679  foreach(const QString& rawPattern, m_param.value(parameterIndex).toStringList()) {
680  patterns << QRegExp(rawPattern);
681  }
682  m_patternCache[parameterIndex] = patterns;
683  }
684 
685  foreach(const QRegExp& pattern, patterns) {
686  if (pattern.indexIn(line) != -1) {
687  return true;
688  }
689  }
690  return false;
691 }
692 
693 bool CliInterface::doKill()
694 {
695  if (m_process) {
696  // Give some time for the application to finish gracefully
697  m_abortingOperation = true;
698  if (!m_process->waitForFinished(5)) {
699  m_process->kill();
700  }
701  m_abortingOperation = false;
702 
703  return true;
704  }
705 
706  return false;
707 }
708 
709 bool CliInterface::doSuspend()
710 {
711  return false;
712 }
713 
714 bool CliInterface::doResume()
715 {
716  return false;
717 }
718 
719 void CliInterface::substituteListVariables(QStringList& params)
720 {
721  for (int i = 0; i < params.size(); ++i) {
722  const QString parameter = params.at(i);
723 
724  if (parameter == QLatin1String( "$Archive" )) {
725  params[i] = filename();
726  }
727  }
728 }
729 
730 QString CliInterface::escapeFileName(const QString& fileName) const
731 {
732  return fileName;
733 }
734 
735 void CliInterface::writeToProcess(const QByteArray& data)
736 {
737  Q_ASSERT(m_process);
738  Q_ASSERT(!data.isNull());
739 
740  kDebug() << "Writing" << data << "to the process";
741 
742 #ifdef Q_OS_WIN
743  m_process->write(data);
744 #else
745  m_process->pty()->write(data);
746 #endif
747 }
748 
749 }
750 
751 #include "cliinterface.moc"
cliinterface.h
Kerfuffle::CliInterface::Add
Definition: cliinterface.h:230
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QRegExp::cap
QString cap(int nth) const
QDir::relativeFilePath
QString relativeFilePath(const QString &fileName) const
Kerfuffle::ReadOnlyArchiveInterface::setWaitForFinishedSignal
void setWaitForFinishedSignal(bool value)
Setting this option to true will not exit the thread with the exit of the various functions...
Definition: archiveinterface.cpp:105
Kerfuffle::ExtractionFailedPatterns
QStringList Default: empty A list of regexp patterns that will cause the extraction to exit with a ge...
Definition: cliinterface.h:194
QByteArray::clear
void clear()
Kerfuffle::ExtractProgram
QStringList The names to the program that will handle extracting of this archive (eg "rar")...
Definition: cliinterface.h:84
QEventLoop
Kerfuffle::CliInterface::CliInterface
CliInterface(QObject *parent, const QVariantList &args)
Definition: cliinterface.cpp:54
Kerfuffle::ReadOnlyArchiveInterface::entryRemoved
void entryRemoved(const QString &path)
QByteArray::split
QList< QByteArray > split(char sep) const
QRegExp::isEmpty
bool isEmpty() const
QByteArray
Kerfuffle::AddProgram
QStringList The names to the program that will handle adding in this archive format (eg "rar")...
Definition: cliinterface.h:210
Kerfuffle::ListArgs
QStringList The arguments that are passed to the program above for listing the archive.
Definition: cliinterface.h:75
Kerfuffle::PasswordNeededQuery::password
QString password()
Definition: queries.cpp:195
QList::at
const T & at(int i) const
QByteArray::isNull
bool isNull() const
Kerfuffle::ReadOnlyArchiveInterface::userQuery
void userQuery(Query *query)
QList::removeAt
void removeAt(int i)
QByteArray::isEmpty
bool isEmpty() const
Kerfuffle::PasswordPromptPattern
QString Default: empty A regexp pattern that matches the program's password prompt.
Definition: cliinterface.h:58
Kerfuffle::ReadOnlyArchiveInterface::filename
QString filename() const
Returns the filename of the archive currently being handled.
Definition: archiveinterface.cpp:48
queries.h
QStringList::join
QString join(const QString &separator) const
QObject::thread
QThread * thread() const
Kerfuffle::CliInterface::doSuspend
bool doSuspend()
Definition: cliinterface.cpp:709
Kerfuffle::CliInterface::parameterList
virtual ParameterList parameterList() const =0
QMetaType::type
int type(const char *typeName)
Kerfuffle::PasswordNeededQuery::responseCancelled
bool responseCancelled()
Definition: queries.cpp:200
QList::size
int size() const
Kerfuffle::ReadOnlyArchiveInterface::password
QString password() const
Definition: archiveinterface.cpp:68
Kerfuffle::Query::waitForResponse
void waitForResponse()
Will block until the response have been set.
Definition: queries.cpp:50
QRegExp::setPattern
void setPattern(const QString &pattern)
QRegExp::indexIn
int indexIn(const QString &str, int offset, CaretMode caretMode) const
QRegExp
QList::count
int count(const T &value) const
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
Kerfuffle::ReadWriteArchiveInterface
Definition: archiveinterface.h:121
Kerfuffle::PreservePathSwitch
QStringList This should be a qstringlist with either two elements.
Definition: cliinterface.h:122
Kerfuffle::CliInterface::readListLine
virtual bool readListLine(const QString &line)=0
QHash
QEventLoop::exec
int exec(QFlags< QEventLoop::ProcessEventsFlag > flags)
Kerfuffle::ReadOnlyArchiveInterface::setPassword
void setPassword(const QString &password)
Definition: archiveinterface.cpp:63
QObject
QString::toInt
int toInt(bool *ok, int base) const
Kerfuffle::WrongPasswordPatterns
QStringList Default: empty A list of regexp patterns that will alert the user that the password was w...
Definition: cliinterface.h:201
Kerfuffle::CliInterface::copyFiles
virtual bool copyFiles(const QList< QVariant > &files, const QString &destinationDirectory, ExtractionOptions options)
Extract files from archive.
Definition: cliinterface.cpp:104
QString::isEmpty
bool isEmpty() const
Kerfuffle::CliInterface::doResume
bool doResume()
Definition: cliinterface.cpp:714
Kerfuffle::ExtractArgs
QStringList The arguments that are passed to the program above for extracting the archive...
Definition: cliinterface.h:100
QDir::setCurrent
bool setCurrent(const QString &path)
QCoreApplication::instance
QCoreApplication * instance()
Kerfuffle::FileExistsExpression
QString This is a regexp, defining how to recognize a "File already exists" prompt when extracting...
Definition: cliinterface.h:148
Kerfuffle::ReadOnlyArchiveInterface::finished
void finished(bool result)
QString
QList
Kerfuffle::CliInterface::Copy
Definition: cliinterface.h:230
QStringList
Kerfuffle::CliInterface::Delete
Definition: cliinterface.h:230
QHash::value
const T value(const Key &key) const
QLatin1Char
Kerfuffle::CaptureProgress
Bool (default false) Will look for the %-sign in the stdout while working, in the form of (2%...
Definition: cliinterface.h:51
Kerfuffle::CliInterface::List
Definition: cliinterface.h:230
QDir
Kerfuffle::CliInterface::~CliInterface
virtual ~CliInterface()
Definition: cliinterface.cpp:78
Kerfuffle::PasswordNeededQuery
Definition: queries.h:99
QString::replace
QString & replace(int position, int n, QChar after)
Kerfuffle::DeleteArgs
QStringList The arguments that are passed to the program above for deleting from the archive...
Definition: cliinterface.h:187
QList::takeLast
T takeLast()
Kerfuffle::PasswordSwitch
QStringList (default empty) The format of the root node switch.
Definition: cliinterface.h:141
QString::mid
QString mid(int position, int n) const
Kerfuffle::DeleteProgram
QStringList The names to the program that will handle deleting of elements in this archive format (eg...
Definition: cliinterface.h:178
QLatin1String
QList::insert
void insert(int i, const T &value)
Kerfuffle::CliInterface::setListEmptyLines
void setListEmptyLines(bool emptyLines)
Sets if the listing should include empty lines.
Definition: cliinterface.cpp:83
QThread::currentThread
QThread * currentThread()
Kerfuffle::FileExistsInput
QStringList The various responses that can be supplied as a response to the "file exists" prompt...
Definition: cliinterface.h:169
Kerfuffle::ReadOnlyArchiveInterface::error
void error(const QString &message, const QString &details=QString())
Kerfuffle::CliInterface::m_operationMode
OperationMode m_operationMode
Definition: cliinterface.h:232
Kerfuffle::AddArgs
QStringList The arguments that are passed to the program above for adding to the archive.
Definition: cliinterface.h:219
QList::last
T & last()
Kerfuffle::OverwriteQuery
Definition: queries.h:77
Kerfuffle::ReadOnlyArchiveInterface::progress
void progress(double progress)
QHash::contains
bool contains(const Key &key) const
Kerfuffle::CliInterface::list
virtual bool list()
List archive contents.
Definition: cliinterface.cpp:88
QDir::current
QDir current()
Kerfuffle::CliInterface::addFiles
virtual bool addFiles(const QStringList &files, const CompressionOptions &options)
Definition: cliinterface.cpp:243
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Kerfuffle::CliInterface::doKill
bool doKill()
Definition: cliinterface.cpp:693
QVariant::toString
QString toString() const
Kerfuffle::RootNodeSwitch
QStringList (default empty) The format of the root node switch.
Definition: cliinterface.h:130
Kerfuffle::CliInterface::deleteFiles
virtual bool deleteFiles(const QList< QVariant > &files)
Definition: cliinterface.cpp:293
Kerfuffle::ListProgram
QStringList The names to the program that will handle listing of this archive (eg "rar")...
Definition: cliinterface.h:67
QVariant
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:42:37 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

ark

Skip menu "ark"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdeutils API Reference

Skip menu "kdeutils API Reference"
  • ark
  • filelight
  • kcalc
  • kcharselect
  • kdf
  • kfloppy
  • kgpg
  • ktimer
  • kwallet
  • sweeper

Search



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

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