~ubuntu-branches/ubuntu/trusty/unrar-nonfree/trusty

1 by Chris Anderson
Import upstream version 3.3.6
1
#include "rar.hpp"
2
1.2.4 by Martin Meredith
Import upstream version 3.9.3
3
size_t Archive::SearchBlock(int BlockType)
1 by Chris Anderson
Import upstream version 3.3.6
4
{
1.2.4 by Martin Meredith
Import upstream version 3.9.3
5
  size_t Size,Count=0;
1 by Chris Anderson
Import upstream version 3.3.6
6
  while ((Size=ReadHeader())!=0 &&
7
         (BlockType==ENDARC_HEAD || GetHeaderType()!=ENDARC_HEAD))
8
  {
9
    if ((++Count & 127)==0)
10
      Wait();
11
    if (GetHeaderType()==BlockType)
12
      return(Size);
13
    SeekToNext();
14
  }
15
  return(0);
16
}
17
18
1.2.4 by Martin Meredith
Import upstream version 3.9.3
19
size_t Archive::SearchSubBlock(const char *Type)
1 by Chris Anderson
Import upstream version 3.3.6
20
{
1.2.4 by Martin Meredith
Import upstream version 3.9.3
21
  size_t Size;
1.1.1 by Chris Anderson
Import upstream version 3.4.3
22
  while ((Size=ReadHeader())!=0 && GetHeaderType()!=ENDARC_HEAD)
1 by Chris Anderson
Import upstream version 3.3.6
23
  {
24
    if (GetHeaderType()==NEWSUB_HEAD && SubHead.CmpName(Type))
25
      return(Size);
26
    SeekToNext();
27
  }
28
  return(0);
29
}
30
31
1.2.6 by Martin Meredith
Import upstream version 3.9.6
32
void Archive::UnexpEndArcMsg()
33
{
34
  int64 ArcSize=FileLength();
35
  if (CurBlockPos>ArcSize || NextBlockPos>ArcSize)
36
  {
37
#ifndef SHELL_EXT
38
    Log(FileName,St(MLogUnexpEOF));
39
#endif
1.2.13 by Nick Andrik
Import upstream version 4.2.4
40
    ErrHandler.SetErrorCode(RARX_WARNING);
1.2.6 by Martin Meredith
Import upstream version 3.9.6
41
  }
42
}
43
44
1.2.4 by Martin Meredith
Import upstream version 3.9.3
45
size_t Archive::ReadHeader()
1 by Chris Anderson
Import upstream version 3.3.6
46
{
1.2.12 by Martin Meredith
Import upstream version 4.1.4
47
  // Once we failed to decrypt an encrypted block, there is no reason to
48
  // attempt to do it further. We'll never be successful and only generate
49
  // endless errors.
50
  if (FailedHeaderDecryption)
51
    return 0;
52
1 by Chris Anderson
Import upstream version 3.3.6
53
  CurBlockPos=Tell();
54
55
#ifndef SFX_MODULE
56
  if (OldFormat)
57
    return(ReadOldHeader());
58
#endif
59
60
  RawRead Raw(this);
61
1.2.4 by Martin Meredith
Import upstream version 3.9.3
62
  bool Decrypt=Encrypted && CurBlockPos>=(int64)SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD;
1 by Chris Anderson
Import upstream version 3.3.6
63
64
  if (Decrypt)
65
  {
1.2.12 by Martin Meredith
Import upstream version 4.1.4
66
#if defined(SHELL_EXT) || defined(RAR_NOCRYPT)
1 by Chris Anderson
Import upstream version 3.3.6
67
    return(0);
68
#else
69
    if (Read(HeadersSalt,SALT_SIZE)!=SALT_SIZE)
1.2.6 by Martin Meredith
Import upstream version 3.9.6
70
    {
71
      UnexpEndArcMsg();
1 by Chris Anderson
Import upstream version 3.3.6
72
      return(0);
1.2.6 by Martin Meredith
Import upstream version 3.9.6
73
    }
1.2.13 by Nick Andrik
Import upstream version 4.2.4
74
    if (!Cmd->Password.IsSet())
1.2.10 by Martin Meredith
Import upstream version 4.0.2
75
    {
1 by Chris Anderson
Import upstream version 3.3.6
76
#ifdef RARDLL
1.2.13 by Nick Andrik
Import upstream version 4.2.4
77
      if (Cmd->Callback!=NULL)
78
      {
79
        wchar PasswordW[MAXPASSWORD];
80
        *PasswordW=0;
81
        if (Cmd->Callback(UCM_NEEDPASSWORDW,Cmd->UserData,(LPARAM)PasswordW,ASIZE(PasswordW))==-1)
82
          *PasswordW=0;
83
        if (*PasswordW==0)
84
        {
85
          char PasswordA[MAXPASSWORD];
86
          *PasswordA=0;
87
          if (Cmd->Callback(UCM_NEEDPASSWORD,Cmd->UserData,(LPARAM)PasswordA,ASIZE(PasswordA))==-1)
88
            *PasswordA=0;
89
          GetWideName(PasswordA,NULL,PasswordW,ASIZE(PasswordW));
90
          cleandata(PasswordA,sizeof(PasswordA));
91
        }
92
        Cmd->Password.Set(PasswordW);
93
        cleandata(PasswordW,sizeof(PasswordW));
94
      }
95
      if (!Cmd->Password.IsSet())
1 by Chris Anderson
Import upstream version 3.3.6
96
      {
97
        Close();
1.2.13 by Nick Andrik
Import upstream version 4.2.4
98
        Cmd->DllError=ERAR_MISSING_PASSWORD;
99
        ErrHandler.Exit(RARX_USERBREAK);
1 by Chris Anderson
Import upstream version 3.3.6
100
      }
101
#else
1.2.13 by Nick Andrik
Import upstream version 4.2.4
102
      if (!GetPassword(PASSWORD_ARCHIVE,FileName,FileNameW,&Cmd->Password))
1 by Chris Anderson
Import upstream version 3.3.6
103
      {
104
        Close();
1.2.13 by Nick Andrik
Import upstream version 4.2.4
105
        ErrHandler.Exit(RARX_USERBREAK);
1 by Chris Anderson
Import upstream version 3.3.6
106
      }
107
#endif
1.2.10 by Martin Meredith
Import upstream version 4.0.2
108
    }
1.2.13 by Nick Andrik
Import upstream version 4.2.4
109
    HeadersCrypt.SetCryptKeys(&Cmd->Password,HeadersSalt,false,false,NewMhd.EncryptVer>=36);
1 by Chris Anderson
Import upstream version 3.3.6
110
    Raw.SetCrypt(&HeadersCrypt);
111
#endif
112
  }
113
114
  Raw.Read(SIZEOF_SHORTBLOCKHEAD);
115
  if (Raw.Size()==0)
116
  {
1.2.6 by Martin Meredith
Import upstream version 3.9.6
117
    UnexpEndArcMsg();
1 by Chris Anderson
Import upstream version 3.3.6
118
    return(0);
119
  }
120
121
  Raw.Get(ShortBlock.HeadCRC);
122
  byte HeadType;
123
  Raw.Get(HeadType);
124
  ShortBlock.HeadType=(HEADER_TYPE)HeadType;
125
  Raw.Get(ShortBlock.Flags);
126
  Raw.Get(ShortBlock.HeadSize);
127
  if (ShortBlock.HeadSize<SIZEOF_SHORTBLOCKHEAD)
128
  {
129
#ifndef SHELL_EXT
130
    Log(FileName,St(MLogFileHead),"???");
131
#endif
132
    BrokenFileHeader=true;
1.2.13 by Nick Andrik
Import upstream version 4.2.4
133
    ErrHandler.SetErrorCode(RARX_CRC);
1 by Chris Anderson
Import upstream version 3.3.6
134
    return(0);
135
  }
136
137
  if (ShortBlock.HeadType==COMM_HEAD)
1.2.10 by Martin Meredith
Import upstream version 4.0.2
138
  {
139
    // Old style (up to RAR 2.9) comment header embedded into main
140
    // or file header. We must not read the entire ShortBlock.HeadSize here
141
    // to not break the comment processing logic later.
1 by Chris Anderson
Import upstream version 3.3.6
142
    Raw.Read(SIZEOF_COMMHEAD-SIZEOF_SHORTBLOCKHEAD);
1.2.10 by Martin Meredith
Import upstream version 4.0.2
143
  }
1 by Chris Anderson
Import upstream version 3.3.6
144
  else
145
    if (ShortBlock.HeadType==MAIN_HEAD && (ShortBlock.Flags & MHD_COMMENT)!=0)
1.2.10 by Martin Meredith
Import upstream version 4.0.2
146
    {
147
      // Old style (up to RAR 2.9) main archive comment embedded into
148
      // the main archive header found. While we can read the entire 
149
      // ShortBlock.HeadSize here and remove this part of "if", it would be
150
      // waste of memory, because we'll read and process this comment data
151
      // in other function anyway and we do not need them here now.
1 by Chris Anderson
Import upstream version 3.3.6
152
      Raw.Read(SIZEOF_NEWMHD-SIZEOF_SHORTBLOCKHEAD);
1.2.10 by Martin Meredith
Import upstream version 4.0.2
153
    }
1 by Chris Anderson
Import upstream version 3.3.6
154
    else
155
      Raw.Read(ShortBlock.HeadSize-SIZEOF_SHORTBLOCKHEAD);
156
157
  NextBlockPos=CurBlockPos+ShortBlock.HeadSize;
158
159
  switch(ShortBlock.HeadType)
160
  {
161
    case MAIN_HEAD:
162
      *(BaseBlock *)&NewMhd=ShortBlock;
163
      Raw.Get(NewMhd.HighPosAV);
164
      Raw.Get(NewMhd.PosAV);
1.1.4 by Martin Meredith
Import upstream version 3.6.8
165
      if (NewMhd.Flags & MHD_ENCRYPTVER)
166
        Raw.Get(NewMhd.EncryptVer);
1 by Chris Anderson
Import upstream version 3.3.6
167
      break;
168
    case ENDARC_HEAD:
169
      *(BaseBlock *)&EndArcHead=ShortBlock;
170
      if (EndArcHead.Flags & EARC_DATACRC)
171
        Raw.Get(EndArcHead.ArcDataCRC);
1.1.1 by Chris Anderson
Import upstream version 3.4.3
172
      if (EndArcHead.Flags & EARC_VOLNUMBER)
173
        Raw.Get(EndArcHead.VolNumber);
1 by Chris Anderson
Import upstream version 3.3.6
174
      break;
175
    case FILE_HEAD:
176
    case NEWSUB_HEAD:
177
      {
178
        FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
179
        *(BaseBlock *)hd=ShortBlock;
180
        Raw.Get(hd->PackSize);
181
        Raw.Get(hd->UnpSize);
182
        Raw.Get(hd->HostOS);
183
        Raw.Get(hd->FileCRC);
184
        Raw.Get(hd->FileTime);
185
        Raw.Get(hd->UnpVer);
186
        Raw.Get(hd->Method);
187
        Raw.Get(hd->NameSize);
188
        Raw.Get(hd->FileAttr);
189
        if (hd->Flags & LHD_LARGE)
190
        {
191
          Raw.Get(hd->HighPackSize);
192
          Raw.Get(hd->HighUnpSize);
193
        }
194
        else 
1.1.1 by Chris Anderson
Import upstream version 3.4.3
195
        {
1 by Chris Anderson
Import upstream version 3.3.6
196
          hd->HighPackSize=hd->HighUnpSize=0;
1.1.1 by Chris Anderson
Import upstream version 3.4.3
197
          if (hd->UnpSize==0xffffffff)
198
          {
1.2.4 by Martin Meredith
Import upstream version 3.9.3
199
            // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
200
            // that we do not know the unpacked file size and must unpack it
201
            // until we find the end of file marker in compressed data.
202
            hd->UnpSize=(uint)(INT64NDF);
203
            hd->HighUnpSize=(uint)(INT64NDF>>32);
1.1.1 by Chris Anderson
Import upstream version 3.4.3
204
          }
205
        }
1.2.4 by Martin Meredith
Import upstream version 3.9.3
206
        hd->FullPackSize=INT32TO64(hd->HighPackSize,hd->PackSize);
207
        hd->FullUnpSize=INT32TO64(hd->HighUnpSize,hd->UnpSize);
1 by Chris Anderson
Import upstream version 3.3.6
208
209
        char FileName[NM*4];
1.2.12 by Martin Meredith
Import upstream version 4.1.4
210
        size_t NameSize=Min(hd->NameSize,sizeof(FileName)-1);
1 by Chris Anderson
Import upstream version 3.3.6
211
        Raw.Get((byte *)FileName,NameSize);
212
        FileName[NameSize]=0;
213
1.1.5 by Martin Meredith
Import upstream version 3.7.2
214
        strncpyz(hd->FileName,FileName,ASIZE(hd->FileName));
1 by Chris Anderson
Import upstream version 3.3.6
215
216
        if (hd->HeadType==NEWSUB_HEAD)
217
        {
1.2.7 by Martin Meredith
Import upstream version 3.9.7
218
          // Let's calculate the size of optional data.
1 by Chris Anderson
Import upstream version 3.3.6
219
          int DataSize=hd->HeadSize-hd->NameSize-SIZEOF_NEWLHD;
220
          if (hd->Flags & LHD_SALT)
221
            DataSize-=SALT_SIZE;
1.2.7 by Martin Meredith
Import upstream version 3.9.7
222
1 by Chris Anderson
Import upstream version 3.3.6
223
          if (DataSize>0)
224
          {
1.2.7 by Martin Meredith
Import upstream version 3.9.7
225
            // Here we read optional additional fields for subheaders.
226
            // They are stored after the file name and before salt.
1 by Chris Anderson
Import upstream version 3.3.6
227
            hd->SubData.Alloc(DataSize);
228
            Raw.Get(&hd->SubData[0],DataSize);
229
            if (hd->CmpName(SUBHEAD_TYPE_RR))
230
            {
231
              byte *D=&hd->SubData[8];
232
              RecoverySectors=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24);
233
            }
234
          }
235
        }
236
        else
237
          if (hd->HeadType==FILE_HEAD)
238
          {
239
            if (hd->Flags & LHD_UNICODE)
240
            {
241
              EncodeFileName NameCoder;
1.2.4 by Martin Meredith
Import upstream version 3.9.3
242
              size_t Length=strlen(FileName);
1.1.4 by Martin Meredith
Import upstream version 3.6.8
243
              if (Length==hd->NameSize)
244
              {
245
                UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1);
246
                WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1);
247
                ExtToInt(hd->FileName,hd->FileName);
248
              }
249
              else
250
              {
251
                Length++;
252
                NameCoder.Decode(FileName,(byte *)FileName+Length,
253
                                 hd->NameSize-Length,hd->FileNameW,
254
                                 sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
255
              }
1 by Chris Anderson
Import upstream version 3.3.6
256
              if (*hd->FileNameW==0)
257
                hd->Flags &= ~LHD_UNICODE;
258
            }
259
            else
260
              *hd->FileNameW=0;
261
#ifndef SFX_MODULE
262
            ConvertNameCase(hd->FileName);
263
            ConvertNameCase(hd->FileNameW);
264
#endif
265
            ConvertUnknownHeader();
266
          }
267
        if (hd->Flags & LHD_SALT)
268
          Raw.Get(hd->Salt,SALT_SIZE);
269
        hd->mtime.SetDos(hd->FileTime);
270
        hd->ctime.Reset();
271
        hd->atime.Reset();
272
        hd->arctime.Reset();
273
        if (hd->Flags & LHD_EXTTIME)
274
        {
275
          ushort Flags;
276
          Raw.Get(Flags);
277
          RarTime *tbl[4];
278
          tbl[0]=&NewLhd.mtime;
279
          tbl[1]=&NewLhd.ctime;
280
          tbl[2]=&NewLhd.atime;
281
          tbl[3]=&NewLhd.arctime;
282
          for (int I=0;I<4;I++)
283
          {
284
            RarTime *CurTime=tbl[I];
285
            uint rmode=Flags>>(3-I)*4;
286
            if ((rmode & 8)==0)
287
              continue;
288
            if (I!=0)
289
            {
290
              uint DosTime;
291
              Raw.Get(DosTime);
292
              CurTime->SetDos(DosTime);
293
            }
294
            RarLocalTime rlt;
295
            CurTime->GetLocal(&rlt);
296
            if (rmode & 4)
297
              rlt.Second++;
298
            rlt.Reminder=0;
299
            int count=rmode&3;
300
            for (int J=0;J<count;J++)
301
            {
302
              byte CurByte;
303
              Raw.Get(CurByte);
304
              rlt.Reminder|=(((uint)CurByte)<<((J+3-count)*8));
305
            }
306
            CurTime->SetLocal(&rlt);
307
          }
308
        }
309
        NextBlockPos+=hd->FullPackSize;
310
        bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0;
311
        HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff;
312
        if (hd->HeadCRC!=HeaderCRC)
313
        {
1.2.10 by Martin Meredith
Import upstream version 4.0.2
314
          if (hd->HeadType==NEWSUB_HEAD && strlen(hd->FileName)<ASIZE(hd->FileName)-5)
1 by Chris Anderson
Import upstream version 3.3.6
315
            strcat(hd->FileName,"- ???");
316
          BrokenFileHeader=true;
1.2.13 by Nick Andrik
Import upstream version 4.2.4
317
          ErrHandler.SetErrorCode(RARX_WARNING);
1.2.10 by Martin Meredith
Import upstream version 4.0.2
318
319
          // If we have a broken encrypted header, we do not need to display
320
          // the error message here, because it will be displayed for such
321
          // headers later in this function. Also such headers are unlikely
322
          // to have anything sensible in file name field, so it is useless
323
          // to display the file name.
324
          bool EncBroken=Decrypt && ShortBlock.HeadCRC!=(~Raw.GetCRC(false)&0xffff);
325
          if (!EncBroken)
326
          {
1 by Chris Anderson
Import upstream version 3.3.6
327
#ifndef SHELL_EXT
1.2.10 by Martin Meredith
Import upstream version 4.0.2
328
            Log(Archive::FileName,St(MLogFileHead),IntNameToExt(hd->FileName));
329
            Alarm();
1 by Chris Anderson
Import upstream version 3.3.6
330
#endif
1.2.10 by Martin Meredith
Import upstream version 4.0.2
331
          }
1 by Chris Anderson
Import upstream version 3.3.6
332
        }
333
      }
334
      break;
335
#ifndef SFX_MODULE
336
    case COMM_HEAD:
337
      *(BaseBlock *)&CommHead=ShortBlock;
338
      Raw.Get(CommHead.UnpSize);
339
      Raw.Get(CommHead.UnpVer);
340
      Raw.Get(CommHead.Method);
341
      Raw.Get(CommHead.CommCRC);
342
      break;
343
    case SIGN_HEAD:
344
      *(BaseBlock *)&SignHead=ShortBlock;
345
      Raw.Get(SignHead.CreationTime);
346
      Raw.Get(SignHead.ArcNameSize);
347
      Raw.Get(SignHead.UserNameSize);
348
      break;
349
    case AV_HEAD:
350
      *(BaseBlock *)&AVHead=ShortBlock;
351
      Raw.Get(AVHead.UnpVer);
352
      Raw.Get(AVHead.Method);
353
      Raw.Get(AVHead.AVVer);
354
      Raw.Get(AVHead.AVInfoCRC);
355
      break;
356
    case PROTECT_HEAD:
357
      *(BaseBlock *)&ProtectHead=ShortBlock;
358
      Raw.Get(ProtectHead.DataSize);
359
      Raw.Get(ProtectHead.Version);
360
      Raw.Get(ProtectHead.RecSectors);
361
      Raw.Get(ProtectHead.TotalBlocks);
362
      Raw.Get(ProtectHead.Mark,8);
363
      NextBlockPos+=ProtectHead.DataSize;
364
      RecoverySectors=ProtectHead.RecSectors;
365
      break;
366
    case SUB_HEAD:
367
      *(BaseBlock *)&SubBlockHead=ShortBlock;
368
      Raw.Get(SubBlockHead.DataSize);
369
      NextBlockPos+=SubBlockHead.DataSize;
370
      Raw.Get(SubBlockHead.SubType);
371
      Raw.Get(SubBlockHead.Level);
372
      switch(SubBlockHead.SubType)
373
      {
374
        case UO_HEAD:
375
          *(SubBlockHeader *)&UOHead=SubBlockHead;
376
          Raw.Get(UOHead.OwnerNameSize);
377
          Raw.Get(UOHead.GroupNameSize);
378
          if (UOHead.OwnerNameSize>NM-1)
379
            UOHead.OwnerNameSize=NM-1;
380
          if (UOHead.GroupNameSize>NM-1)
381
            UOHead.GroupNameSize=NM-1;
382
          Raw.Get((byte *)UOHead.OwnerName,UOHead.OwnerNameSize);
383
          Raw.Get((byte *)UOHead.GroupName,UOHead.GroupNameSize);
384
          UOHead.OwnerName[UOHead.OwnerNameSize]=0;
385
          UOHead.GroupName[UOHead.GroupNameSize]=0;
386
          break;
387
        case MAC_HEAD:
388
          *(SubBlockHeader *)&MACHead=SubBlockHead;
389
          Raw.Get(MACHead.fileType);
390
          Raw.Get(MACHead.fileCreator);
391
          break;
392
        case EA_HEAD:
393
        case BEEA_HEAD:
394
        case NTACL_HEAD:
395
          *(SubBlockHeader *)&EAHead=SubBlockHead;
396
          Raw.Get(EAHead.UnpSize);
397
          Raw.Get(EAHead.UnpVer);
398
          Raw.Get(EAHead.Method);
399
          Raw.Get(EAHead.EACRC);
400
          break;
401
        case STREAM_HEAD:
402
          *(SubBlockHeader *)&StreamHead=SubBlockHead;
403
          Raw.Get(StreamHead.UnpSize);
404
          Raw.Get(StreamHead.UnpVer);
405
          Raw.Get(StreamHead.Method);
406
          Raw.Get(StreamHead.StreamCRC);
407
          Raw.Get(StreamHead.StreamNameSize);
408
          if (StreamHead.StreamNameSize>NM-1)
409
            StreamHead.StreamNameSize=NM-1;
410
          Raw.Get((byte *)StreamHead.StreamName,StreamHead.StreamNameSize);
411
          StreamHead.StreamName[StreamHead.StreamNameSize]=0;
412
          break;
413
      }
414
      break;
415
#endif
416
    default:
417
      if (ShortBlock.Flags & LONG_BLOCK)
418
      {
419
        uint DataSize;
420
        Raw.Get(DataSize);
421
        NextBlockPos+=DataSize;
422
      }
423
      break;
424
  }
425
  HeaderCRC=~Raw.GetCRC(false)&0xffff;
426
  CurHeaderType=ShortBlock.HeadType;
427
  if (Decrypt)
428
  {
429
    NextBlockPos+=Raw.PaddedSize()+SALT_SIZE;
430
431
    if (ShortBlock.HeadCRC!=HeaderCRC)
432
    {
433
      bool Recovered=false;
434
      if (ShortBlock.HeadType==ENDARC_HEAD && (EndArcHead.Flags & EARC_REVSPACE)!=0)
435
      {
1.2.1 by Martin Meredith
Import upstream version 3.8.2
436
        // Last 7 bytes of recovered volume can contain zeroes, because
437
        // REV files store its own information (volume number, etc.) here.
1 by Chris Anderson
Import upstream version 3.3.6
438
        SaveFilePos SavePos(*this);
1.2.4 by Martin Meredith
Import upstream version 3.9.3
439
        int64 Length=Tell();
1 by Chris Anderson
Import upstream version 3.3.6
440
        Seek(Length-7,SEEK_SET);
441
        Recovered=true;
442
        for (int J=0;J<7;J++)
443
          if (GetByte()!=0)
444
            Recovered=false;
445
      }
446
      if (!Recovered)
447
      {
448
#ifndef SILENT
449
        Log(FileName,St(MEncrBadCRC),FileName);
450
#endif
1.2.12 by Martin Meredith
Import upstream version 4.1.4
451
//        Close();
452
        FailedHeaderDecryption=true;
1 by Chris Anderson
Import upstream version 3.3.6
453
        BrokenFileHeader=true;
1.2.12 by Martin Meredith
Import upstream version 4.1.4
454
1.2.13 by Nick Andrik
Import upstream version 4.2.4
455
        ErrHandler.SetErrorCode(RARX_CRC);
1 by Chris Anderson
Import upstream version 3.3.6
456
        return(0);
457
      }
458
    }
459
  }
460
461
  if (NextBlockPos<=CurBlockPos)
462
  {
463
#ifndef SHELL_EXT
464
    Log(FileName,St(MLogFileHead),"???");
465
#endif
466
    BrokenFileHeader=true;
1.2.13 by Nick Andrik
Import upstream version 4.2.4
467
    ErrHandler.SetErrorCode(RARX_CRC);
1 by Chris Anderson
Import upstream version 3.3.6
468
    return(0);
469
  }
470
  return(Raw.Size());
471
}
472
473
474
#ifndef SFX_MODULE
1.2.4 by Martin Meredith
Import upstream version 3.9.3
475
size_t Archive::ReadOldHeader()
1 by Chris Anderson
Import upstream version 3.3.6
476
{
477
  RawRead Raw(this);
1.2.4 by Martin Meredith
Import upstream version 3.9.3
478
  if (CurBlockPos<=(int64)SFXSize)
1 by Chris Anderson
Import upstream version 3.3.6
479
  {
480
    Raw.Read(SIZEOF_OLDMHD);
481
    Raw.Get(OldMhd.Mark,4);
482
    Raw.Get(OldMhd.HeadSize);
483
    Raw.Get(OldMhd.Flags);
484
    NextBlockPos=CurBlockPos+OldMhd.HeadSize;
485
    CurHeaderType=MAIN_HEAD;
486
  }
487
  else
488
  {
489
    OldFileHeader OldLhd;
490
    Raw.Read(SIZEOF_OLDLHD);
491
    NewLhd.HeadType=FILE_HEAD;
492
    Raw.Get(NewLhd.PackSize);
493
    Raw.Get(NewLhd.UnpSize);
494
    Raw.Get(OldLhd.FileCRC);
495
    Raw.Get(NewLhd.HeadSize);
496
    Raw.Get(NewLhd.FileTime);
497
    Raw.Get(OldLhd.FileAttr);
498
    Raw.Get(OldLhd.Flags);
499
    Raw.Get(OldLhd.UnpVer);
500
    Raw.Get(OldLhd.NameSize);
501
    Raw.Get(OldLhd.Method);
502
503
    NewLhd.Flags=OldLhd.Flags|LONG_BLOCK;
504
    NewLhd.UnpVer=(OldLhd.UnpVer==2) ? 13 : 10;
505
    NewLhd.Method=OldLhd.Method+0x30;
506
    NewLhd.NameSize=OldLhd.NameSize;
507
    NewLhd.FileAttr=OldLhd.FileAttr;
508
    NewLhd.FileCRC=OldLhd.FileCRC;
509
    NewLhd.FullPackSize=NewLhd.PackSize;
510
    NewLhd.FullUnpSize=NewLhd.UnpSize;
511
1.1.2 by Jeroen van Wolffelaar
Import upstream version 3.5.2
512
    NewLhd.mtime.SetDos(NewLhd.FileTime);
513
    NewLhd.ctime.Reset();
514
    NewLhd.atime.Reset();
515
    NewLhd.arctime.Reset();
516
1 by Chris Anderson
Import upstream version 3.3.6
517
    Raw.Read(OldLhd.NameSize);
518
    Raw.Get((byte *)NewLhd.FileName,OldLhd.NameSize);
519
    NewLhd.FileName[OldLhd.NameSize]=0;
520
    ConvertNameCase(NewLhd.FileName);
521
    *NewLhd.FileNameW=0;
522
523
    if (Raw.Size()!=0)
524
      NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize;
525
    CurHeaderType=FILE_HEAD;
526
  }
1.1.1 by Chris Anderson
Import upstream version 3.4.3
527
  return(NextBlockPos>CurBlockPos ? Raw.Size():0);
1 by Chris Anderson
Import upstream version 3.3.6
528
}
529
#endif
530
531
532
void Archive::ConvertNameCase(char *Name)
533
{
534
  if (Cmd->ConvertNames==NAMES_UPPERCASE)
535
  {
536
    IntToExt(Name,Name);
537
    strupper(Name);
538
    ExtToInt(Name,Name);
539
  }
540
  if (Cmd->ConvertNames==NAMES_LOWERCASE)
541
  {
542
    IntToExt(Name,Name);
543
    strlower(Name);
544
    ExtToInt(Name,Name);
545
  }
546
}
547
548
549
#ifndef SFX_MODULE
550
void Archive::ConvertNameCase(wchar *Name)
551
{
552
  if (Cmd->ConvertNames==NAMES_UPPERCASE)
1.2.10 by Martin Meredith
Import upstream version 4.0.2
553
    wcsupper(Name);
1 by Chris Anderson
Import upstream version 3.3.6
554
  if (Cmd->ConvertNames==NAMES_LOWERCASE)
1.2.10 by Martin Meredith
Import upstream version 4.0.2
555
    wcslower(Name);
1 by Chris Anderson
Import upstream version 3.3.6
556
}
557
#endif
558
559
560
bool Archive::IsArcDir()
561
{
562
  return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY);
563
}
564
565
566
bool Archive::IsArcLabel()
567
{
568
  return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8));
569
}
570
571
572
void Archive::ConvertAttributes()
573
{
1.2.10 by Martin Meredith
Import upstream version 4.0.2
574
#if defined(_WIN_ALL) || defined(_EMX)
1 by Chris Anderson
Import upstream version 3.3.6
575
  switch(NewLhd.HostOS)
576
  {
577
    case HOST_MSDOS:
578
    case HOST_OS2:
579
    case HOST_WIN32:
580
      break;
581
    case HOST_UNIX:
582
    case HOST_BEOS:
583
      if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
584
        NewLhd.FileAttr=0x10;
585
      else
586
        NewLhd.FileAttr=0x20;
587
      break;
588
    default:
589
      if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
590
        NewLhd.FileAttr=0x10;
591
      else
592
        NewLhd.FileAttr=0x20;
593
      break;
594
  }
595
#endif
596
#ifdef _UNIX
1.2.4 by Martin Meredith
Import upstream version 3.9.3
597
  // umask defines which permission bits must not be set by default
1.2.12 by Martin Meredith
Import upstream version 4.1.4
598
  // when creating a file or directory. The typical default value
599
  // for the process umask is S_IWGRP | S_IWOTH (octal 022),
600
  // resulting in 0644 mode for new files.
1 by Chris Anderson
Import upstream version 3.3.6
601
  static mode_t mask = (mode_t) -1;
602
603
  if (mask == (mode_t) -1)
604
  {
1.2.4 by Martin Meredith
Import upstream version 3.9.3
605
    // umask call returns the current umask value. Argument (022) is not 
1.2.12 by Martin Meredith
Import upstream version 4.1.4
606
    // really important here.
1 by Chris Anderson
Import upstream version 3.3.6
607
    mask = umask(022);
1.2.4 by Martin Meredith
Import upstream version 3.9.3
608
609
    // Restore the original umask value, which was changed to 022 above.
1 by Chris Anderson
Import upstream version 3.3.6
610
    umask(mask);
611
  }
1.2.4 by Martin Meredith
Import upstream version 3.9.3
612
1 by Chris Anderson
Import upstream version 3.3.6
613
  switch(NewLhd.HostOS)
614
  {
615
    case HOST_MSDOS:
616
    case HOST_OS2:
617
    case HOST_WIN32:
1.2.4 by Martin Meredith
Import upstream version 3.9.3
618
      {
619
        // Mapping MSDOS, OS/2 and Windows file attributes to Unix.
620
621
        if (NewLhd.FileAttr & 0x10) // FILE_ATTRIBUTE_DIRECTORY
622
        {
623
          // For directories we use 0777 mask.
624
          NewLhd.FileAttr=0777 & ~mask;
625
        }
1 by Chris Anderson
Import upstream version 3.3.6
626
        else
1.2.4 by Martin Meredith
Import upstream version 3.9.3
627
          if (NewLhd.FileAttr & 1)  // FILE_ATTRIBUTE_READONLY
628
          {
629
            // For read only files we use 0444 mask with 'w' bits turned off.
630
            NewLhd.FileAttr=0444 & ~mask;
631
          }
632
          else
633
          {
1.2.5 by Martin Meredith
Import upstream version 3.9.5
634
            // umask does not set +x for regular files, so we use 0666
1.2.4 by Martin Meredith
Import upstream version 3.9.3
635
            // instead of 0777 as for directories.
636
            NewLhd.FileAttr=0666 & ~mask;
637
          }
638
      }
1 by Chris Anderson
Import upstream version 3.3.6
639
      break;
640
    case HOST_UNIX:
641
    case HOST_BEOS:
642
      break;
643
    default:
644
      if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
645
        NewLhd.FileAttr=0x41ff & ~mask;
646
      else
647
        NewLhd.FileAttr=0x81b6 & ~mask;
648
      break;
649
  }
650
#endif
651
}
652
653
654
void Archive::ConvertUnknownHeader()
655
{
656
  if (NewLhd.UnpVer<20 && (NewLhd.FileAttr & 0x10))
657
    NewLhd.Flags|=LHD_DIRECTORY;
658
  if (NewLhd.HostOS>=HOST_MAX)
659
  {
660
    if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
661
      NewLhd.FileAttr=0x10;
662
    else
663
      NewLhd.FileAttr=0x20;
664
  }
665
  for (char *s=NewLhd.FileName;*s!=0;s=charnext(s))
666
  {
667
    if (*s=='/' || *s=='\\')
668
      *s=CPATHDIVIDER;
669
#if defined(_APPLE) && !defined(UNICODE_SUPPORTED)
670
    if ((byte)*s<32 || (byte)*s>127)
671
      *s='_';
672
#endif
1.2.1 by Martin Meredith
Import upstream version 3.8.2
673
1.2.10 by Martin Meredith
Import upstream version 4.0.2
674
#if defined(_WIN_ALL) || defined(_EMX)
1.2.1 by Martin Meredith
Import upstream version 3.8.2
675
    // ':' in file names is allowed in Unix, but not in Windows.
676
    // Even worse, file data will be written to NTFS stream on NTFS,
677
    // so automatic name correction on file create error in extraction 
1.2.2 by Martin Meredith
Import upstream version 3.8.4
678
    // routine does not work. In Windows and DOS versions we better 
679
    // replace ':' now.
680
    if (*s==':')
1.2.1 by Martin Meredith
Import upstream version 3.8.2
681
      *s='_';
682
#endif
683
1 by Chris Anderson
Import upstream version 3.3.6
684
  }
1.2.1 by Martin Meredith
Import upstream version 3.8.2
685
1 by Chris Anderson
Import upstream version 3.3.6
686
  for (wchar *s=NewLhd.FileNameW;*s!=0;s++)
1.2.1 by Martin Meredith
Import upstream version 3.8.2
687
  {
1 by Chris Anderson
Import upstream version 3.3.6
688
    if (*s=='/' || *s=='\\')
689
      *s=CPATHDIVIDER;
1.2.1 by Martin Meredith
Import upstream version 3.8.2
690
1.2.10 by Martin Meredith
Import upstream version 4.0.2
691
#if defined(_WIN_ALL) || defined(_EMX)
1.2.1 by Martin Meredith
Import upstream version 3.8.2
692
    // ':' in file names is allowed in Unix, but not in Windows.
693
    // Even worse, file data will be written to NTFS stream on NTFS,
694
    // so automatic name correction on file create error in extraction 
1.2.2 by Martin Meredith
Import upstream version 3.8.4
695
    // routine does not work. In Windows and DOS versions we better 
696
    // replace ':' now.
697
    if (*s==':')
1.2.1 by Martin Meredith
Import upstream version 3.8.2
698
      *s='_';
699
#endif
700
  }
1 by Chris Anderson
Import upstream version 3.3.6
701
}
702
703
704
#ifndef SHELL_EXT
705
bool Archive::ReadSubData(Array<byte> *UnpData,File *DestFile)
706
{
707
  if (HeaderCRC!=SubHead.HeadCRC)
708
  {
709
#ifndef SHELL_EXT
710
    Log(FileName,St(MSubHeadCorrupt));
711
#endif
1.2.13 by Nick Andrik
Import upstream version 4.2.4
712
    ErrHandler.SetErrorCode(RARX_CRC);
1 by Chris Anderson
Import upstream version 3.3.6
713
    return(false);
714
  }
1.1.4 by Martin Meredith
Import upstream version 3.6.8
715
  if (SubHead.Method<0x30 || SubHead.Method>0x35 || SubHead.UnpVer>/*PACK_VER*/36)
1 by Chris Anderson
Import upstream version 3.3.6
716
  {
717
#ifndef SHELL_EXT
718
    Log(FileName,St(MSubHeadUnknown));
719
#endif
720
    return(false);
721
  }
722
723
  if (SubHead.PackSize==0 && (SubHead.Flags & LHD_SPLIT_AFTER)==0)
724
    return(true);
725
726
  SubDataIO.Init();
727
  Unpack Unpack(&SubDataIO);
728
  Unpack.Init();
729
730
  if (DestFile==NULL)
731
  {
732
    UnpData->Alloc(SubHead.UnpSize);
733
    SubDataIO.SetUnpackToMemory(&(*UnpData)[0],SubHead.UnpSize);
734
  }
735
  if (SubHead.Flags & LHD_PASSWORD)
1.2.13 by Nick Andrik
Import upstream version 4.2.4
736
    if (Cmd->Password.IsSet())
737
      SubDataIO.SetEncryption(SubHead.UnpVer,&Cmd->Password,
1.1.4 by Martin Meredith
Import upstream version 3.6.8
738
             (SubHead.Flags & LHD_SALT) ? SubHead.Salt:NULL,false,
739
             SubHead.UnpVer>=36);
1 by Chris Anderson
Import upstream version 3.3.6
740
    else
741
      return(false);
742
  SubDataIO.SetPackedSizeToRead(SubHead.PackSize);
743
  SubDataIO.EnableShowProgress(false);
744
  SubDataIO.SetFiles(this,DestFile);
1.2.4 by Martin Meredith
Import upstream version 3.9.3
745
  SubDataIO.UnpVolume=(SubHead.Flags & LHD_SPLIT_AFTER)!=0;
1 by Chris Anderson
Import upstream version 3.3.6
746
  SubDataIO.SetSubHeader(&SubHead,NULL);
747
  Unpack.SetDestSize(SubHead.UnpSize);
748
  if (SubHead.Method==0x30)
749
    CmdExtract::UnstoreFile(SubDataIO,SubHead.UnpSize);
750
  else
751
    Unpack.DoUnpack(SubHead.UnpVer,false);
752
753
  if (SubHead.FileCRC!=~SubDataIO.UnpFileCRC)
754
  {
755
#ifndef SHELL_EXT
756
    Log(FileName,St(MSubHeadDataCRC),SubHead.FileName);
757
#endif
1.2.13 by Nick Andrik
Import upstream version 4.2.4
758
    ErrHandler.SetErrorCode(RARX_CRC);
1 by Chris Anderson
Import upstream version 3.3.6
759
    if (UnpData!=NULL)
760
      UnpData->Reset();
761
    return(false);
762
  }
763
  return(true);
764
}
765
#endif