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
00085
char magic[8];
00086 dev->
readBlock (magic, 8);
00087
if (qstrncmp(magic,
"!<arch>", 7) != 0) {
00088
kdWarning(7042) <<
"Invalid main magic" <<
endl;
00089
return false;
00090 }
00091
00092
char *ar_longnames = 0;
00093
while (! dev->
atEnd()) {
00094
QCString ar_header;
00095 ar_header.
resize(61);
00096
QCString name;
00097
int date, uid, gid, mode, size;
00098
00099 dev->
at( dev->
at() + (2 - (dev->
at() % 2)) % 2 );
00100
00101
if ( dev->
readBlock (ar_header.data(), 60) != 60 ) {
00102
kdWarning(7042) <<
"Couldn't read header" <<
endl;
00103
delete[] ar_longnames;
00104
00105
return true;
00106 }
00107
00108
if (ar_header.
right(2) !=
"`\n") {
00109
kdWarning(7042) <<
"Invalid magic" <<
endl;
00110
delete[] ar_longnames;
00111
return false;
00112 }
00113
00114 name = ar_header.
mid( 0, 16 );
00115 date = ar_header.
mid( 16, 12 ).toInt();
00116 uid = ar_header.
mid( 28, 6 ).toInt();
00117 gid = ar_header.
mid( 34, 6 ).toInt();
00118 mode = ar_header.
mid( 40, 8 ).toInt();
00119 size = ar_header.
mid( 48, 10 ).toInt();
00120
00121
bool skip_entry =
false;
00122
if (name.
mid(0, 1) ==
"/") {
00123
if (name.
mid(1, 1) ==
"/") {
00124
delete[] ar_longnames;
00125 ar_longnames =
new char[size + 1];
00126 ar_longnames[size] =
'\0';
00127 dev->
readBlock (ar_longnames, size);
00128 skip_entry =
true;
00129
kdDebug(7042) <<
"Read in longnames entry" <<
endl;
00130 }
else if (name.
mid(1, 1) ==
" ") {
00131
kdDebug(7042) <<
"Skipped symbol entry" <<
endl;
00132 dev->
at( dev->
at() + size );
00133 skip_entry =
true;
00134 }
else {
00135
kdDebug(7042) <<
"Longfilename #" << name.
mid(1, 15).toInt() <<
endl;
00136
if (! ar_longnames) {
00137
kdWarning(7042) <<
"Invalid longfilename reference" <<
endl;
00138
return false;
00139 }
00140 name = &ar_longnames[name.
mid(1, 15).toInt()];
00141 name = name.
left(name.
find(
"/"));
00142 }
00143 }
00144
if (skip_entry)
continue;
00145
00146 name = name.
stripWhiteSpace();
00147 name.
replace(
"/",
"" );
00148
kdDebug(7042) <<
"Filename: " << name <<
" Size: " << size <<
endl;
00149
00150
KArchiveEntry* entry;
00151 entry =
new KArchiveFile(
this, name, mode, date, 0, 0, 0, dev->
at(), size);
00152
rootDir()->
addEntry(entry);
00153
00154 dev->
at( dev->
at() + size );
00155 }
00156
delete[] ar_longnames;
00157
00158
return true;
00159 }
00160
00161 bool KAr::closeArchive()
00162 {
00163
00164
return true;
00165 }
00166
00167
void KAr::virtual_hook(
int id,
void* data )
00168 { KArchive::virtual_hook(
id, data ); }