~ubuntu-branches/ubuntu/saucy/unrar-nonfree/saucy

« back to all changes in this revision

Viewing changes to pathfn.cpp

  • Committer: Package Import Robot
  • Author(s): Martin Meredith
  • Date: 2012-02-14 22:39:32 UTC
  • mfrom: (1.1.15) (5.1.13 sid)
  • Revision ID: package-import@ubuntu.com-20120214223932-3785038bqlknu15a
Tags: 1:4.1.4-1
* New upstream release
* Updated Watch file
* Added build-indep and build-arch to rules file

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
      DestPtr=s+4;
47
47
 
48
48
  // Remove any sequence of . and \ in the beginning of path string.
49
 
  while (*DestPtr)
 
49
  while (*DestPtr!=0)
50
50
  {
51
51
    const char *s=DestPtr;
52
52
    if (s[0] && IsDriveDiv(s[1]))
88
88
wchar* ConvertPath(const wchar *SrcPath,wchar *DestPath)
89
89
{
90
90
  const wchar *DestPtr=SrcPath;
 
91
 
 
92
  // Prevent \..\ in any part of path string.
91
93
  for (const wchar *s=DestPtr;*s!=0;s++)
92
94
    if (IsPathDiv(s[0]) && s[1]=='.' && s[2]=='.' && IsPathDiv(s[3]))
93
95
      DestPtr=s+4;
94
 
  while (*DestPtr)
 
96
 
 
97
  // Remove any sequence of . and \ in the beginning of path string.
 
98
  while (*DestPtr!=0)
95
99
  {
96
100
    const wchar *s=DestPtr;
97
101
    if (s[0] && IsDriveDiv(s[1]))
112
116
      break;
113
117
    DestPtr=s;
114
118
  }
 
119
 
 
120
  // Code above does not remove last "..", doing here.
 
121
  if (DestPtr[0]=='.' && DestPtr[1]=='.' && DestPtr[2]==0)
 
122
    DestPtr+=2;
 
123
  
115
124
  if (DestPath!=NULL)
116
125
  {
 
126
    // SrcPath and DestPath can point to same memory area,
 
127
    // so we use the temporary buffer for copying.
117
128
    wchar TmpStr[NM];
118
 
    wcsncpy(TmpStr,DestPtr,sizeof(TmpStr)/sizeof(TmpStr[0])-1);
 
129
    wcsncpyz(TmpStr,DestPtr,ASIZE(TmpStr));
119
130
    wcscpy(DestPath,TmpStr);
120
131
  }
121
132
  return((wchar *)DestPtr);
205
216
}
206
217
 
207
218
 
 
219
// 'Ext' is an extension without the leading dot, like "rar".
208
220
bool CmpExt(const char *Name,const char *Ext)
209
221
{
210
222
  char *NameExt=GetExt(Name);
212
224
}
213
225
 
214
226
 
 
227
// 'Ext' is an extension without the leading dot, like L"rar".
215
228
bool CmpExt(const wchar *Name,const wchar *Ext)
216
229
{
217
230
  wchar *NameExt=GetExt(Name);
310
323
}
311
324
 
312
325
 
313
 
#ifndef SFX_MODULE
314
326
// Removes name and returns file path without the trailing
315
327
// path separator symbol.
316
328
void RemoveNameFromPath(wchar *Path)
320
332
    Name--;
321
333
  *Name=0;
322
334
}
323
 
#endif
324
335
 
325
336
 
326
337
#if defined(_WIN_ALL) && !defined(_WIN_CE) && !defined(SFX_MODULE)
593
604
    char *ChPtr;
594
605
    if ((ChPtr=GetExt(ArcName))==NULL)
595
606
    {
596
 
      strcat(ArcName,".rar");
 
607
      strncatz(ArcName,".rar",MaxLength);
597
608
      ChPtr=GetExt(ArcName);
598
609
    }
599
610
    else
600
 
      if (ChPtr[1]==0 || stricomp(ChPtr+1,"exe")==0 || stricomp(ChPtr+1,"sfx")==0)
 
611
      if (ChPtr[1]==0 && strlen(ArcName)<MaxLength-3 || stricomp(ChPtr+1,"exe")==0 || stricomp(ChPtr+1,"sfx")==0)
601
612
        strcpy(ChPtr+1,"rar");
602
613
    if (!OldNumbering)
603
614
    {
641
652
    wchar *ChPtr;
642
653
    if ((ChPtr=GetExt(ArcNameW))==NULL)
643
654
    {
644
 
      wcscat(ArcNameW,L".rar");
 
655
      wcsncatz(ArcNameW,L".rar",MaxLength);
645
656
      ChPtr=GetExt(ArcNameW);
646
657
    }
647
658
    else
648
 
      if (ChPtr[1]==0 || wcsicomp(ChPtr+1,L"exe")==0 || wcsicomp(ChPtr+1,L"sfx")==0)
 
659
      if (ChPtr[1]==0 && wcslen(ArcNameW)<MaxLength-3 || wcsicomp(ChPtr+1,L"exe")==0 || wcsicomp(ChPtr+1,L"sfx")==0)
649
660
        wcscpy(ChPtr+1,L"rar");
650
661
    if (!OldNumbering)
651
662
    {
699
710
      return(false);
700
711
  }
701
712
#endif
 
713
#ifdef _WIN_ALL
 
714
  // In Windows we need to check if all file name characters are defined
 
715
  // in current code page. For example, in Korean CP949 a lot of high ASCII
 
716
  // characters are not defined, cannot be used in file names, but cannot be
 
717
  // detected by other checks in this function.
 
718
  if (MultiByteToWideChar(CP_ACP,MB_ERR_INVALID_CHARS,Name,-1,NULL,0)==0 &&
 
719
      GetLastError()==ERROR_NO_UNICODE_TRANSLATION)
 
720
    return false;
 
721
#endif
702
722
  return(*Name!=0 && strpbrk(Name,"?*<>|\"")==NULL);
703
723
}
704
724
 
705
725
 
 
726
bool IsNameUsable(const wchar *Name)
 
727
{
 
728
#ifndef _UNIX
 
729
  if (Name[0] && Name[1] && wcschr(Name+2,':')!=NULL)
 
730
    return(false);
 
731
  for (const wchar *s=Name;*s!=0;s++)
 
732
  {
 
733
    if ((uint)*s<32)
 
734
      return(false);
 
735
    if (*s==' ' && IsPathDiv(s[1]))
 
736
      return(false);
 
737
  }
 
738
#endif
 
739
  return(*Name!=0 && wcspbrk(Name,L"?*<>|\"")==NULL);
 
740
}
 
741
 
 
742
 
706
743
void MakeNameUsable(char *Name,bool Extended)
707
744
{
 
745
#ifdef _WIN_ALL
 
746
  // In Windows we also need to convert characters not defined in current
 
747
  // code page. This double conversion changes them to '?', which is
 
748
  // catched by code below.
 
749
  size_t NameLength=strlen(Name);
 
750
  wchar NameW[NM];
 
751
  CharToWide(Name,NameW,ASIZE(NameW));
 
752
  WideToChar(NameW,Name,NameLength+1);
 
753
  Name[NameLength]=0;
 
754
#endif
708
755
  for (char *s=Name;*s!=0;s=charnext(s))
709
756
  {
710
757
    if (strchr(Extended ? "?*<>|\"":"?*",*s)!=NULL || Extended && (byte)*s<32)
805
852
}
806
853
 
807
854
 
 
855
wchar* DosSlashToUnix(wchar *SrcName,wchar *DestName,uint MaxLength)
 
856
{
 
857
  if (DestName!=NULL && DestName!=SrcName)
 
858
    if (wcslen(SrcName)>=MaxLength)
 
859
    {
 
860
      *DestName=0;
 
861
      return(DestName);
 
862
    }
 
863
    else
 
864
      wcscpy(DestName,SrcName);
 
865
  for (wchar *s=SrcName;*s!=0;s++)
 
866
  {
 
867
    if (*s=='\\')
 
868
      if (DestName==NULL)
 
869
        *s='/';
 
870
      else
 
871
        DestName[s-SrcName]='/';
 
872
  }
 
873
  return(DestName==NULL ? SrcName:DestName);
 
874
}
 
875
 
 
876
 
808
877
void ConvertNameToFull(const char *Src,char *Dest)
809
878
{
810
879
#ifdef _WIN_ALL
1103
1172
#endif
1104
1173
 
1105
1174
 
 
1175
#ifndef SFX_MODULE
 
1176
static void GenArcName(char *ArcName,wchar *ArcNameW,char *GenerateMask,
 
1177
                       uint ArcNumber,bool &ArcNumPresent);
 
1178
 
 
1179
void GenerateArchiveName(char *ArcName,wchar *ArcNameW,size_t MaxSize,
 
1180
                         char *GenerateMask,bool Archiving)
 
1181
{
 
1182
  // Must be enough space for archive name plus all stuff in mask plus
 
1183
  // extra overhead produced by mask 'N' (archive number) characters.
 
1184
  // One 'N' character can result in several numbers if we process more
 
1185
  // than 9 archives.
 
1186
  char NewName[NM+MAX_GENERATE_MASK+20];
 
1187
  wchar NewNameW[NM+MAX_GENERATE_MASK+20];
 
1188
 
 
1189
  uint ArcNumber=1;
 
1190
  while (true) // Loop for 'N' (archive number) processing.
 
1191
  {
 
1192
    strncpyz(NewName,NullToEmpty(ArcName),ASIZE(NewName));
 
1193
    wcsncpyz(NewNameW,NullToEmpty(ArcNameW),ASIZE(NewNameW));
 
1194
    
 
1195
    bool ArcNumPresent=false;
 
1196
 
 
1197
    GenArcName(NewName,NewNameW,GenerateMask,ArcNumber,ArcNumPresent);
 
1198
    
 
1199
    if (!ArcNumPresent)
 
1200
      break;
 
1201
    if (!FileExist(NewName,NewNameW))
 
1202
    {
 
1203
      if (!Archiving && ArcNumber>1)
 
1204
      {
 
1205
        // If we perform non-archiving operation, we need to use the last
 
1206
        // existing archive before the first unused name. So we generate
 
1207
        // the name for (ArcNumber-1) below.
 
1208
        strncpyz(NewName,NullToEmpty(ArcName),ASIZE(NewName));
 
1209
        wcsncpyz(NewNameW,NullToEmpty(ArcNameW),ASIZE(NewNameW));
 
1210
        GenArcName(NewName,NewNameW,GenerateMask,ArcNumber-1,ArcNumPresent);
 
1211
      }
 
1212
      break;
 
1213
    }
 
1214
    ArcNumber++;
 
1215
  }
 
1216
  if (ArcName!=NULL && *ArcName!=0)
 
1217
    strncpyz(ArcName,NewName,MaxSize);
 
1218
  if (ArcNameW!=NULL && *ArcNameW!=0)
 
1219
    wcsncpyz(ArcNameW,NewNameW,MaxSize);
 
1220
}
 
1221
 
 
1222
 
 
1223
void GenArcName(char *ArcName,wchar *ArcNameW,char *GenerateMask,
 
1224
                uint ArcNumber,bool &ArcNumPresent)
 
1225
{
 
1226
  bool Prefix=false;
 
1227
  if (*GenerateMask=='+')
 
1228
  {
 
1229
    Prefix=true;    // Add the time string before the archive name.
 
1230
    GenerateMask++; // Skip '+' in the beginning of time mask.
 
1231
  }
 
1232
 
 
1233
  char Mask[MAX_GENERATE_MASK];
 
1234
  strncpyz(Mask,*GenerateMask ? GenerateMask:"yyyymmddhhmmss",ASIZE(Mask));
 
1235
 
 
1236
  bool QuoteMode=false,Hours=false;
 
1237
  for (uint I=0;Mask[I]!=0;I++)
 
1238
  {
 
1239
    if (Mask[I]=='{' || Mask[I]=='}')
 
1240
    {
 
1241
      QuoteMode=(Mask[I]=='{');
 
1242
      continue;
 
1243
    }
 
1244
    if (QuoteMode)
 
1245
      continue;
 
1246
    int CurChar=etoupper(Mask[I]);
 
1247
    if (CurChar=='H')
 
1248
      Hours=true;
 
1249
 
 
1250
    if (Hours && CurChar=='M')
 
1251
    {
 
1252
      // Replace minutes with 'I'. We use 'M' both for months and minutes,
 
1253
      // so we treat as minutes only those 'M' which are found after hours.
 
1254
      Mask[I]='I';
 
1255
    }
 
1256
    if (CurChar=='N')
 
1257
    {
 
1258
      uint Digits=GetDigits(ArcNumber);
 
1259
      uint NCount=0;
 
1260
      while (etoupper(Mask[I+NCount])=='N')
 
1261
        NCount++;
 
1262
 
 
1263
      // Here we ensure that we have enough 'N' characters to fit all digits
 
1264
      // of archive number. We'll replace them by actual number later
 
1265
      // in this function.
 
1266
      if (NCount<Digits)
 
1267
      {
 
1268
        memmove(Mask+I+Digits,Mask+I+NCount,strlen(Mask+I+NCount)+1);
 
1269
        memset(Mask+I,'N',Digits);
 
1270
      }
 
1271
      I+=Max(Digits,NCount)-1;
 
1272
      ArcNumPresent=true;
 
1273
      continue;
 
1274
    }
 
1275
  }
 
1276
 
 
1277
  RarTime CurTime;
 
1278
  CurTime.SetCurrentTime();
 
1279
  RarLocalTime rlt;
 
1280
  CurTime.GetLocal(&rlt);
 
1281
 
 
1282
  char Ext[NM];
 
1283
  *Ext=0;
 
1284
  if (ArcName!=NULL && *ArcName!=0)
 
1285
  {
 
1286
    char *Dot;
 
1287
    if ((Dot=GetExt(ArcName))==NULL)
 
1288
      strcpy(Ext,*PointToName(ArcName)==0 ? ".rar":"");
 
1289
    else
 
1290
    {
 
1291
      strcpy(Ext,Dot);
 
1292
      *Dot=0;
 
1293
    }
 
1294
  }
 
1295
 
 
1296
  wchar ExtW[NM];
 
1297
  *ExtW=0;
 
1298
  if (ArcNameW!=NULL && *ArcNameW!=0)
 
1299
  {
 
1300
    wchar *DotW;
 
1301
    if ((DotW=GetExt(ArcNameW))==NULL)
 
1302
      wcscpy(ExtW,*PointToName(ArcNameW)==0 ? L".rar":L"");
 
1303
    else
 
1304
    {
 
1305
      wcscpy(ExtW,DotW);
 
1306
      *DotW=0;
 
1307
    }
 
1308
  }
 
1309
 
 
1310
  int WeekDay=rlt.wDay==0 ? 6:rlt.wDay-1;
 
1311
  int StartWeekDay=rlt.yDay-WeekDay;
 
1312
  if (StartWeekDay<0)
 
1313
    if (StartWeekDay<=-4)
 
1314
      StartWeekDay+=IsLeapYear(rlt.Year-1) ? 366:365;
 
1315
    else
 
1316
      StartWeekDay=0;
 
1317
  int CurWeek=StartWeekDay/7+1;
 
1318
  if (StartWeekDay%7>=4)
 
1319
    CurWeek++;
 
1320
 
 
1321
  char Field[10][6];
 
1322
 
 
1323
  sprintf(Field[0],"%04d",rlt.Year);
 
1324
  sprintf(Field[1],"%02d",rlt.Month);
 
1325
  sprintf(Field[2],"%02d",rlt.Day);
 
1326
  sprintf(Field[3],"%02d",rlt.Hour);
 
1327
  sprintf(Field[4],"%02d",rlt.Minute);
 
1328
  sprintf(Field[5],"%02d",rlt.Second);
 
1329
  sprintf(Field[6],"%02d",CurWeek);
 
1330
  sprintf(Field[7],"%d",WeekDay+1);
 
1331
  sprintf(Field[8],"%03d",rlt.yDay+1);
 
1332
  sprintf(Field[9],"%05d",ArcNumber);
 
1333
 
 
1334
  const char *MaskChars="YMDHISWAEN";
 
1335
 
 
1336
  int CField[sizeof(Field)/sizeof(Field[0])];
 
1337
  memset(CField,0,sizeof(CField));
 
1338
  QuoteMode=false;
 
1339
  for (int I=0;Mask[I]!=0;I++)
 
1340
  {
 
1341
    if (Mask[I]=='{' || Mask[I]=='}')
 
1342
    {
 
1343
      QuoteMode=(Mask[I]=='{');
 
1344
      continue;
 
1345
    }
 
1346
    if (QuoteMode)
 
1347
      continue;
 
1348
    const char *Ch=strchr(MaskChars,etoupper(Mask[I]));
 
1349
    if (Ch!=NULL)
 
1350
      CField[Ch-MaskChars]++;
 
1351
   }
 
1352
 
 
1353
  char DateText[MAX_GENERATE_MASK];
 
1354
  *DateText=0;
 
1355
  QuoteMode=false;
 
1356
  for (size_t I=0,J=0;Mask[I]!=0 && J<ASIZE(DateText)-1;I++)
 
1357
  {
 
1358
    if (Mask[I]=='{' || Mask[I]=='}')
 
1359
    {
 
1360
      QuoteMode=(Mask[I]=='{');
 
1361
      continue;
 
1362
    }
 
1363
    const char *Ch=strchr(MaskChars,etoupper(Mask[I]));
 
1364
    if (Ch==NULL || QuoteMode)
 
1365
      DateText[J]=Mask[I];
 
1366
    else
 
1367
    {
 
1368
      size_t FieldPos=Ch-MaskChars;
 
1369
      int CharPos=(int)strlen(Field[FieldPos])-CField[FieldPos]--;
 
1370
      if (FieldPos==1 && etoupper(Mask[I+1])=='M' && etoupper(Mask[I+2])=='M')
 
1371
      {
 
1372
        strncpyz(DateText+J,GetMonthName(rlt.Month-1),ASIZE(DateText)-J);
 
1373
        J=strlen(DateText);
 
1374
        I+=2;
 
1375
        continue;
 
1376
      }
 
1377
      if (CharPos<0)
 
1378
        DateText[J]=Mask[I];
 
1379
      else
 
1380
        DateText[J]=Field[FieldPos][CharPos];
 
1381
    }
 
1382
    DateText[++J]=0;
 
1383
  }
 
1384
 
 
1385
  wchar DateTextW[ASIZE(DateText)];
 
1386
  CharToWide(DateText,DateTextW);
 
1387
 
 
1388
  if (Prefix)
 
1389
  {
 
1390
    if (ArcName!=NULL && *ArcName!=0)
 
1391
    {
 
1392
      char NewName[NM];
 
1393
      GetFilePath(ArcName,NewName,ASIZE(NewName));
 
1394
      AddEndSlash(NewName);
 
1395
      strcat(NewName,DateText);
 
1396
      strcat(NewName,PointToName(ArcName));
 
1397
      strcpy(ArcName,NewName);
 
1398
    }
 
1399
    if (ArcNameW!=NULL && *ArcNameW!=0)
 
1400
    {
 
1401
      wchar NewNameW[NM];
 
1402
      GetFilePath(ArcNameW,NewNameW,ASIZE(NewNameW));
 
1403
      AddEndSlash(NewNameW);
 
1404
      wcscat(NewNameW,DateTextW);
 
1405
      wcscat(NewNameW,PointToName(ArcNameW));
 
1406
      wcscpy(ArcNameW,NewNameW);
 
1407
    }
 
1408
  }
 
1409
  else
 
1410
  {
 
1411
    if (ArcName!=NULL && *ArcName!=0)
 
1412
      strcat(ArcName,DateText);
 
1413
    if (ArcNameW!=NULL && *ArcNameW!=0)
 
1414
      wcscat(ArcNameW,DateTextW);
 
1415
  }
 
1416
  if (ArcName!=NULL && *ArcName!=0)
 
1417
    strcat(ArcName,Ext);
 
1418
  if (ArcNameW!=NULL && *ArcNameW!=0)
 
1419
    wcscat(ArcNameW,ExtW);
 
1420
}
 
1421
#endif
1106
1422
 
1107
1423
 
1108
1424
wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize)