41 #include "kfilterdev.h"
42 #include "klimitediodevice.h"
43 #include <kmimetype.h>
44 #include <ksavefile.h>
47 #include <tqasciidict.h>
50 #include <tqdatetime.h>
51 #include <tqptrlist.h>
57 const int max_path_len = 4095;
59 static 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);
88 static 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();
109 struct 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);
141 static 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;
201 static 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;
226 #if 0 // not needed yet
235 static 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;
265 static 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;
291 #if 0 // not needed yet
293 if (!parseInfoZipUnixNew(buffer, fieldsize, islocal, pfi))
return false;
310 class 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( TQT_TQIODEVICE(d->m_saveFile->file()) );
395 if ( !m_filename.isEmpty() ) {
396 setDevice( TQT_TQIODEVICE(
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;
429 kdDebug(7040) <<
"loop starts" << endl;
430 kdDebug(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 = QMIN(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;
1055 bool KZip::writeFile(
const TQString& name,
const TQString& user,
const TQString& group, uint size,
const char* data )
1057 mode_t
mode = 0100644;
1058 time_t the_time = time(0);
1060 the_time, the_time, data );
1065 const TQString& group, uint size, mode_t perm,
1066 time_t atime, time_t mtime, time_t ctime,
1067 const char* data ) {
1075 mode_t dflt_perm = 0100644;
1076 time_t the_time = time(0);
1078 the_time,the_time,the_time);
1083 const TQString& group, uint size, mode_t perm,
1084 time_t atime, time_t mtime, time_t ctime) {
1088 bool KZip::prepareWriting_impl(
const TQString &name,
const TQString &user,
1089 const TQString &group, uint , mode_t perm,
1090 time_t atime, time_t mtime, time_t ctime) {
1094 qWarning(
"KZip::writeFile: You must open the zip file before writing to it\n");
1098 if ( ! (
mode() & IO_WriteOnly ) )
1100 qWarning(
"KZip::writeFile: You must open the zip file for writing\n");
1110 if ( !
device()->at( d->m_offset ) ) {
1111 kdWarning(7040) <<
"prepareWriting_impl: cannot seek in ZIP file. Disk full?" << endl;
1120 TQPtrListIterator<KZipFileEntry> it( d->m_fileList );
1123 for ( ; it.current() ; ++it )
1126 if (name == it.current()->path() )
1129 d->m_fileList.remove();
1136 int i = name.findRev(
'/' );
1139 TQString dir = name.left( i );
1146 KZipFileEntry * e =
new KZipFileEntry(
this,
fileName, perm, mtime, user, group, TQString::null,
1147 name,
device()->at() + 30 + name.length(),
1148 0 , d->m_compression, 0 );
1149 e->setHeaderStart(
device()->at() );
1151 parentDir->addEntry( e );
1153 d->m_currentFile = e;
1154 d->m_fileList.append( e );
1156 int extra_field_len = 0;
1158 extra_field_len = 17;
1161 TQCString encodedName = TQFile::encodeName(name);
1162 int bufferSize = extra_field_len + encodedName.length() + 30;
1164 char* buffer =
new char[ bufferSize ];
1177 buffer[ 8 ] = char(e->encoding());
1178 buffer[ 9 ] = char(e->encoding() >> 8);
1180 transformToMsDos( e->datetime(), &buffer[ 10 ] );
1197 buffer[ 26 ] = (uchar)(encodedName.length());
1198 buffer[ 27 ] = (uchar)(encodedName.length() >> 8);
1200 buffer[ 28 ] = (uchar)(extra_field_len);
1201 buffer[ 29 ] = (uchar)(extra_field_len >> 8);
1204 strncpy( buffer + 30, encodedName, encodedName.length() );
1209 char *extfield = buffer + 30 + encodedName.length();
1215 extfield[4] = 1 | 2 | 4;
1217 extfield[5] = char(mtime);
1218 extfield[6] = char(mtime >> 8);
1219 extfield[7] = char(mtime >> 16);
1220 extfield[8] = char(mtime >> 24);
1222 extfield[9] = char(atime);
1223 extfield[10] = char(atime >> 8);
1224 extfield[11] = char(atime >> 16);
1225 extfield[12] = char(atime >> 24);
1227 extfield[13] = char(ctime);
1228 extfield[14] = char(ctime >> 8);
1229 extfield[15] = char(ctime >> 16);
1230 extfield[16] = char(ctime >> 24);
1234 bool b = (
device()->writeBlock( buffer, bufferSize ) == bufferSize );
1246 if ( d->m_compression == 0 ) {
1247 d->m_currentDev =
device();
1252 Q_ASSERT( d->m_currentDev );
1253 if ( !d->m_currentDev ) {
1257 static_cast<KFilterDev *
>(d->m_currentDev)->setSkipHeaders();
1259 b = d->m_currentDev->
open( IO_WriteOnly );
1266 if ( d->m_currentFile->encoding() == 8 ) {
1268 (void)d->m_currentDev->writeBlock( 0, 0 );
1269 delete d->m_currentDev;
1272 d->m_currentDev = 0L;
1274 Q_ASSERT( d->m_currentFile );
1278 d->m_currentFile->setSize(size);
1279 int extra_field_len = 0;
1281 extra_field_len = 17;
1283 int csize =
device()->at() -
1284 d->m_currentFile->headerStart() - 30 -
1285 d->m_currentFile->path().length() - extra_field_len;
1286 d->m_currentFile->setCompressedSize(csize);
1292 d->m_currentFile->setCRC32( d->m_crc );
1294 d->m_currentFile = 0L;
1297 d->m_offset =
device()->at();
1301 bool KZip::writeSymLink(
const TQString &name,
const TQString &target,
1302 const TQString &user,
const TQString &group,
1303 mode_t perm, time_t atime, time_t mtime, time_t ctime) {
1307 bool KZip::writeSymLink_impl(
const TQString &name,
const TQString &target,
1308 const TQString &user,
const TQString &group,
1309 mode_t perm, time_t atime, time_t mtime, time_t ctime) {
1317 if (!
prepareWriting(name, user, group, 0, perm, atime, mtime, ctime)) {
1318 kdWarning() <<
"KZip::writeFile prepareWriting failed" << endl;
1323 TQCString symlink_target = TQFile::encodeName(target);
1324 if (!
writeData(symlink_target, symlink_target.length())) {
1325 kdWarning() <<
"KZip::writeFile writeData failed" << endl;
1331 kdWarning() <<
"KZip::writeFile doneWriting failed" << endl;
1340 void KZip::virtual_hook(
int id,
void* data )
1343 case VIRTUAL_WRITE_DATA: {
1344 WriteDataParams* params =
reinterpret_cast<WriteDataParams *
>(data);
1345 params->retval = writeData_impl( params->data, params->size );
1348 case VIRTUAL_WRITE_SYMLINK: {
1349 WriteSymlinkParams *params =
reinterpret_cast<WriteSymlinkParams *
>(data);
1350 params->retval = writeSymLink_impl(*params->name,*params->target,
1351 *params->user,*params->group,params->perm,
1352 params->atime,params->mtime,params->ctime);
1355 case VIRTUAL_PREPARE_WRITING: {
1356 PrepareWritingParams *params =
reinterpret_cast<PrepareWritingParams *
>(data);
1357 params->retval = prepareWriting_impl(*params->name,*params->user,
1358 *params->group,params->size,params->perm,
1359 params->atime,params->mtime,params->ctime);
1363 KArchive::virtual_hook(
id, data );
1373 bool KZip::writeData_impl(
const char * c, uint i)
1375 Q_ASSERT( d->m_currentFile );
1376 Q_ASSERT( d->m_currentDev );
1377 if (!d->m_currentFile || !d->m_currentDev) {
1384 d->m_crc = crc32(d->m_crc, (
const Bytef *) c , i);
1386 TQ_LONG written = d->m_currentDev->writeBlock( c, i );
1388 bool ok = written == (TQ_LONG)i;
1406 d->m_extraField = ef;
1411 return d->m_extraField;
1416 if ( d->m_saveFile ) {
1417 d->m_saveFile->abort();
1425 TQByteArray KZipFileEntry::data()
const
1427 TQIODevice* dev = device();
1430 arr = dev->readAll();
1436 TQIODevice* KZipFileEntry::device()
const
1441 if ( encoding() == 0 || compressedSize() == 0 )
1444 if ( encoding() == 8 )
1450 static_cast<KFilterDev *
>(filterDev)->setSkipHeaders();
1451 bool b = filterDev->
open( IO_ReadOnly );
1456 kdError() <<
"This zip file contains files compressed with method "
1457 << encoding() <<
", this method is currently not supported by KZip,"
1458 <<
" please use a command-line tool to handle this file." << endl;