kio Library API Documentation

kar.cpp

00001 
00002 /* This file is part of the KDE libraries
00003    Copyright (C) 2002 Laurence Anderson <l.d.anderson@warwick.ac.uk>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
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 //#include "klimitediodevice.h"
00031 
00035 
00036 class KAr::KArPrivate
00037 {
00038 public:
00039     KArPrivate() {}
00040 };
00041 
00042 KAr::KAr( const QString& filename )
00043     : KArchive( 0L )
00044 {
00045     //kdDebug(7042) << "KAr(filename) reached." << endl;
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     //kdDebug(7042) << "KAr::KAr( QIODevice * dev) reached." << endl;
00055     d = new KArPrivate;
00056 }
00057 
00058 KAr::~KAr()
00059 {
00060     // mjarrett: Closes to prevent ~KArchive from aborting w/o device
00061     //kdDebug(7042) << "~KAr reached." << endl;
00062     if( isOpened() )
00063         close();
00064     if ( !m_filename.isEmpty() )
00065         delete device(); // we created it ourselves
00066     delete d;
00067 }
00068 
00069 bool KAr::openArchive( int mode )
00070 {
00071     // Open archive
00072     
00073     //kdDebug(7042) << "openarchive reached." << endl;
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 ); // Ar headers are padded to byte boundry
00100 
00101         if ( dev->readBlock (ar_header.data(), 60) != 60 ) { // Read ar header
00102             kdWarning(7042) << "Couldn't read header" << endl;
00103             if (ar_longnames) delete[] ar_longnames;
00104             //return false;
00105             return true; // Probably EOF / trailing junk
00106         }
00107 
00108         if (ar_header.right(2) != "`\n") { // Check header magic
00109             kdWarning(7042) << "Invalid magic" << endl;
00110             if (ar_longnames) delete[] ar_longnames;
00111             return false;
00112         }
00113 
00114         name = ar_header.mid( 0, 16 ); // Process header
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; // Deal with special entries
00122         if (name.mid(0, 1) == "/") {
00123             if (name.mid(1, 1) == "/") { // Longfilename table entry
00124                 if (ar_longnames) 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) == " ") { // Symbol table entry
00131                 kdDebug(7042) << "Skipped symbol entry" << endl;
00132                 dev->at( dev->at() + size );
00133                 skip_entry = true;
00134             } else { // Longfilename
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(); // Process filename
00147         name.replace( QRegExp("/"), "" );
00148         kdDebug(7042) << "Filename: " << name << " Size: " << size << endl;
00149 
00150         KArchiveEntry* entry;
00151         entry = new KArchiveFile(this, name, mode, date, /*uid*/ 0, /*gid*/ 0, 0, dev->at(), size);
00152         rootDir()->addEntry(entry); // Ar files don't support directorys, so everything in root    
00153         
00154         dev->at( dev->at() + size ); // Skip contents
00155     }
00156     if (ar_longnames) delete[] ar_longnames;
00157 
00158     return true;
00159 }
00160 
00161 bool KAr::closeArchive()
00162 {
00163     // Close the archive
00164     return true;
00165 }
00166 
00167 void KAr::virtual_hook( int id, void* data )
00168 { KArchive::virtual_hook( id, data ); }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:13:05 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001