00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kar.h"
00021
00022 #include <QtCore/QFile>
00023 #include <QtCore/QDir>
00024 #include <time.h>
00025 #include <kdebug.h>
00026 #include <kmimetype.h>
00027 #include <QtCore/QRegExp>
00028
00029 #include "kfilterdev.h"
00030
00031
00035
00036 class KAr::KArPrivate
00037 {
00038 public:
00039 KArPrivate() {}
00040 };
00041
00042 KAr::KAr( const QString& filename )
00043 : KArchive( filename ), d(new KArPrivate)
00044 {
00045 }
00046
00047 KAr::KAr( QIODevice * dev )
00048 : KArchive( dev ), d(new KArPrivate)
00049 {
00050 }
00051
00052 KAr::~KAr()
00053 {
00054 if( isOpen() )
00055 close();
00056 delete d;
00057 }
00058
00059 bool KAr::doPrepareWriting( const QString&, const QString&, const QString&,
00060 qint64, mode_t, time_t, time_t, time_t )
00061 {
00062 return false;
00063 }
00064
00065 bool KAr::doFinishWriting( qint64 )
00066 {
00067 return false;
00068 }
00069
00070 bool KAr::doWriteDir( const QString&, const QString&, const QString&,
00071 mode_t, time_t, time_t, time_t )
00072 {
00073 return false;
00074 }
00075
00076 bool KAr::doWriteSymLink( const QString&, const QString&, const QString&,
00077 const QString&, mode_t, time_t, time_t, time_t )
00078 {
00079 return false;
00080 }
00081
00082 bool KAr::openArchive( QIODevice::OpenMode mode )
00083 {
00084
00085
00086 if ( mode == QIODevice::WriteOnly )
00087 return true;
00088 if ( mode != QIODevice::ReadOnly && mode != QIODevice::ReadWrite )
00089 {
00090 kWarning(7042) << "Unsupported mode " << mode;
00091 return false;
00092 }
00093
00094 QIODevice* dev = device();
00095 if ( !dev )
00096 return false;
00097
00098 QByteArray magic = dev->read( 7 );
00099 if ( magic != "!<arch>" ) {
00100 kWarning(7042) << "Invalid main magic";
00101 return false;
00102 }
00103
00104 char *ar_longnames = 0;
00105 while (! dev->atEnd()) {
00106 QByteArray ar_header;
00107 ar_header.resize(61);
00108 QByteArray name;
00109 int date, uid, gid, mode;
00110 qint64 size;
00111
00112 dev->seek( dev->pos() + (2 - (dev->pos() % 2)) % 2 );
00113
00114 if ( dev->read(ar_header.data(), 60) != 60 ) {
00115 kWarning(7042) << "Couldn't read header";
00116 delete[] ar_longnames;
00117
00118 return true;
00119 }
00120
00121 if (!ar_header.endsWith("`\n")) {
00122 kWarning(7042) << "Invalid magic";
00123 delete[] ar_longnames;
00124 return false;
00125 }
00126
00127 name = ar_header.mid( 0, 16 );
00128 date = ar_header.mid( 16, 12 ).toInt();
00129 uid = ar_header.mid( 28, 6 ).toInt();
00130 gid = ar_header.mid( 34, 6 ).toInt();
00131 mode = ar_header.mid( 40, 8 ).toInt();
00132 size = ar_header.mid( 48, 10 ).toInt();
00133
00134 bool skip_entry = false;
00135 if (name.mid(0, 1) == "/") {
00136 if (name.mid(1, 1) == "/") {
00137 delete[] ar_longnames;
00138 ar_longnames = new char[size + 1];
00139 ar_longnames[size] = '\0';
00140 dev->read(ar_longnames, size);
00141 skip_entry = true;
00142 kDebug(7042) << "Read in longnames entry";
00143 } else if (name.mid(1, 1) == " ") {
00144 kDebug(7042) << "Skipped symbol entry";
00145 dev->seek( dev->pos() + size );
00146 skip_entry = true;
00147 } else {
00148 kDebug(7042) << "Longfilename #" << name.mid(1, 15).toInt();
00149 if (! ar_longnames) {
00150 kWarning(7042) << "Invalid longfilename reference";
00151 delete[] ar_longnames;
00152 return false;
00153 }
00154 name = &ar_longnames[name.mid(1, 15).toInt()];
00155 name = name.left(name.indexOf("/"));
00156 }
00157 }
00158 if (skip_entry) continue;
00159
00160 name = name.trimmed();
00161 name.replace( '/', QByteArray() );
00162 kDebug(7042) << "Filename: " << name << " Size: " << size;
00163
00164 KArchiveEntry* entry;
00165 entry = new KArchiveFile(this, name, mode, date, 0, 0, 0, dev->pos(), size);
00166 rootDir()->addEntry(entry);
00167
00168 dev->seek( dev->pos() + size );
00169 }
00170 delete[] ar_longnames;
00171
00172 return true;
00173 }
00174
00175 bool KAr::closeArchive()
00176 {
00177
00178 return true;
00179 }
00180
00181 void KAr::virtual_hook( int id, void* data )
00182 { KArchive::virtual_hook( id, data ); }