kio: make KIO::UDSEntry::UDS_URL required/mandatory

if the slaves do not know what URL is being stat()-ed, listed, etc. then
what? this may make the URL different than the one originally requested (as
it should be) in case of redirection(s) for example

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2024-05-31 16:30:03 +03:00
parent 1d0d3598c7
commit c18bacba12
11 changed files with 44 additions and 81 deletions

View file

@ -325,7 +325,7 @@ KPropertiesDialog::KPropertiesDialog(const KUrl &url, QWidget* parent)
KIO::UDSEntry entry;
KIO::NetAccess::stat(url, entry, parent);
d->m_items.append(KFileItem(entry, url));
d->m_items.append(KFileItem(entry));
d->init();
}
@ -1350,8 +1350,8 @@ void KFilePropsPlugin::slotCopyFinished(KJob *job)
// the file is copied from a template.
if (d->m_bFromTemplate) {
KIO::UDSEntry entry;
KIO::NetAccess::stat(properties->kurl(), entry, 0);
KFileItem item(entry, properties->kurl());
KIO::NetAccess::stat(properties->kurl(), entry, nullptr);
KFileItem item(entry);
KDesktopFile config(item.localPath());
KConfigGroup cg = config.desktopGroup();
QString nameStr = nameFromFileName(properties->kurl().fileName());

View file

@ -115,7 +115,7 @@ void DirectorySizeJobPrivate::processNextItem()
{
if ( item.isDir() )
{
//kDebug(7007) << "dir -> listing";
kDebug(7007) << "dir -> listing";
KUrl url = item.url();
startNextJob( url );
return; // we'll come back later, when this one's finished
@ -124,20 +124,20 @@ void DirectorySizeJobPrivate::processNextItem()
{
m_totalSize += item.size();
m_totalFiles++;
//kDebug(7007) << "file -> " << m_totalSize;
kDebug(7007) << "file -> " << m_totalSize;
}
} else {
m_totalFiles++;
}
}
//kDebug(7007) << "finished";
kDebug(7007) << "finished";
q->emitResult();
}
void DirectorySizeJobPrivate::startNextJob( const KUrl & url )
{
Q_Q(DirectorySizeJob);
//kDebug(7007) << url;
kDebug(7007) << url;
KIO::ListJob * listJob = KIO::listRecursive( url, KIO::HideProgressInfo );
listJob->addMetaData("details", "3");
q->connect( listJob, SIGNAL(entries(KIO::Job*,KIO::UDSEntryList)),
@ -154,15 +154,15 @@ void DirectorySizeJobPrivate::slotEntries( KIO::Job*, const KIO::UDSEntryList &
const long inode = entry.numberValue(KIO::UDSEntry::UDS_INODE, 0);
QSet<long> & visitedInodes = m_visitedInodes[device]; // find or insert
if (visitedInodes.contains(inode)) {
continue;
}
visitedInodes.insert(inode);
continue;
}
visitedInodes.insert(inode);
}
const KIO::filesize_t size = entry.numberValue(KIO::UDSEntry::UDS_SIZE, 0);
const QString name = entry.stringValue( KIO::UDSEntry::UDS_NAME );
if (name == ".") {
m_totalSize += size;
//kDebug(7007) << "'.': added" << size << "->" << m_totalSize;
kDebug(7007) << "'.': added" << size << "->" << m_totalSize;
} else if (name != "..") {
if (!entry.isLink())
m_totalSize += size;
@ -170,7 +170,7 @@ void DirectorySizeJobPrivate::slotEntries( KIO::Job*, const KIO::UDSEntryList &
m_totalFiles++;
else
m_totalSubdirs++;
//kDebug(7007) << name << ":" << size << "->" << m_totalSize;
kDebug(7007) << name << ":" << size << "->" << m_totalSize;
}
}
}
@ -178,7 +178,7 @@ void DirectorySizeJobPrivate::slotEntries( KIO::Job*, const KIO::UDSEntryList &
void DirectorySizeJob::slotResult( KJob * job )
{
Q_D(DirectorySizeJob);
//kDebug(7007) << d->m_totalSize;
kDebug(7007) << d->m_totalSize;
removeSubjob(job);
if (d->m_currentItem < d->m_lstItems.count())
{

View file

@ -989,7 +989,7 @@ QPixmap KIO::pixmapForUrl(const KUrl &url, KIconLoader::Group group,
} else {
KIO::UDSEntry entry;
KIO::NetAccess::stat(url, entry, nullptr);
fileitem = KFileItem(entry, url);
fileitem = KFileItem(entry);
}
return KIconLoader::global()->loadIcon(fileitem.iconName(), group, force_size, state, fileitem.overlays(), path);
}

View file

@ -80,7 +80,7 @@ void KDirListerPrivate::processEntries(KIO::Job *job, const KIO::UDSEntryList &e
if (name.isEmpty()) {
continue;
}
const KFileItem item(it, processJob->url());
const KFileItem item(it);
if (name == QLatin1String(".")) {
rootItem = item;
continue;

View file

@ -67,8 +67,7 @@ class KFileItemPrivate : public QSharedData
{
public:
KFileItemPrivate(const KIO::UDSEntry &entry,
const KUrl &itemOrDirUrl,
bool urlIsDirectory)
const KUrl &itemOrDirUrl)
: m_entry(entry),
m_url(itemOrDirUrl),
m_pMimeType(nullptr),
@ -78,8 +77,8 @@ public:
m_bIsLocalUrl(itemOrDirUrl.isLocalFile())
{
if (entry.count() != 0) {
Q_ASSERT(m_url.isEmpty())
// extract fields from the KIO::UDS Entry
m_fileMode = m_entry.numberValue(KIO::UDSEntry::UDS_FILE_TYPE);
m_permissions = m_entry.numberValue(KIO::UDSEntry::UDS_ACCESS);
m_strName = m_entry.stringValue(KIO::UDSEntry::UDS_NAME);
@ -92,8 +91,7 @@ public:
}
const QString urlStr = m_entry.stringValue(KIO::UDSEntry::UDS_URL);
const bool UDS_URL_seen = !urlStr.isEmpty();
if (UDS_URL_seen) {
if (!urlStr.isEmpty()) {
m_url = KUrl(urlStr);
if (m_url.isLocalFile()) {
m_bIsLocalUrl = true;
@ -106,12 +104,7 @@ public:
m_guessedMimeType = m_entry.stringValue(KIO::UDSEntry::UDS_GUESSED_MIME_TYPE);
m_bLink = !m_entry.stringValue(KIO::UDSEntry::UDS_LINK_DEST).isEmpty(); // we don't store the link dest
if (urlIsDirectory && !UDS_URL_seen && !m_strName.isEmpty() && m_strName != s_dot) {
m_url.addPath(m_strName);
}
} else {
Q_ASSERT(!urlIsDirectory);
m_strName = itemOrDirUrl.fileName();
m_strText = KIO::decodeFileName(m_strName);
}
@ -280,13 +273,13 @@ KFileItem::KFileItem()
{
}
KFileItem::KFileItem(const KIO::UDSEntry& entry, const KUrl &dirUrl)
: d(new KFileItemPrivate(entry, dirUrl, true))
KFileItem::KFileItem(const KIO::UDSEntry& entry)
: d(new KFileItemPrivate(entry, KUrl()))
{
}
KFileItem::KFileItem(const KUrl &url)
: d(new KFileItemPrivate(KIO::UDSEntry(), url, false))
: d(new KFileItemPrivate(KIO::UDSEntry(), url))
{
}

View file

@ -70,12 +70,8 @@ public:
* This is the preferred constructor when using KIO::listDir().
*
* @param entry the KIO entry used to get the file, contains info about it
* @param dirUrl the URL of the directory containing this item.
*
* When creating KFileItems out of the UDSEntry emitted by a KIO list job,
* use KFileItem(entry, listjob->url());
*/
KFileItem(const KIO::UDSEntry &entry, const KUrl &dirUrl);
KFileItem(const KIO::UDSEntry &entry);
/**
* Creates an item representing a file.

View file

@ -243,11 +243,12 @@ RenameDialog::RenameDialog(QWidget *parent, const QString & _caption,
UDSEntry srcUds;
srcUds.insert(UDSEntry::UDS_NAME, d->src.fileName());
srcUds.insert(UDSEntry::UDS_URL, d->src.url());
srcUds.insert(UDSEntry::UDS_MODIFICATION_TIME, mtimeSrc);
srcUds.insert(UDSEntry::UDS_CREATION_TIME, ctimeSrc);
srcUds.insert(UDSEntry::UDS_SIZE, sizeSrc);
d->srcItem = KFileItem(srcUds, d->src);
d->srcItem = KFileItem(srcUds);
}
if (d->dest.isLocalFile()) {
@ -256,11 +257,12 @@ RenameDialog::RenameDialog(QWidget *parent, const QString & _caption,
UDSEntry destUds;
destUds.insert(UDSEntry::UDS_NAME, d->dest.fileName());
destUds.insert(UDSEntry::UDS_URL, d->dest.url());
destUds.insert(UDSEntry::UDS_MODIFICATION_TIME, mtimeDest);
destUds.insert(UDSEntry::UDS_CREATION_TIME, ctimeDest);
destUds.insert(UDSEntry::UDS_SIZE, sizeDest);
d->destItem = KFileItem(destUds, d->dest);
d->destItem = KFileItem(destUds);
}
d->m_srcPreview = d->createPixmapWidget(parent);

View file

@ -455,6 +455,7 @@ void CurlProtocol::stat(const KUrl &url)
kDebug(7103) << "Faking root directory for" << url.prettyUrl();
KIO::UDSEntry kioudsentry;
kioudsentry.insert(KIO::UDSEntry::UDS_NAME, QLatin1String("."));
kioudsentry.insert(KIO::UDSEntry::UDS_URL, url.url());
kioudsentry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR);
kioudsentry.insert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
kioudsentry.insert(KIO::UDSEntry::UDS_MIME_TYPE, QLatin1String("inode/directory"));
@ -493,6 +494,7 @@ void CurlProtocol::stat(const KUrl &url)
kDebug(7103) << "Content length" << curlcontentlength;
kDebug(7103) << "MIME type" << httpmimetype;
kioudsentry.insert(KIO::UDSEntry::UDS_NAME, staturlfilename);
kioudsentry.insert(KIO::UDSEntry::UDS_URL, url.url());
kioudsentry.insert(KIO::UDSEntry::UDS_SIZE, qlonglong(curlcontentlength));
kioudsentry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, qlonglong(curlfiletime));
if (!httpmimetype.isEmpty()) {
@ -1203,7 +1205,9 @@ QList<KIO::UDSEntry> CurlProtocol::udsEntries()
KIO::UDSEntry kioudsentry;
const mode_t stdmode = ftpModeFromString(ftpmode);
const qlonglong ftpmodtime = ftpTimeFromString(ftpmonth, ftpday, ftphouroryear, currentdate.year());
kioudsentry.insert(KIO::UDSEntry::UDS_NAME, SlaveBase::decodeName(ftpfilepath));
const QString filename = SlaveBase::decodeName(ftpfilepath);
kioudsentry.insert(KIO::UDSEntry::UDS_NAME, filename);
kioudsentry.insert(KIO::UDSEntry::UDS_URL, p_url.url(KUrl::AddTrailingSlash) + filename);
kioudsentry.insert(KIO::UDSEntry::UDS_FILE_TYPE, stdmode & S_IFMT);
kioudsentry.insert(KIO::UDSEntry::UDS_ACCESS, stdmode & 07777);
kioudsentry.insert(KIO::UDSEntry::UDS_SIZE, ftpsize);

View file

@ -591,19 +591,21 @@ QString FileProtocol::getGroupName(gid_t gid) const
return mGroupcache[gid];
}
bool FileProtocol::createUDSEntry(const QString &filename, const QByteArray &path, UDSEntry &entry,
bool FileProtocol::createUDSEntry(const QString &filename, const QString &path, UDSEntry &entry,
short int details)
{
assert(entry.count() == 0); // by contract :-)
// entry.reserve( 8 ); // speed up QHash insertion
entry.insert(KIO::UDSEntry::UDS_NAME, filename);
entry.insert(KIO::UDSEntry::UDS_URL, path);
mode_t type;
mode_t access;
KDE_struct_stat buff;
if (KDE_lstat(path.data(), &buff) == 0) {
const QByteArray _path(QFile::encodeName(path));
if (KDE_lstat(_path.data(), &buff) == 0) {
if (details > 2) {
entry.insert(KIO::UDSEntry::UDS_DEVICE_ID, buff.st_dev);
entry.insert(KIO::UDSEntry::UDS_INODE, buff.st_ino);
@ -612,11 +614,11 @@ bool FileProtocol::createUDSEntry(const QString &filename, const QByteArray &pat
if (S_ISLNK(buff.st_mode)) {
char buffer2[1000];
::memset(buffer2, 0, 1000 * sizeof(char));
readlink(path.data(), buffer2, 999);
readlink(_path.data(), buffer2, 999);
entry.insert(KIO::UDSEntry::UDS_LINK_DEST, QFile::decodeName(buffer2));
// A symlink -> follow it only if details>1
if (details > 1 && KDE_stat(path.data(), &buff) == -1) {
if (details > 1 && KDE_stat(_path.data(), &buff) == -1) {
// It is a link pointing to nowhere
type = S_IFMT - 1;
access = S_IRWXU | S_IRWXG | S_IRWXO;
@ -629,7 +631,7 @@ bool FileProtocol::createUDSEntry(const QString &filename, const QByteArray &pat
}
}
} else {
// kWarning() << "lstat didn't work on " << path.data();
// kWarning() << "lstat didn't work on " << _path.data();
return false;
}
@ -645,7 +647,7 @@ bool FileProtocol::createUDSEntry(const QString &filename, const QByteArray &pat
if (details > 0) {
/* Append an atom indicating whether the file has extended acl information. If it's a
* directory and it has a default ACL, also append that. */
appendACLAtoms(path, entry, type);
appendACLAtoms(_path, entry, type);
}
#endif

View file

@ -53,7 +53,7 @@ public:
void del(const KUrl &url, bool isfile) final;
private:
bool createUDSEntry(const QString &filename, const QByteArray &path, KIO::UDSEntry &entry,
bool createUDSEntry(const QString &filename, const QString &path, KIO::UDSEntry &entry,
short int details);
int setACL(const char *path, mode_t perm, bool _directoryDefault);

View file

@ -376,42 +376,9 @@ void FileProtocol::listDir(const KUrl &url)
entry.clear();
const QString filename = QFile::decodeName(ep->d_name);
/*
* details == 0 (if statement) is the fast code path.
* We only get the file name and type. After that we emit
* the result.
*
* The else statement is the slow path that requests all
* file information in file.cpp. It executes a stat call
* for every entry thus becoming slower.
*
*/
if (details == 0) {
entry.insert(KIO::UDSEntry::UDS_NAME, filename);
#ifdef HAVE_DIRENT_D_TYPE
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, (ep->d_type == DT_DIR) ? S_IFDIR : S_IFREG);
const bool isSymLink = (ep->d_type == DT_LNK);
#else
// oops, no fast way, we need to stat (e.g. on Solaris)
if (KDE_lstat(ep->d_name, &st) == -1) {
continue; // how can stat fail?
}
entry.insert(KIO::UDSEntry::UDS_FILE_TYPE,
(S_ISDIR(st.st_mode)) ? S_IFDIR : S_IFREG );
const bool isSymLink = S_ISLNK(st.st_mode);
#endif
if (isSymLink) {
// for symlinks obey the UDSEntry contract and provide UDS_LINK_DEST
// even if we don't know the link dest (and DeleteJob doesn't care...)
entry.insert(KIO::UDSEntry::UDS_LINK_DEST, QLatin1String("Dummy Link Target"));
}
const QString filepath = path + QDir::separator() + filename;
if (createUDSEntry(filename, filepath, entry, details)) {
listEntry(entry, false);
} else {
if (createUDSEntry(filename, QByteArray(ep->d_name), entry, details)) {
listEntry(entry, false);
}
}
}
@ -611,13 +578,12 @@ void FileProtocol::stat(const KUrl &url)
return;
}
const QString path(url.path(KUrl::RemoveTrailingSlash));
const QByteArray _path(QFile::encodeName(path));
const QString path(url.path());
const QString sDetails = metaData(QLatin1String("details"));
const int details = (sDetails.isEmpty() ? 2 : sDetails.toInt());
UDSEntry entry;
if (!createUDSEntry(url.fileName(), _path, entry, details)) {
if (!createUDSEntry(url.fileName(), path, entry, details)) {
error(KIO::ERR_DOES_NOT_EXIST, path);
return;
}