File indexing completed on 2024-05-19 05:49:20

0001 /***************************************************************************
0002  *   Copyright © 2009 Jonathan Thomas <echidnaman@kubuntu.org>             *
0003  *   Copyright © 2009-2021 Harald Sitter <apachelogger@ubuntu.com>              *
0004  *                                                                         *
0005  *   This program is free software; you can redistribute it and/or         *
0006  *   modify it under the terms of the GNU General Public License as        *
0007  *   published by the Free Software Foundation; either version 2 of        *
0008  *   the License or (at your option) version 3 or any later version        *
0009  *   accepted by the membership of KDE e.V. (or its successor approved     *
0010  *   by the membership of KDE e.V.), which shall act as a proxy            *
0011  *   defined in Section 14 of version 3 of the license.                    *
0012  *                                                                         *
0013  *   This program is distributed in the hope that it will be useful,       *
0014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0016  *   GNU General Public License for more details.                          *
0017  *                                                                         *
0018  *   You should have received a copy of the GNU General Public License     *
0019  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0020  ***************************************************************************/
0021 
0022 #include "apportevent.h"
0023 
0024 #include <QDebug>
0025 #include <QStandardPaths>
0026 #include <QDir>
0027 
0028 #include <KProcess>
0029 #include <KToolInvocation>
0030 #include <KDirWatch>
0031 
0032 ApportEvent::ApportEvent(QObject* parent)
0033         : Event(parent, "Apport")
0034 {
0035     const bool apportKde = QFile::exists("/usr/share/apport/apport-kde");
0036     const bool apportGtk = QFile::exists("/usr/share/apport/apport-gtk");
0037     qDebug() << "ApportEvent ::"
0038              << "apport-kde=" << apportKde
0039              << "apport-gtk=" << apportGtk;
0040     if (!apportKde && !apportGtk) {
0041         return;
0042     }
0043     qDebug() << "Using ApportEvent";
0044 
0045     auto apportDirWatch =  new KDirWatch(this);
0046     apportDirWatch->addDir("/var/crash/");
0047     connect(apportDirWatch, &KDirWatch::dirty, this, &ApportEvent::onDirty);
0048 
0049     // Force check, we just started up and there might have been crashes on reboot
0050     show();
0051 }
0052 
0053 ApportEvent::~ApportEvent()
0054 {
0055 }
0056 
0057 bool ApportEvent::reportsAvailable()
0058 {
0059 // TODO: there is also a --system arg for checkreports, update-notifier does seem to use
0060 //       that in an either-or combo... so question is why does that --system arg exist at
0061 //       all if we are supposed to either-or the results of two runs anyway?
0062     KProcess *apportProcess = new KProcess();
0063     apportProcess->setProgram(QStringList() << "/usr/share/apport/apport-checkreports");
0064 
0065     if (apportProcess->execute() == 0) {
0066         return true;
0067     }
0068     return false;
0069 }
0070 
0071 void ApportEvent::show()
0072 {
0073     if (isHidden()) {
0074         return;
0075     }
0076 
0077     if (!reportsAvailable()) {
0078         qDebug() << "no reports available, aborting";
0079         return;
0080     }
0081 
0082     QString icon = QString("apport");
0083     QString text(i18nc("Notification when apport detects a crash",
0084                        "An application has crashed on your system (now or in the past)"));
0085     QStringList actions;
0086     actions << i18nc("Opens a dialog with more details", "Details");
0087     actions << i18nc("Button to dismiss this notification once", "Ignore for now");
0088     actions << i18nc("Button to make this notification never show up again",
0089                      "Never show again");
0090 
0091     Event::show(icon, text, actions);
0092 }
0093 
0094 void ApportEvent::batchUploadAllowed()
0095 {
0096     const QString script = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
0097                                                   "kubuntu-notification-helper/whoopsie-upload-all");
0098     if (script.isEmpty()) {
0099         qWarning() << "ApportEvent: whoopsie-upload-all not found";
0100         return;
0101     }
0102     qDebug() << "running" << script;
0103     KToolInvocation::kdeinitExec(script);
0104 }
0105 
0106 void ApportEvent::run()
0107 {
0108     KToolInvocation::kdeinitExec("/usr/share/apport/apport-kde");
0109     Event::run();
0110 }
0111 
0112 void ApportEvent::apportDirEvent()
0113 {
0114     qDebug();
0115 
0116     QDir dir(QLatin1String("/var/crash"));
0117     dir.setNameFilters(QStringList() << QLatin1String("*.crash"));
0118 
0119     bool foundCrashFile = false;
0120     bool foundAutoUpload = false;
0121     foreach (const QFileInfo &fileInfo, dir.entryInfoList()) {
0122         CrashFile f(fileInfo);
0123         if (f.isAutoUploadAllowed())
0124             foundAutoUpload = true;
0125             continue;
0126         if (f.isValid()) {
0127             foundCrashFile = true;
0128             continue;
0129         }
0130     }
0131 
0132     qDebug() << "foundCrashFile" << foundCrashFile
0133              << "foundAutoUpload" << foundAutoUpload;
0134 
0135     if (foundAutoUpload) {
0136         batchUploadAllowed();
0137     }
0138 
0139     if (foundCrashFile) {
0140         show();
0141     }
0142 }
0143 
0144 void ApportEvent::onDirty(const QString &path)
0145 {
0146     if (isHidden()) {
0147         return;
0148     }
0149 
0150     qDebug() << path;
0151     if (path.isEmpty()) { // Check whole directory for possible crash files.
0152         apportDirEvent();
0153         return;
0154     }
0155 
0156     // Check param path for validity.
0157     CrashFile f(path);
0158     if (f.isAutoUploadAllowed()) {
0159         batchUploadAllowed();
0160     } else if (f.isValid()) {
0161         show();
0162     }
0163 }