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 }