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