BundleInstaller::BundleStatus EmoticonSetInstaller::validate() { kDebug(); KArchiveEntry *currentEntry = 0L; KArchiveDirectory* currentDir = 0L; if(m_archive == 0) exit(1); m_archive->fileName(); m_archive->directory(); const KArchiveDirectory* rootDir = m_archive->directory(); const QStringList entries = rootDir->entries(); // Will be reused later. QStringList::ConstIterator entriesIt; for (entriesIt = entries.begin(); entriesIt != entries.end(); ++entriesIt) { currentEntry = const_cast<KArchiveEntry*>(rootDir->entry(*entriesIt)); kDebug() << "Current entry name: " << currentEntry->name(); if (currentEntry->isDirectory()) { currentDir = dynamic_cast<KArchiveDirectory*>(currentEntry); if (currentDir) { if (currentDir->entry(QString::fromUtf8("Emoticons.plist"))) { kDebug() << "Emoticons.plist found"; QString currentItem = currentEntry->name(); if(m_bundleName.isEmpty() && currentItem.endsWith(QLatin1String(".AdiumEmoticonset"))) { m_bundleName = currentItem.remove(QLatin1String(".AdiumEmoticonset")); } return BundleValid; } } } } return BundleNotValid; }
QStringList IconThemesConfig::findThemeDirs(const QString &archiveName) { QStringList foundThemes; KTar archive(archiveName); archive.open(IO_ReadOnly); const KArchiveDirectory* themeDir = archive.directory(); KArchiveEntry* possibleDir = 0L; KArchiveDirectory* subDir = 0L; // iterate all the dirs looking for an index.theme or index.desktop file QStringList entries = themeDir->entries(); for (QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) { possibleDir = const_cast<KArchiveEntry*>(themeDir->entry(*it)); if (possibleDir->isDirectory()) { subDir = dynamic_cast<KArchiveDirectory*>( possibleDir ); if (subDir && (subDir->entry("index.theme") != NULL || subDir->entry("index.desktop") != NULL)) foundThemes.append(subDir->name()); } } archive.close(); return foundThemes; }
KArchiveDirectory *KArchive::findOrCreate(const QString &path) { //qCDebug(KArchiveLog) << path; if (path.isEmpty() || path == QLatin1String("/") || path == QLatin1String(".")) { // root dir => found //qCDebug(KArchiveLog) << "returning rootdir"; return rootDir(); } // Important note : for tar files containing absolute paths // (i.e. beginning with "/"), this means the leading "/" will // be removed (no KDirectory for it), which is exactly the way // the "tar" program works (though it displays a warning about it) // See also KArchiveDirectory::entry(). // Already created ? => found const KArchiveEntry *ent = rootDir()->entry(path); if (ent) { if (ent->isDirectory()) //qCDebug(KArchiveLog) << "found it"; { const KArchiveDirectory *dir = static_cast<const KArchiveDirectory *>(ent); return const_cast<KArchiveDirectory *>(dir); } else { const KArchiveFile *file = static_cast<const KArchiveFile *>(ent); if (file->size() > 0) { qCWarning(KArchiveLog) << path << "is normal file, but there are file paths in the archive assuming it is a directory, bailing out"; return nullptr; } qCDebug(KArchiveLog) << path << " is an empty file, assuming it is actually a directory and replacing"; KArchiveEntry *myEntry = const_cast<KArchiveEntry*>(ent); rootDir()->removeEntry(myEntry); delete myEntry; } } // Otherwise go up and try again int pos = path.lastIndexOf(QLatin1Char('/')); KArchiveDirectory *parent; QString dirname; if (pos == -1) { // no more slash => create in root dir parent = rootDir(); dirname = path; } else { QString left = path.left(pos); dirname = path.mid(pos + 1); parent = findOrCreate(left); // recursive call... until we find an existing dir. } //qCDebug(KArchiveLog) << "found parent " << parent->name() << " adding " << dirname << " to ensure " << path; // Found -> add the missing piece KArchiveDirectory *e = new KArchiveDirectory(this, dirname, d->rootDir->permissions(), d->rootDir->date(), d->rootDir->user(), d->rootDir->group(), QString()); parent->addEntry(e); return e; // now a directory to <path> exists }
KArchiveDirectory * KArchiveHandler::findOrCreate( const QString & path ) { //qDebug() << path; if ( path.isEmpty() || path == QLatin1String("/") || path == QLatin1String(".") ) // root dir => found { //qDebug() << "returning rootdir"; return rootDir(); } // Important note : for tar files containing absolute paths // (i.e. beginning with "/"), this means the leading "/" will // be removed (no KDirectory for it), which is exactly the way // the "tar" program works (though it displays a warning about it) // See also KArchiveDirectory::entry(). // Already created ? => found const KArchiveEntry* ent = rootDir()->entry( path ); if ( ent ) { if ( ent->isDirectory() ) //qDebug() << "found it"; return (KArchiveDirectory *) ent; else { //qWarning() << "Found" << path << "but it's not a directory"; } } // Otherwise go up and try again int pos = path.lastIndexOf( QLatin1Char('/') ); KArchiveDirectory * parent; QString dirname; if ( pos == -1 ) // no more slash => create in root dir { parent = rootDir(); dirname = path; } else { QString left = path.left( pos ); dirname = path.mid( pos + 1 ); parent = findOrCreate( left ); // recursive call... until we find an existing dir. } //qDebug() << "found parent " << parent->name() << " adding " << dirname << " to ensure " << path; // Found -> add the missing piece KArchiveDirectory * e = new KArchiveDirectory( d->archive, dirname, d->rootDir->permissions(), d->rootDir->date(), d->rootDir->user(), d->rootDir->group(), QString() ); parent->addEntry( e ); return e; // now a directory to <path> exists }
bool IconThemesConfig::installThemes(const QStringList &themes, const QString &archiveName) { bool everythingOk = true; QString localThemesDir(locateLocal("icon", "./")); KProgressDialog progressDiag(this, "themeinstallprogress", i18n("Installing icon themes"), QString::null, true); progressDiag.setAutoClose(true); progressDiag.progressBar()->setTotalSteps(themes.count()); progressDiag.show(); KTar archive(archiveName); archive.open(IO_ReadOnly); kapp->processEvents(); const KArchiveDirectory* rootDir = archive.directory(); KArchiveDirectory* currentTheme; for (QStringList::ConstIterator it = themes.begin(); it != themes.end(); ++it) { progressDiag.setLabel( i18n("<qt>Installing <strong>%1</strong> theme</qt>") .arg(*it)); kapp->processEvents(); if (progressDiag.wasCancelled()) break; currentTheme = dynamic_cast<KArchiveDirectory*>( const_cast<KArchiveEntry*>( rootDir->entry(*it))); if (currentTheme == NULL) { // we tell back that something went wrong, but try to install as much // as possible everythingOk = false; continue; } currentTheme->copyTo(localThemesDir + *it); progressDiag.progressBar()->advance(1); } archive.close(); return everythingOk; }
bool KPak::openArchive(int mode) { kdDebug(7000) << "openArchiving!"; if ( mode == IO_WriteOnly ) return true; if ( mode != IO_ReadOnly && mode != IO_ReadWrite ) { kdWarning(7000) << "Unsupported mode " << mode << endl; return false; } QIODevice *dev = device(); if (!dev) return false; _pakFile = new libPak(dev); if (!_pakFile->isValidPak()) { kdWarning(7000) << "Invalid file magic" << endl; return false; } QValueList<libPak::PakFile> files(_pakFile->getAllFiles()); for ( QValueList<libPak::PakFile>::Iterator it = files.begin(); it != files.end(); ++it ) { QString temp((*it).filename.mid(1)); temp.replace("\\", "/"); int pos = temp.findRev("/"); QString file; file = temp.mid(pos + 1); // TODO: Add position and size KArchiveEntry *e = new KArchiveFile(this, file, 0444, 0, /*uid*/0, /*gid*/0, /*symlink*/0, (int)(*it).offset, (*it).size); if (pos == -1) { rootDir()->addEntry(e); } else { QString path = QDir::cleanDirPath( (*it).filename.mid(1).replace("\\", "/").left(pos) ); KArchiveDirectory *d = findOrCreate(path); d->addEntry(e); } } return true; }
QStringList KEmoticons::installTheme(const QString &archiveName) { QStringList foundThemes; KArchiveEntry *currentEntry = 0L; KArchiveDirectory* currentDir = 0L; KArchive *archive = 0L; QString localThemesDir(KStandardDirs::locateLocal("emoticons", QString())); if (localThemesDir.isEmpty()) { kError() << "Could not find a suitable place in which to install the emoticon theme"; return QStringList(); } const QString currentBundleMimeType = KMimeType::findByPath(archiveName, 0, false)->name(); if (currentBundleMimeType == "application/zip" || currentBundleMimeType == "application/x-zip" || currentBundleMimeType == "application/x-zip-compressed") { archive = new KZip(archiveName); } else if (currentBundleMimeType == "application/x-compressed-tar" || currentBundleMimeType == "application/x-bzip-compressed-tar" || currentBundleMimeType == "application/x-lzma-compressed-tar" || currentBundleMimeType == "application/x-xz-compressed-tar" || currentBundleMimeType == "application/x-gzip" || currentBundleMimeType == "application/x-bzip" || currentBundleMimeType == "application/x-lzma" || currentBundleMimeType == "application/x-xz") { archive = new KTar(archiveName); } else if (archiveName.endsWith(QLatin1String("jisp")) || archiveName.endsWith(QLatin1String("zip"))) { archive = new KZip(archiveName); } else { archive = new KTar(archiveName); } if (!archive || !archive->open(QIODevice::ReadOnly)) { kError() << "Could not open" << archiveName << "for unpacking"; delete archive; return QStringList(); } const KArchiveDirectory* rootDir = archive->directory(); // iterate all the dirs looking for an emoticons.xml file const QStringList entries = rootDir->entries(); for (QStringList::ConstIterator it = entries.begin(); it != entries.end(); ++it) { currentEntry = const_cast<KArchiveEntry*>(rootDir->entry(*it)); if (currentEntry->isDirectory()) { currentDir = dynamic_cast<KArchiveDirectory*>(currentEntry); for (int i = 0; i < d->m_loaded.size(); ++i) { QString fName = d->m_loaded.at(i)->property("X-KDE-EmoticonsFileName").toString(); if (currentDir && currentDir->entry(fName) != NULL) { foundThemes.append(currentDir->name()); } } } } if (foundThemes.isEmpty()) { kError() << "The file" << archiveName << "is not a valid emoticon theme archive"; archive->close(); delete archive; return QStringList(); } for (int themeIndex = 0; themeIndex < foundThemes.size(); ++themeIndex) { const QString &theme = foundThemes[themeIndex]; currentEntry = const_cast<KArchiveEntry *>(rootDir->entry(theme)); if (currentEntry == 0) { kDebug() << "couldn't get next archive entry"; continue; } if (currentEntry->isDirectory()) { currentDir = dynamic_cast<KArchiveDirectory*>(currentEntry); if (currentDir == 0) { kDebug() << "couldn't cast archive entry to KArchiveDirectory"; continue; } currentDir->copyTo(localThemesDir + theme); } } archive->close(); delete archive; return foundThemes; }
void KArchiveDirectory::copyTo(const QString &dest, bool recursiveCopy) const { QDir root; PosSortedPtrList fileList; QMap< int, QString > fileToDir; QStringList::Iterator it; // placeholders for iterated items KArchiveDirectory *curDir; QString curDirName; QStringList dirEntries; KArchiveEntry *curEntry; KArchiveFile *curFile; QPtrStack< KArchiveDirectory > dirStack; QValueStack< QString > dirNameStack; dirStack.push(this); // init stack at current directory dirNameStack.push(dest); // ... with given path do { curDir = dirStack.pop(); curDirName = dirNameStack.pop(); root.mkdir(curDirName); dirEntries = curDir->entries(); for(it = dirEntries.begin(); it != dirEntries.end(); ++it) { curEntry = curDir->entry(*it); if(!curEntry->symlink().isEmpty()) { const QString linkName = curDirName + '/' + curEntry->name(); kdDebug() << "symlink(" << curEntry->symlink() << ',' << linkName << ')'; if(!::symlink(curEntry->symlink().local8Bit(), linkName.local8Bit())) { kdDebug() << "symlink(" << curEntry->symlink() << ',' << linkName << ") failed:" << strerror(errno); } } else { if(curEntry->isFile()) { curFile = dynamic_cast< KArchiveFile * >(curEntry); if(curFile) { fileList.append(curFile); fileToDir.insert(curFile->position(), curDirName); } } if(curEntry->isDirectory()) if(recursiveCopy) { KArchiveDirectory *ad = dynamic_cast< KArchiveDirectory * >(curEntry); if(ad) { dirStack.push(ad); dirNameStack.push(curDirName + "/" + curEntry->name()); } } } } } while(!dirStack.isEmpty()); fileList.sort(); // sort on m_pos, so we have a linear access KArchiveFile *f; for(f = fileList.first(); f; f = fileList.next()) { int pos = f->position(); f->copyTo(fileToDir[pos]); } }
bool KTar::openArchive( QIODevice::OpenMode mode ) { if ( !(mode & QIODevice::ReadOnly) ) return true; if ( !d->fillTempFile( fileName() ) ) return false; // We'll use the permission and user/group of d->rootDir // for any directory we emulate (see findOrCreate) //struct stat buf; //stat( fileName(), &buf ); d->dirList.clear(); QIODevice* dev = device(); if ( !dev ) return false; // read dir information char buffer[ 0x200 ]; bool ende = false; do { QString name; QString symlink; // Read header qint64 n = d->readHeader( buffer, name, symlink ); if (n < 0) return false; if (n == 0x200) { bool isdir = false; if ( name.endsWith( QLatin1Char( '/' ) ) ) { isdir = true; name.truncate( name.length() - 1 ); } QByteArray prefix = QByteArray(buffer + 0x159, 155); if (prefix[0] != '\0') { name = (QString::fromLatin1(prefix.constData()) + QLatin1Char('/') + name); } int pos = name.lastIndexOf( QLatin1Char('/') ); QString nm = ( pos == -1 ) ? name : name.mid( pos + 1 ); // read access buffer[ 0x6b ] = 0; char *dummy; const char* p = buffer + 0x64; while( *p == ' ' ) ++p; int access = (int)strtol( p, &dummy, 8 ); // read user and group QString user = QString::fromLocal8Bit( buffer + 0x109 ); QString group = QString::fromLocal8Bit( buffer + 0x129 ); // read time buffer[ 0x93 ] = 0; p = buffer + 0x88; while( *p == ' ' ) ++p; uint time = (int)strtol( p, &dummy, 8 ); // read type flag char typeflag = buffer[ 0x9c ]; // '0' for files, '1' hard link, '2' symlink, '5' for directory // (and 'L' for longlink fileNames, 'K' for longlink symlink targets) // 'D' for GNU tar extension DUMPDIR, 'x' for Extended header referring // to the next file in the archive and 'g' for Global extended header if ( typeflag == '5' ) isdir = true; bool isDumpDir = false; if ( typeflag == 'D' ) { isdir = false; isDumpDir = true; } //qDebug() << nm << "isdir=" << isdir << "pos=" << dev->pos() << "typeflag=" << typeflag << " islink=" << ( typeflag == '1' || typeflag == '2' ); if (typeflag == 'x' || typeflag == 'g') { // pax extended header, or pax global extended header // Skip it for now. TODO: implement reading of extended header, as per http://pubs.opengroup.org/onlinepubs/009695399/utilities/pax.html (void)dev->read( buffer, 0x200 ); continue; } if (isdir) access |= S_IFDIR; // f*cking broken tar files KArchiveEntry* e; if ( isdir ) { //qDebug() << "directory" << nm; e = new KArchiveDirectory( this, nm, access, KArchivePrivate::time_tToDateTime(time), user, group, symlink ); } else { // read size QByteArray sizeBuffer( buffer + 0x7c, 12 ); qint64 size = sizeBuffer.trimmed().toLongLong( 0, 8 /*octal*/ ); //qDebug() << "sizeBuffer='" << sizeBuffer << "' -> size=" << size; // for isDumpDir we will skip the additional info about that dirs contents if ( isDumpDir ) { //qDebug() << nm << "isDumpDir"; e = new KArchiveDirectory( this, nm, access, KArchivePrivate::time_tToDateTime(time), user, group, symlink ); } else { // Let's hack around hard links. Our classes don't support that, so make them symlinks if ( typeflag == '1' ) { //qDebug() << "Hard link, setting size to 0 instead of" << size; size = 0; // no contents } //qDebug() << "file" << nm << "size=" << size; e = new KArchiveFile( this, nm, access, KArchivePrivate::time_tToDateTime(time), user, group, symlink, dev->pos(), size ); } // Skip contents + align bytes qint64 rest = size % 0x200; qint64 skip = size + (rest ? 0x200 - rest : 0); //qDebug() << "pos()=" << dev->pos() << "rest=" << rest << "skipping" << skip; if (! dev->seek( dev->pos() + skip ) ) { //qWarning() << "skipping" << skip << "failed"; } } if ( pos == -1 ) { if (nm == QLatin1String(".")) { // special case Q_ASSERT( isdir ); if (isdir) { setRootDir( static_cast<KArchiveDirectory *>( e ) ); } } else { rootDir()->addEntry( e ); } } else { // In some tar files we can find dir/./file => call cleanPath QString path = QDir::cleanPath( name.left( pos ) ); // Ensure container directory exists, create otherwise KArchiveDirectory * d = findOrCreate( path ); d->addEntry( e ); } } else { //qDebug("Terminating. Read %d bytes, first one is %d", n, buffer[0]); d->tarEnd = dev->pos() - n; // Remember end of archive ende = true; } } while( !ende ); return true; }
bool KIso::openArchive(QIODevice::OpenMode mode) { KISOFUNC; iso_vol_desc *desc; QString path, uid, gid; QT_STATBUF buf; int tracks[2*100], trackno = 0, i, access, c_b, c_i, c_j; KArchiveDirectory *root; struct iso_directory_record* idr; struct el_torito_boot_descriptor* bootdesc; if (mode == QIODevice::WriteOnly) return false; readParams(); d->dirList.clear(); tracks[0] = 0; if (m_startsec > 0) tracks[0] = m_startsec; //qDebug() << " m_startsec: " << m_startsec << endl; /* We'll use the permission and user/group of the 'host' file except * in Rock Ridge, where the permissions are stored on the file system */ if (QT_STAT(m_filename.toLocal8Bit(), &buf) < 0) { /* defaults, if stat fails */ memset(&buf, 0, sizeof(struct stat)); buf.st_mode = 0777; } else { /* If it's a block device, try to query the track layout (for multisession) */ if (m_startsec == -1 && S_ISBLK(buf.st_mode)) trackno = getTracks(m_filename.toLatin1(), (int*) & tracks); } uid.setNum(buf.st_uid); gid.setNum(buf.st_gid); access = buf.st_mode & ~S_IFMT; //qDebug() << "KIso::openArchive number of tracks: " << trackno << endl; if (trackno == 0) trackno = 1; for (i = 0;i < trackno;++i) { c_b = 1;c_i = 1;c_j = 1; root = rootDir(); if (trackno > 1) { path.clear(); QTextStream(&path) << "Track " << tracks[(i<<1)+1]; root = new KIsoDirectory(this, path, access | S_IFDIR, buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString()); rootDir()->addEntry(root); } desc = ReadISO9660(&readf, tracks[i<<1], this); if (!desc) { //qDebug() << "KIso::openArchive no volume descriptors" << endl; continue; } while (desc) { switch (isonum_711(desc->data.type)) { case ISO_VD_BOOT: bootdesc = (struct el_torito_boot_descriptor*) & (desc->data); if (!memcmp(EL_TORITO_ID, bootdesc->system_id, ISODCL(8, 39))) { path = "El Torito Boot"; if (c_b > 1) path += " (" + QString::number(c_b) + ')'; dirent = new KIsoDirectory(this, path, access | S_IFDIR, buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString()); root->addEntry(dirent); addBoot(bootdesc); c_b++; } break; case ISO_VD_PRIMARY: case ISO_VD_SUPPLEMENTARY: idr = (struct iso_directory_record*) & (((struct iso_primary_descriptor*) & desc->data)->root_directory_record); joliet = JolietLevel(&desc->data); if (joliet) { QTextStream(&path) << "Joliet level " << joliet; if (c_j > 1) path += " (" + QString::number(c_j) + ')'; } else { path = "ISO9660"; if (c_i > 1) path += " (" + QString::number(c_i) + ')'; } dirent = new KIsoDirectory(this, path, access | S_IFDIR, buf.st_mtime, buf.st_atime, buf.st_ctime, uid, gid, QString()); root->addEntry(dirent); level = 0; mycallb(idr, this); if (joliet) c_j++; else c_i++; break; } desc = desc->next; } free(desc); } device()->close(); return true; }