41#include "kfilterdev.h"
42#include "klimitediodevice.h"
47#include <tqasciidict.h>
50#include <tqdatetime.h>
57const int max_path_len = 4095;
59static void transformToMsDos(
const TQDateTime& dt,
char* buffer)
63 const TQ_UINT16 time =
64 ( dt.time().hour() << 11 )
65 | ( dt.time().minute() << 5 )
66 | ( dt.time().second() >> 1 );
68 buffer[0] = char(time);
69 buffer[1] = char(time >> 8);
71 const TQ_UINT16 date =
72 ( ( dt.date().year() - 1980 ) << 9 )
73 | ( dt.date().month() << 5 )
74 | ( dt.date().day() );
76 buffer[2] = char(date);
77 buffer[3] = char(date >> 8);
88static time_t transformFromMsDos(
const char* buffer)
90 TQ_UINT16 time = (uchar)buffer[0] | ( (uchar)buffer[1] << 8 );
92 int m = ( time & 0x7ff ) >> 5;
93 int s = ( time & 0x1f ) * 2 ;
96 TQ_UINT16 date = (uchar)buffer[2] | ( (uchar)buffer[3] << 8 );
97 int y = ( date >> 9 ) + 1980;
98 int o = ( date & 0x1ff ) >> 5;
99 int d = ( date & 0x1f );
102 TQDateTime dt( qd, qt );
103 return dt.toTime_t();
109struct ParseFileInfo {
118 TQCString guessed_symlink;
122 bool exttimestamp_seen;
124 bool newinfounix_seen;
127 ParseFileInfo() : perm(0100644), uid(-1), gid(-1), extralen(0),
128 exttimestamp_seen(false), newinfounix_seen(false) {
129 ctime = mtime = atime = time(0);
141static bool parseExtTimestamp(
const char *buffer,
int size,
bool islocal,
142 ParseFileInfo &pfi) {
144 kdDebug(7040) <<
"premature end of extended timestamp (#1)" << endl;
153 kdDebug(7040) <<
"premature end of extended timestamp (#2)" << endl;
156 pfi.mtime = time_t((uchar)buffer[0] | (uchar)buffer[1] << 8
157 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
164 pfi.exttimestamp_seen =
true;
170 kdDebug(7040) <<
"premature end of extended timestamp (#3)" << endl;
173 pfi.atime = time_t((uchar)buffer[0] | (uchar)buffer[1] << 8
174 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
181 kdDebug(7040) <<
"premature end of extended timestamp (#4)" << endl;
184 pfi.ctime = time_t((uchar)buffer[0] | (uchar)buffer[1] << 8
185 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
189 pfi.exttimestamp_seen =
true;
201static bool parseInfoZipUnixOld(
const char *buffer,
int size,
bool islocal,
202 ParseFileInfo &pfi) {
204 if (pfi.exttimestamp_seen || pfi.newinfounix_seen)
return true;
207 kdDebug(7040) <<
"premature end of Info-ZIP unix extra field old" << endl;
211 pfi.atime = time_t((uchar)buffer[0] | (uchar)buffer[1] << 8
212 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
214 pfi.mtime = time_t((uchar)buffer[0] | (uchar)buffer[1] << 8
215 | (uchar)buffer[2] << 16 | (uchar)buffer[3] << 24);
217 if (islocal && size >= 12) {
218 pfi.uid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
220 pfi.gid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
235static bool parseInfoZipUnixNew(const char *buffer, int size, bool islocal,
236 ParseFileInfo &pfi) {
238 pfi.newinfounix =
true;
243 kdDebug(7040) <<
"premature end of Info-ZIP unix extra field new" << endl;
247 pfi.uid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
249 pfi.gid = (uchar)buffer[0] | (uchar)buffer[1] << 8;
252 pfi.newinfounix =
true;
265static bool parseExtraField(
const char *buffer,
int size,
bool islocal,
266 ParseFileInfo &pfi) {
269 if (!islocal)
return true;
272 int magic = (uchar)buffer[0] | (uchar)buffer[1] << 8;
274 int fieldsize = (uchar)buffer[0] | (uchar)buffer[1] << 8;
278 if (fieldsize > size) {
280 kdDebug(7040) <<
"premature end of extra fields reached" << endl;
286 if (!parseExtTimestamp(buffer, fieldsize, islocal, pfi))
return false;
289 if (!parseInfoZipUnixOld(buffer, fieldsize, islocal, pfi))
return false;
293 if (!parseInfoZipUnixNew(buffer, fieldsize, islocal, pfi))
return false;
310class KZip::KZipPrivate
323 KZipFileEntry* m_currentFile;
324 TQIODevice* m_currentDev;
325 TQPtrList<KZipFileEntry> m_fileList;
328 unsigned int m_offset;
332 KSaveFile* m_saveFile;
339 Q_ASSERT( !filename.isEmpty() );
340 m_filename = filename;
360 if ( !m_filename.isEmpty() ) {
362 delete d->m_saveFile;
372 d->m_fileList.clear();
378 if ( !m_filename.isEmpty() ) {
379 kdDebug(7040) <<
"Writing to a file using KSaveFile" << endl;
380 d->m_saveFile =
new KSaveFile( m_filename );
381 if ( d->m_saveFile->status() != 0 ) {
382 kdWarning(7040) <<
"KSaveFile creation for " << m_filename <<
" failed, " << strerror( d->m_saveFile->status() ) << endl;
383 delete d->m_saveFile;
387 Q_ASSERT( d->m_saveFile->file() );
388 setDevice( d->m_saveFile->file() );
395 if ( !m_filename.isEmpty() ) {
396 setDevice(
new TQFile( m_filename ) );
403 kdWarning(7040) <<
"Unsupported mode " <<
mode << endl;
411 TQIODevice* dev =
device();
421 TQAsciiDict<ParseFileInfo> pfi_map(1009,
true ,
true );
422 pfi_map.setAutoDelete(
true);
425 bool startOfFile =
true;
429kdDebug(7040) <<
"loop starts" << endl;
430kdDebug(7040) <<
"dev->at() now : " << dev->at() << endl;
431 n = dev->readBlock( buffer, 4 );
435 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. (#1)" << endl;
440 if ( !memcmp( buffer,
"PK\5\6", 4 ) )
442 kdDebug(7040) <<
"PK56 found end of archive" << endl;
447 if ( !memcmp( buffer,
"PK\3\4", 4 ) )
449 kdDebug(7040) <<
"PK34 found local file header" << endl;
452 dev->at( dev->at() + 2 );
455 n = dev->readBlock( buffer, 24 );
457 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. (#4)" << endl;
461 int gpf = (uchar)buffer[0];
462 int compression_mode = (uchar)buffer[2] | (uchar)buffer[3] << 8;
463 time_t mtime = transformFromMsDos( buffer+4 );
465 TQ_LONG compr_size = (uchar)buffer[12] | (uchar)buffer[13] << 8
466 | (uchar)buffer[14] << 16 | (uchar)buffer[15] << 24;
467 TQ_LONG uncomp_size = (uchar)buffer[16] | (uchar)buffer[17] << 8
468 | (uchar)buffer[18] << 16 | (uchar)buffer[19] << 24;
469 int namelen = (uchar)buffer[20] | (uchar)buffer[21] << 8;
470 int extralen = (uchar)buffer[22] | (uchar)buffer[23] << 8;
472 kdDebug(7040) <<
"general purpose bit flag: " << gpf << endl;
473 kdDebug(7040) <<
"compressed size: " << compr_size << endl;
474 kdDebug(7040) <<
"uncompressed size: " << uncomp_size << endl;
475 kdDebug(7040) <<
"namelen: " << namelen << endl;
476 kdDebug(7040) <<
"extralen: " << extralen << endl;
477 kdDebug(7040) <<
"archive size: " << dev->size() << endl;
480 TQCString filename(namelen + 1);
481 n = dev->readBlock(filename.data(), namelen);
483 kdWarning(7040) <<
"Invalid ZIP file. Name not completely read (#2)" << endl;
487 ParseFileInfo *pfi =
new ParseFileInfo();
489 pfi_map.insert(filename.data(), pfi);
493 unsigned int extraFieldEnd = dev->at() + extralen;
494 pfi->extralen = extralen;
495 int handledextralen = TQMIN(extralen, (
int)
sizeof buffer);
497 kdDebug(7040) <<
"handledextralen: " << handledextralen << endl;
499 n = dev->readBlock(buffer, handledextralen);
501 if (!parseExtraField(buffer, handledextralen,
true, *pfi))
503 kdWarning(7040) <<
"Invalid ZIP File. Broken ExtraField." << endl;
508 dev->at( extraFieldEnd );
517 kdDebug(7040) <<
"trying to seek for next PK78" << endl;
518 bool foundSignature =
false;
520 while (!foundSignature)
522 n = dev->readBlock( buffer, 1 );
525 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. (#2)" << endl;
529 if ( buffer[0] !=
'P' )
532 n = dev->readBlock( buffer, 3 );
535 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. (#3)" << endl;
544 if ( buffer[0] ==
'K' && buffer[1] == 7 && buffer[2] == 8 )
546 foundSignature =
true;
547 dev->at( dev->at() + 12 );
549 else if ( ( buffer[0] ==
'K' && buffer[1] == 1 && buffer[2] == 2 )
550 || ( buffer[0] ==
'K' && buffer[1] == 3 && buffer[2] == 4 ) )
552 foundSignature =
true;
553 dev->at( dev->at() - 4 );
555 else if ( buffer[0] ==
'P' || buffer[1] ==
'P' || buffer[2] ==
'P' )
558 dev->at( dev->at() - 3 );
566 kdDebug(7040) <<
"general purpose bit flag indicates, that local file header contains valid size" << endl;
569 && uncomp_size <= max_path_len
570 && uncomp_size > 0) {
572 pfi->guessed_symlink.resize(uncomp_size + 1);
573 kdDebug(7040) <<
"guessed symlink size: " << uncomp_size << endl;
574 n = dev->readBlock(pfi->guessed_symlink.data(), uncomp_size);
575 if (n < uncomp_size) {
576 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. (#5)" << endl;
581 if ( compr_size > (TQ_LONG)dev->size() )
585 bool foundSignature =
false;
587 while (!foundSignature)
589 n = dev->readBlock( buffer, 1 );
592 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. (#2)" << endl;
596 if ( buffer[0] !=
'P' )
599 n = dev->readBlock( buffer, 3 );
602 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. (#3)" << endl;
611 if ( buffer[0] ==
'K' && buffer[1] == 7 && buffer[2] == 8 )
613 foundSignature =
true;
614 dev->at( dev->at() + 12 );
617 if ( ( buffer[0] ==
'K' && buffer[1] == 1 && buffer[2] == 2 )
618 || ( buffer[0] ==
'K' && buffer[1] == 3 && buffer[2] == 4 ) )
620 foundSignature =
true;
621 dev->at( dev->at() - 4 );
631 success = dev->at( dev->at() + compr_size );
648 else if ( !memcmp( buffer,
"PK\1\2", 4 ) )
650 kdDebug(7040) <<
"PK12 found central block" << endl;
656 offset = dev->at() - 4;
659 if ( d->m_offset == 0L ) d->m_offset = offset;
661 n = dev->readBlock( buffer + 4, 42 );
663 kdWarning(7040) <<
"Invalid ZIP file, central entry too short" << endl;
670 int namelen = (uchar)buffer[29] << 8 | (uchar)buffer[28];
671 TQCString bufferName( namelen + 1 );
672 n = dev->readBlock( bufferName.data(), namelen );
674 kdWarning(7040) <<
"Invalid ZIP file. Name not completely read" << endl;
676 ParseFileInfo *pfi = pfi_map[bufferName];
678 pfi_map.insert(bufferName.data(), pfi =
new ParseFileInfo());
680 TQString name( TQFile::decodeName(bufferName) );
685 int extralen = (uchar)buffer[31] << 8 | (uchar)buffer[30];
687 int commlen = (uchar)buffer[33] << 8 | (uchar)buffer[32];
689 int cmethod = (uchar)buffer[11] << 8 | (uchar)buffer[10];
695 uint ucsize = (uchar)buffer[27] << 24 | (uchar)buffer[26] << 16 |
696 (uchar)buffer[25] << 8 | (uchar)buffer[24];
698 uint csize = (uchar)buffer[23] << 24 | (uchar)buffer[22] << 16 |
699 (uchar)buffer[21] << 8 | (uchar)buffer[20];
702 uint localheaderoffset = (uchar)buffer[45] << 24 | (uchar)buffer[44] << 16 |
703 (uchar)buffer[43] << 8 | (uchar)buffer[42];
709 int localextralen = pfi->extralen;
715 uint dataoffset = localheaderoffset + 30 + localextralen + namelen;
721 int os_madeby = (uchar)buffer[5];
723 int access = 0100644;
725 if (os_madeby == 3) {
726 access = (uchar)buffer[40] | (uchar)buffer[41] << 8;
731 if ( name.endsWith(
"/" ) )
734 name = name.left( name.length() - 1 );
735 if (os_madeby != 3) access = S_IFDIR | 0755;
736 else Q_ASSERT(access & S_IFDIR);
739 int pos = name.findRev(
'/' );
743 entryName = name.mid( pos + 1 );
744 Q_ASSERT( !entryName.isEmpty() );
749 TQString path = TQDir::cleanDirPath( name );
765 if (S_ISLNK(access)) {
766 symlink = TQFile::decodeName(pfi->guessed_symlink);
768 entry =
new KZipFileEntry(
this, entryName, access, pfi->mtime,
770 symlink, name, dataoffset,
771 ucsize, cmethod, csize );
772 static_cast<KZipFileEntry *
>(entry)->setHeaderStart( localheaderoffset );
774 d->m_fileList.append(
static_cast<KZipFileEntry *
>( entry ) );
786 TQString path = TQDir::cleanDirPath( name.left( pos ) );
789 tdir->addEntry(entry);
794 offset += 46 + commlen + extralen + namelen;
795 bool b = dev->at(offset);
800 else if ( startOfFile )
804 kdDebug(7040) <<
"Try to skip start of file" << endl;
806 bool foundSignature =
false;
808 while (!foundSignature)
810 n = dev->readBlock( buffer, 1 );
813 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. " << k_funcinfo << endl;
817 if ( buffer[0] !=
'P' )
820 n = dev->readBlock( buffer, 3 );
823 kdWarning(7040) <<
"Invalid ZIP file. Unexpected end of file. " << k_funcinfo << endl;
832 if ( buffer[0] ==
'K' && buffer[1] == 3 && buffer[2] == 4 )
834 foundSignature =
true;
835 dev->at( dev->at() - 4 );
837 else if ( buffer[0] ==
'P' || buffer[1] ==
'P' || buffer[2] ==
'P' )
840 dev->at( dev->at() - 3 );
846 kdWarning(7040) <<
"Invalid ZIP file. Unrecognized header at offset " << offset << endl;
857 if ( ! (
mode() & IO_WriteOnly ) )
863 kdDebug() << k_funcinfo <<
"device=" <<
device() << endl;
872 uLong crc = crc32(0L, Z_NULL, 0);
874 TQ_LONG centraldiroffset =
device()->at();
876 TQ_LONG atbackup = centraldiroffset;
877 TQPtrListIterator<KZipFileEntry> it( d->m_fileList );
879 for ( ; it.current() ; ++it )
881 if ( !
device()->at( it.current()->headerStart() + 14 ) )
887 uLong mycrc = it.current()->crc32();
888 buffer[0] = char(mycrc);
889 buffer[1] = char(mycrc >> 8);
890 buffer[2] = char(mycrc >> 16);
891 buffer[3] = char(mycrc >> 24);
893 int mysize1 = it.current()->compressedSize();
894 buffer[4] = char(mysize1);
895 buffer[5] = char(mysize1 >> 8);
896 buffer[6] = char(mysize1 >> 16);
897 buffer[7] = char(mysize1 >> 24);
899 int myusize = it.current()->size();
900 buffer[8] = char(myusize);
901 buffer[9] = char(myusize >> 8);
902 buffer[10] = char(myusize >> 16);
903 buffer[11] = char(myusize >> 24);
905 if (
device()->writeBlock( buffer, 12 ) != 12 )
910 for ( it.toFirst(); it.current() ; ++it )
915 TQCString path = TQFile::encodeName(it.current()->path());
917 const int extra_field_len = 9;
918 int bufferSize = extra_field_len + path.length() + 46;
919 char* buffer =
new char[ bufferSize ];
921 memset(buffer, 0, 46);
932 tqmemmove(buffer, head,
sizeof(head));
934 buffer[ 10 ] = char(it.current()->encoding());
935 buffer[ 11 ] = char(it.current()->encoding() >> 8);
937 transformToMsDos( it.current()->datetime(), &buffer[ 12 ] );
939 uLong mycrc = it.current()->crc32();
940 buffer[ 16 ] = char(mycrc);
941 buffer[ 17 ] = char(mycrc >> 8);
942 buffer[ 18 ] = char(mycrc >> 16);
943 buffer[ 19 ] = char(mycrc >> 24);
945 int mysize1 = it.current()->compressedSize();
946 buffer[ 20 ] = char(mysize1);
947 buffer[ 21 ] = char(mysize1 >> 8);
948 buffer[ 22 ] = char(mysize1 >> 16);
949 buffer[ 23 ] = char(mysize1 >> 24);
951 int mysize = it.current()->size();
952 buffer[ 24 ] = char(mysize);
953 buffer[ 25 ] = char(mysize >> 8);
954 buffer[ 26 ] = char(mysize >> 16);
955 buffer[ 27 ] = char(mysize >> 24);
957 buffer[ 28 ] = char(it.current()->path().length());
958 buffer[ 29 ] = char(it.current()->path().length() >> 8);
960 buffer[ 30 ] = char(extra_field_len);
961 buffer[ 31 ] = char(extra_field_len >> 8);
963 buffer[ 40 ] = char(it.current()->permissions());
964 buffer[ 41 ] = char(it.current()->permissions() >> 8);
966 int myhst = it.current()->headerStart();
967 buffer[ 42 ] = char(myhst);
968 buffer[ 43 ] = char(myhst >> 8);
969 buffer[ 44 ] = char(myhst >> 16);
970 buffer[ 45 ] = char(myhst >> 24);
973 strncpy( buffer + 46, path, path.length() );
977 char *extfield = buffer + 46 + path.length();
982 extfield[4] = 1 | 2 | 4;
985 unsigned long time = (
unsigned long)it.current()->date();
986 extfield[5] = char(time);
987 extfield[6] = char(time >> 8);
988 extfield[7] = char(time >> 16);
989 extfield[8] = char(time >> 24);
991 crc = crc32(crc, (Bytef *)buffer, bufferSize );
992 bool ok = (
device()->writeBlock( buffer, bufferSize ) == bufferSize );
997 TQ_LONG centraldirendoffset =
device()->at();
1013 int count = d->m_fileList.count();
1017 buffer[ 8 ] = char(count);
1018 buffer[ 9 ] = char(count >> 8);
1020 buffer[ 10 ] = buffer[ 8 ];
1021 buffer[ 11 ] = buffer[ 9 ];
1023 int cdsize = centraldirendoffset - centraldiroffset;
1024 buffer[ 12 ] = char(cdsize);
1025 buffer[ 13 ] = char(cdsize >> 8);
1026 buffer[ 14 ] = char(cdsize >> 16);
1027 buffer[ 15 ] = char(cdsize >> 24);
1032 buffer[ 16 ] = char(centraldiroffset);
1033 buffer[ 17 ] = char(centraldiroffset >> 8);
1034 buffer[ 18 ] = char(centraldiroffset >> 16);
1035 buffer[ 19 ] = char(centraldiroffset >> 24);
1040 if (
device()->writeBlock( buffer, 22 ) != 22 )
1043 if ( d->m_saveFile ) {
1044 d->m_saveFile->close();
1046 delete d->m_saveFile;
1054bool KZip::writeDir(
const TQString& name,
const TQString& user,
const TQString& group)
1059 TQString dirName = name;
1060 if (!name.endsWith(
"/")) {
1061 dirName = dirName.append(
'/');
1064 mode_t perm = 040755;
1065 time_t the_time = time(0);
1066 return writeFile(dirName, user, group, 0, perm, the_time, the_time, the_time, 0);
1070bool KZip::writeFile(
const TQString& name,
const TQString& user,
const TQString& group, uint size,
const char* data )
1072 mode_t
mode = 0100644;
1073 time_t the_time = time(0);
1075 the_time, the_time, data );
1080 const TQString& group, uint size, mode_t perm,
1081 time_t atime, time_t mtime, time_t ctime,
1082 const char* data ) {
1090 mode_t dflt_perm = 0100644;
1091 time_t the_time = time(0);
1093 the_time,the_time,the_time);
1098 const TQString& group, uint size, mode_t perm,
1099 time_t atime, time_t mtime, time_t ctime) {
1103bool KZip::prepareWriting_impl(
const TQString &name,
const TQString &user,
1104 const TQString &group, uint , mode_t perm,
1105 time_t atime, time_t mtime, time_t ctime) {
1109 tqWarning(
"KZip::writeFile: You must open the zip file before writing to it\n");
1113 if ( ! (
mode() & IO_WriteOnly ) )
1115 tqWarning(
"KZip::writeFile: You must open the zip file for writing\n");
1125 if ( !
device()->at( d->m_offset ) ) {
1126 kdWarning(7040) <<
"prepareWriting_impl: cannot seek in ZIP file. Disk full?" << endl;
1135 TQPtrListIterator<KZipFileEntry> it( d->m_fileList );
1138 for ( ; it.current() ; ++it )
1141 if (name == it.current()->path() )
1144 d->m_fileList.remove();
1151 int i = name.findRev(
'/' );
1154 TQString dir = name.left( i );
1161 KZipFileEntry * e =
new KZipFileEntry(
this,
fileName, perm, mtime, user, group, TQString::null,
1162 name,
device()->at() + 30 + name.length(),
1163 0 , d->m_compression, 0 );
1164 e->setHeaderStart(
device()->at() );
1166 parentDir->addEntry( e );
1168 d->m_currentFile = e;
1169 d->m_fileList.append( e );
1171 int extra_field_len = 0;
1173 extra_field_len = 17;
1176 TQCString encodedName = TQFile::encodeName(name);
1177 int bufferSize = extra_field_len + encodedName.length() + 30;
1179 char* buffer =
new char[ bufferSize ];
1192 buffer[ 8 ] = char(e->encoding());
1193 buffer[ 9 ] = char(e->encoding() >> 8);
1195 transformToMsDos( e->datetime(), &buffer[ 10 ] );
1212 buffer[ 26 ] = (uchar)(encodedName.length());
1213 buffer[ 27 ] = (uchar)(encodedName.length() >> 8);
1215 buffer[ 28 ] = (uchar)(extra_field_len);
1216 buffer[ 29 ] = (uchar)(extra_field_len >> 8);
1219 strncpy( buffer + 30, encodedName, encodedName.length() );
1224 char *extfield = buffer + 30 + encodedName.length();
1230 extfield[4] = 1 | 2 | 4;
1232 extfield[5] = char(mtime);
1233 extfield[6] = char(mtime >> 8);
1234 extfield[7] = char(mtime >> 16);
1235 extfield[8] = char(mtime >> 24);
1237 extfield[9] = char(atime);
1238 extfield[10] = char(atime >> 8);
1239 extfield[11] = char(atime >> 16);
1240 extfield[12] = char(atime >> 24);
1242 extfield[13] = char(ctime);
1243 extfield[14] = char(ctime >> 8);
1244 extfield[15] = char(ctime >> 16);
1245 extfield[16] = char(ctime >> 24);
1249 bool b = (
device()->writeBlock( buffer, bufferSize ) == bufferSize );
1261 if ( d->m_compression == 0 ) {
1262 d->m_currentDev =
device();
1267 Q_ASSERT( d->m_currentDev );
1268 if ( !d->m_currentDev ) {
1272 static_cast<KFilterDev *
>(d->m_currentDev)->setSkipHeaders();
1274 b = d->m_currentDev->
open( IO_WriteOnly );
1281 if ( d->m_currentFile->encoding() == 8 ) {
1283 (void)d->m_currentDev->writeBlock( 0, 0 );
1284 delete d->m_currentDev;
1287 d->m_currentDev = 0L;
1289 Q_ASSERT( d->m_currentFile );
1293 d->m_currentFile->setSize(size);
1294 int extra_field_len = 0;
1296 extra_field_len = 17;
1298 int csize =
device()->at() -
1299 d->m_currentFile->headerStart() - 30 -
1300 d->m_currentFile->path().length() - extra_field_len;
1301 d->m_currentFile->setCompressedSize(csize);
1307 d->m_currentFile->setCRC32( d->m_crc );
1309 d->m_currentFile = 0L;
1312 d->m_offset =
device()->at();
1316bool KZip::writeSymLink(
const TQString &name,
const TQString &target,
1317 const TQString &user,
const TQString &group,
1318 mode_t perm, time_t atime, time_t mtime, time_t ctime) {
1322bool KZip::writeSymLink_impl(
const TQString &name,
const TQString &target,
1323 const TQString &user,
const TQString &group,
1324 mode_t perm, time_t atime, time_t mtime, time_t ctime) {
1332 if (!
prepareWriting(name, user, group, 0, perm, atime, mtime, ctime)) {
1333 kdWarning() <<
"KZip::writeFile prepareWriting failed" << endl;
1338 TQCString symlink_target = TQFile::encodeName(target);
1339 if (!
writeData(symlink_target, symlink_target.length())) {
1340 kdWarning() <<
"KZip::writeFile writeData failed" << endl;
1346 kdWarning() <<
"KZip::writeFile doneWriting failed" << endl;
1355void KZip::virtual_hook(
int id,
void* data )
1358 case VIRTUAL_WRITE_DATA: {
1359 WriteDataParams* params =
reinterpret_cast<WriteDataParams *
>(data);
1360 params->retval = writeData_impl( params->data, params->size );
1363 case VIRTUAL_WRITE_SYMLINK: {
1364 WriteSymlinkParams *params =
reinterpret_cast<WriteSymlinkParams *
>(data);
1365 params->retval = writeSymLink_impl(*params->name,*params->target,
1366 *params->user,*params->group,params->perm,
1367 params->atime,params->mtime,params->ctime);
1370 case VIRTUAL_PREPARE_WRITING: {
1371 PrepareWritingParams *params =
reinterpret_cast<PrepareWritingParams *
>(data);
1372 params->retval = prepareWriting_impl(*params->name,*params->user,
1373 *params->group,params->size,params->perm,
1374 params->atime,params->mtime,params->ctime);
1378 KArchive::virtual_hook(
id, data );
1388bool KZip::writeData_impl(
const char * c, uint i)
1390 Q_ASSERT( d->m_currentFile );
1391 Q_ASSERT( d->m_currentDev );
1392 if (!d->m_currentFile || !d->m_currentDev) {
1399 d->m_crc = crc32(d->m_crc, (
const Bytef *) c , i);
1401 TQ_LONG written = d->m_currentDev->writeBlock( c, i );
1403 bool ok = written == (TQ_LONG)i;
1421 d->m_extraField = ef;
1426 return d->m_extraField;
1431 if ( d->m_saveFile ) {
1432 d->m_saveFile->abort();
1440TQByteArray KZipFileEntry::data()
const
1442 TQIODevice* dev = device();
1445 arr = dev->readAll();
1451TQIODevice* KZipFileEntry::device()
const
1456 if ( encoding() == 0 || compressedSize() == 0 )
1459 if ( encoding() == 8 )
1465 static_cast<KFilterDev *
>(filterDev)->setSkipHeaders();
1466 bool b = filterDev->
open( IO_ReadOnly );
1471 kdError() <<
"This zip file contains files compressed with method "
1472 << encoding() <<
", this method is currently not supported by KZip,"
1473 <<
" please use a command-line tool to handle this file." << endl;
Represents a directory entry in a KArchive.
KArchiveEntry * entry(TQString name)
Returns the entry with the given name.
A base class for entries in an KArchive.
virtual bool isDirectory() const
Checks whether the entry is a directory.
KArchive is a base class for reading and writing archives.
virtual KArchiveDirectory * rootDir()
Retrieves or create the root directory.
virtual bool open(int mode)
Opens the archive for reading or writing.
KArchiveDirectory * findOrCreate(const TQString &path)
Ensures that path exists, create otherwise.
virtual void close()
Closes the archive.
int mode() const
Returns the mode in which the archive was opened.
TQIODevice * device() const
The underlying device.
bool isOpened() const
Checks whether the archive is open.
bool writeData(const char *data, uint size)
Write data into the current file - to be called after calling prepareWriting.
bool writeSymLink(const TQString &name, const TQString &target, const TQString &user, const TQString &group, mode_t perm, time_t atime, time_t mtime, time_t ctime)
Writes a symbolic link to the archive if the archive must be opened for writing.
virtual bool prepareWriting(const TQString &name, const TQString &user, const TQString &group, uint size)=0
Here's another way of writing a file into an archive: Call prepareWriting, then call writeData() as m...
virtual bool writeFile(const TQString &name, const TQString &user, const TQString &group, uint size, const char *data)
If an archive is opened for writing then you can add a new file using this function.
A class for reading and writing compressed data onto a device (e.g.
virtual bool open(int mode)
Open for reading or writing.
static TQIODevice * device(TQIODevice *inDevice, const TQString &mimetype)
Creates an i/o device that is able to read from the TQIODevice inDevice, whether the data is compress...
A readonly device that reads from an underlying device from a given point to another (e....
This class implements a tdeioslave to access zip files from KDE.
virtual bool writeDir(const TQString &name, const TQString &user, const TQString &group)
If an archive is opened for writing then you can add new directories using this function.
TQString fileName()
The name of the zip file, as passed to the constructor.
void setCompression(Compression c)
Call this before writeFile or prepareWriting, to define whether the next files to be written should b...
ExtraField
Describes the contents of the "extra field" for a given file in the Zip archive.
@ ModificationTime
Modification time ("extended timestamp" header)
@ NoExtraField
No extra field.
bool writeData(const char *data, uint size)
Write data to a file that has been created using prepareWriting().
virtual bool closeArchive()
Closes the archive.
virtual bool prepareWriting(const TQString &name, const TQString &user, const TQString &group, uint size)
Alternative method for writing: call prepareWriting(), then feed the data in small chunks using write...
void setExtraField(ExtraField ef)
Call this before writeFile or prepareWriting, to define what the next file to be written should have ...
virtual bool writeFile(const TQString &name, const TQString &user, const TQString &group, uint size, const char *data)
If an archive is opened for writing then you can add a new file using this function.
virtual ~KZip()
If the zip file is still opened, then it will be closed automatically by the destructor.
virtual bool openArchive(int mode)
Opens the archive for reading.
Compression
Describes the compression type for a given file in the Zip archive.
@ DeflateCompression
Deflate compression method.
@ NoCompression
Uncompressed.
Compression compression() const
The current compression mode that will be used for new files.
KZip(const TQString &filename)
Creates an instance that operates on the given filename.
virtual bool doneWriting(uint size)
Write data to a file that has been created using prepareWriting().
ExtraField extraField() const
The current type of "extra field" that will be used for new files.