Warning, file /plasma/libksysguard/processui/ProcessFilter.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     KSysGuard, the KDE System Guard
0003 
0004     SPDX-FileCopyrightText: 2006-2007 John Tapsell <john.tapsell@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 
0008 */
0009 #include "processui_debug.h"
0010 
0011 /* For getuid() */
0012 #include <sys/types.h>
0013 #include <unistd.h>
0014 
0015 #include <QDebug>
0016 #include <QVariant>
0017 
0018 #include "ProcessFilter.h"
0019 #include "ProcessModel.h"
0020 #include "ProcessModel_p.h"
0021 
0022 bool ProcessFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
0023 {
0024     if ((mFilter == AllProcesses || mFilter == AllProcessesInTreeForm) && filterRegularExpression().pattern().isEmpty())
0025         return true; // Shortcut for common case
0026 
0027     ProcessModel *model = static_cast<ProcessModel *>(sourceModel());
0028     const KSysGuard::Process *process;
0029     if (model->isSimpleMode()) {
0030         if (source_parent.isValid()) {
0031             qCDebug(LIBKSYSGUARD_PROCESSUI) << "Serious error with data.  In simple mode, there should be no children";
0032             return true;
0033         }
0034         process = model->getProcessAtIndex(source_row);
0035     } else {
0036         KSysGuard::Process *parent_process = nullptr;
0037         if (source_parent.isValid()) {
0038             parent_process = reinterpret_cast<KSysGuard::Process *>(source_parent.internalPointer());
0039             Q_ASSERT(parent_process);
0040         } else {
0041             // if(!model->isSimpleMode()) {
0042             parent_process = model->getProcess(-1); // Get our 'special' process which should have the root init child
0043             Q_ASSERT(parent_process);
0044             //}
0045         }
0046         if (!model->isSimpleMode() && source_row >= parent_process->children().size()) {
0047             qCDebug(LIBKSYSGUARD_PROCESSUI) << "Serious error with data.  Source row requested for a non existent row. Requested " << source_row << " of "
0048                                             << parent_process->children().size() << " for " << parent_process->pid();
0049             return true;
0050         }
0051 
0052         process = parent_process->children().at(source_row);
0053     }
0054     Q_ASSERT(process);
0055     long uid = process->uid();
0056     long euid = process->euid();
0057 
0058     bool accepted = true;
0059     switch (mFilter) {
0060     case AllProcesses:
0061     case AllProcessesInTreeForm:
0062         break;
0063     case SystemProcesses:
0064         if (uid >= 100 && model->canUserLogin(uid))
0065             accepted = false;
0066         break;
0067     case UserProcesses:
0068         if ((uid < 100 || !model->canUserLogin(uid)) && (euid < 100 || !model->canUserLogin(euid)))
0069             accepted = false;
0070         break;
0071     case OwnProcesses: {
0072         long ownuid = getuid();
0073         if (uid != ownuid && process->suid() != ownuid && process->fsuid() != ownuid && euid != ownuid)
0074             accepted = false;
0075         break;
0076     }
0077     case ProgramsOnly:
0078         if (process->tty().isEmpty()) {
0079             if (!model->hasGUIWindow(process->pid()))
0080                 accepted = false;
0081         } else {
0082             // login and getty kinda _are_ the tty, so I do not really count them as 'programs'. So make a special case and hide them
0083             // Their ppid are 1 (init) so by checking we try to avoid false matches, and speed up checking overall
0084             QString name = process->name().section(QLatin1Char(' '), 0, 0);
0085             if (process->parentPid() == 1 && (name == QLatin1String("login") || name.endsWith(QLatin1String("getty"))))
0086                 accepted = false;
0087         }
0088         break;
0089     default:
0090         break;
0091     }
0092 
0093     if (accepted) {
0094         if (filterRegularExpression().pattern().isEmpty())
0095             return true;
0096 
0097         // Allow the user to search by PID
0098         if (QString::number(process->pid()).contains(filterRegularExpression()))
0099             return true;
0100         // None of our tests have rejected it.  Pass it on to qsortfilterproxymodel's filter
0101         if (QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent))
0102             return true;
0103 
0104         auto strings = filterRegularExpression().pattern().split(QLatin1Char(','), Qt::SkipEmptyParts);
0105         for (auto string : strings) {
0106             string = string.trimmed();
0107             if (process->name().indexOf(string) != -1 || QString::number(process->pid()).indexOf(string) != -1) {
0108                 return true;
0109             }
0110         }
0111     }
0112 
0113     // We did not accept this row at all.
0114 
0115     // If we are in flat mode, then give up now
0116     if (mFilter != AllProcessesInTreeForm)
0117         return false;
0118 
0119     // one of our children might be accepted, so accept this row if our children are accepted.
0120     QModelIndex source_index = sourceModel()->index(source_row, 0, source_parent);
0121     for (int i = 0; i < sourceModel()->rowCount(source_index); i++) {
0122         if (filterAcceptsRow(i, source_index))
0123             return true;
0124     }
0125     return false;
0126 }
0127 
0128 bool ProcessFilter::lessThan(const QModelIndex &left, const QModelIndex &right) const
0129 {
0130     if (right.isValid() && left.isValid()) {
0131         Q_ASSERT(left.model());
0132         Q_ASSERT(right.model());
0133         const ProcessModel *model = static_cast<const ProcessModel *>(left.model());
0134         return model->lessThan(left, right);
0135     }
0136     return QSortFilterProxyModel::lessThan(left, right);
0137 }
0138 
0139 void ProcessFilter::setFilter(State filter)
0140 {
0141     mFilter = filter;
0142     invalidateFilter(); // Tell the proxy view to refresh all its information
0143 }