File indexing completed on 2024-05-12 05:46:33

0001 /*
0002    Copyright (C) 2008-2010 by Sebastian Trueg <trueg at kde.org>
0003    Copyright (C) 2012-2014 by Vishesh Handa <me@vhanda.in>
0004 
0005    This program is free software; you can redistribute it and/or modify
0006    it under the terms of the GNU General Public License as published by
0007    the Free Software Foundation; either version 2, or (at your option)
0008    any later version.
0009 
0010    This program is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013    GNU General Public License for more details.
0014 
0015    You should have received a copy of the GNU General Public License
0016    along with this program; if not, write to the Free Software
0017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0018  */
0019 
0020 #include "kio_search.h"
0021 
0022 #include "query.h"
0023 #include "resultiterator.h"
0024 #include "idutils.h"
0025 
0026 #include <QUrl>
0027 #include <QUrlQuery>
0028 #include <KUser>
0029 #include <QCoreApplication>
0030 #include <KLocalizedString>
0031 
0032 #include <KIO/Job>
0033 
0034 using namespace Baloo;
0035 
0036 namespace
0037 {
0038 
0039 KIO::UDSEntry statSearchFolder(const QUrl& url)
0040 {
0041     KIO::UDSEntry uds;
0042     uds.reserve(9);
0043     uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, 0700);
0044     uds.fastInsert(KIO::UDSEntry::UDS_USER, KUser().loginName());
0045     uds.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
0046     uds.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory"));
0047     uds.fastInsert(KIO::UDSEntry::UDS_ICON_OVERLAY_NAMES, QStringLiteral("baloo"));
0048     uds.fastInsert(KIO::UDSEntry::UDS_DISPLAY_TYPE, i18n("Search Folder"));
0049     uds.fastInsert(KIO::UDSEntry::UDS_URL, url.url());
0050 
0051     QUrlQuery query(url);
0052     QString title = query.queryItemValue(QStringLiteral("title"), QUrl::FullyDecoded);
0053     if (!title.isEmpty()) {
0054         uds.fastInsert(KIO::UDSEntry::UDS_NAME, title);
0055         uds.fastInsert(KIO::UDSEntry::UDS_DISPLAY_NAME, title);
0056     }
0057 
0058     return uds;
0059 }
0060 
0061 }
0062 
0063 SearchProtocol::SearchProtocol(const QByteArray& poolSocket, const QByteArray& appSocket)
0064     : KIO::SlaveBase("baloosearch", poolSocket, appSocket)
0065 {
0066 }
0067 
0068 
0069 SearchProtocol::~SearchProtocol()
0070 {
0071 }
0072 
0073 static QString jsonQueryForType(const QString &type)
0074 {
0075     const QString jsonQuery(QStringLiteral("{\"dayFilter\": 0,\
0076                                              \"monthFilter\": 0, \
0077                                              \"yearFilter\": 0, \
0078                                              \"type\": [ \"%1\"]}"));
0079     return jsonQuery.arg(type);
0080 }
0081 
0082 static QString jsonQueryFromUrl(const QUrl &url)
0083 {
0084     const QString path = url.path();
0085 
0086     if (path == QLatin1String("/documents")) {
0087         return jsonQueryForType(QStringLiteral("Document"));
0088     } else if (path.endsWith(QLatin1String("/images"))) {
0089         return jsonQueryForType(QStringLiteral("Image"));
0090     } else if (path.endsWith(QLatin1String("/audio"))) {
0091         return jsonQueryForType(QStringLiteral("Audio"));
0092     } else if (path.endsWith(QLatin1String("/videos"))) {
0093         return jsonQueryForType(QStringLiteral("Video"));
0094     }
0095 
0096     return QString();
0097 }
0098 
0099 void SearchProtocol::listDir(const QUrl& url)
0100 {
0101     Query q;
0102 
0103     QUrlQuery urlQuery(url);
0104     if (urlQuery.hasQueryItem(QStringLiteral("json"))) {
0105         QString jsonString = urlQuery.queryItemValue(QStringLiteral("json"), QUrl::FullyDecoded);
0106         q = Query::fromJSON(jsonString.toUtf8());
0107     } else if (urlQuery.hasQueryItem(QStringLiteral("query"))) {
0108         QString queryString = urlQuery.queryItemValue(QStringLiteral("query"), QUrl::FullyDecoded);
0109 
0110         q.setSearchString(queryString);
0111     } else {
0112         const QString jsonString = jsonQueryFromUrl(url);
0113         if (!jsonString.isEmpty()) {
0114             q = Query::fromJSON(jsonString.toUtf8());
0115         }
0116     }
0117 
0118     q.setSortingOption(Query::SortNone);
0119     ResultIterator it = q.exec();
0120 
0121     while (it.next()) {
0122         KIO::UDSEntry uds;
0123         uds.reserve(10);
0124         const QString filePath(it.filePath());
0125 
0126         // Code from kdelibs/kioslaves/file.cpp
0127         QT_STATBUF statBuf;
0128         const QByteArray ba = QFile::encodeName(filePath);
0129         if (filePathToStat(ba, statBuf) == 0) {
0130             uds.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, statBuf.st_mtime);
0131             uds.fastInsert(KIO::UDSEntry::UDS_ACCESS_TIME, statBuf.st_atime);
0132             uds.fastInsert(KIO::UDSEntry::UDS_SIZE, statBuf.st_size);
0133 #ifndef Q_OS_WIN
0134             uds.fastInsert(KIO::UDSEntry::UDS_USER, getUserName(KUserId(statBuf.st_uid)));
0135             uds.fastInsert(KIO::UDSEntry::UDS_GROUP, getGroupName(KGroupId(statBuf.st_gid)));
0136 #else
0137 #pragma message("TODO: st_uid and st_gid are always zero, use GetSecurityInfo to find the owner")
0138 #endif
0139 
0140             mode_t type = statBuf.st_mode & S_IFMT;
0141             mode_t access = statBuf.st_mode & 07777;
0142 
0143             uds.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, type);
0144             uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, access);
0145         }
0146         else {
0147             continue;
0148         }
0149 
0150         QUrl url = QUrl::fromLocalFile(filePath);
0151         uds.fastInsert(KIO::UDSEntry::UDS_NAME, url.fileName());
0152         uds.fastInsert(KIO::UDSEntry::UDS_URL, url.url());
0153         uds.fastInsert(KIO::UDSEntry::UDS_LOCAL_PATH, filePath);
0154 
0155         listEntry(uds);
0156     }
0157 
0158     KIO::UDSEntry uds;
0159     uds.reserve(5);
0160     uds.fastInsert(KIO::UDSEntry::UDS_NAME, QStringLiteral("."));
0161     uds.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
0162     uds.fastInsert(KIO::UDSEntry::UDS_MIME_TYPE, QStringLiteral("inode/directory"));
0163     uds.fastInsert(KIO::UDSEntry::UDS_ACCESS, 0700);
0164     uds.fastInsert(KIO::UDSEntry::UDS_USER, KUser().loginName());
0165     listEntry(uds);
0166 
0167     finished();
0168 }
0169 
0170 
0171 void SearchProtocol::mimetype(const QUrl&)
0172 {
0173     mimeType(QStringLiteral("inode/directory"));
0174     finished();
0175 }
0176 
0177 
0178 void SearchProtocol::stat(const QUrl& url)
0179 {
0180     statEntry(statSearchFolder(url));
0181     finished();
0182 }
0183 
0184 QString SearchProtocol::getUserName(const KUserId &uid) const
0185 {
0186     if (Q_UNLIKELY(!uid.isValid())) {
0187         return QString();
0188     }
0189     if (!mUsercache.contains(uid)) {
0190         KUser user(uid);
0191         QString name = user.loginName();
0192         if (name.isEmpty()) {
0193             name = uid.toString();
0194         }
0195         mUsercache.insert(uid, name);
0196         return name;
0197     }
0198     return mUsercache[uid];
0199 }
0200 
0201 QString SearchProtocol::getGroupName(const KGroupId &gid) const
0202 {
0203     if (Q_UNLIKELY(!gid.isValid())) {
0204         return QString();
0205     }
0206     if (!mGroupcache.contains(gid)) {
0207         KUserGroup group(gid);
0208         QString name = group.name();
0209         if (name.isEmpty()) {
0210             name = gid.toString();
0211         }
0212         mGroupcache.insert(gid, name);
0213         return name;
0214     }
0215     return mGroupcache[gid];
0216 }
0217 
0218 
0219 extern "C"
0220 {
0221     Q_DECL_EXPORT int kdemain(int argc, char** argv)
0222     {
0223         QCoreApplication app(argc, argv);
0224         app.setApplicationName(QStringLiteral("kio_baloosearch"));
0225         Baloo::SearchProtocol slave(argv[2], argv[3]);
0226         slave.dispatchLoop();
0227         return 0;
0228     }
0229 }