Subversion Repositories spk

Rev

Rev 134 | Rev 155 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 cycrow 1
// File.cpp: implementation of the C_File class.
2
//
3
//////////////////////////////////////////////////////////////////////
4
 
5
#include "File.h"
6
 
7
#include <time.h>
8
#include <sys/types.h>
9
#include <sys/stat.h>
10
 
11
#ifndef _WIN32
12
#include <unistd.h>
13
#endif
14
 
15
#include <iostream>
16
#include <fstream>
17
 
18
#include "spk.h"
19
 
6 cycrow 20
#include "BaseFile.h"
1 cycrow 21
#include "CatFile.h"
22
#include "DirIO.h"
23
 
24
#include "secure.h"
25
 
26
// LZMA compression
27
#include "lzma/Lzma86Enc.h"
28
#include "lzma/Lzma86Dec.h"
29
 
115 cycrow 30
// X2BOD
31
/*
32
#include "x2bc/x2bc_common/settings.h"
33
#include "x2bc/x2bc_common/bob_dom.h"
34
#include "x2bc/x2bc_common/bod_parser.h"
35
#include "x2bc/x2bc_common/realfile_stream.h"
36
*/
37
#include "../Windows/libx2bc.h"
38
 
1 cycrow 39
//////////////////////////////////////////////////////////////////////
127 cycrow 40
// STATIC FUNCTIONS
41
//////////////////////////////////////////////////////////////////////
42
 
43
Utils::String C_File::GetDirectory(FileType eType, const Utils::String &filename, CBaseFile *file)
44
{
45
	switch (eType)
46
	{
47
	case FILETYPE_SCRIPT:
48
		return "Scripts";
49
	case FILETYPE_TEXT:
50
		return "T";
51
	case FILETYPE_README:
52
	{
53
		if (file)
134 cycrow 54
			return Utils::String("PluginManager/Readme/") + file->getNameValidFile();
127 cycrow 55
		return "PluginManager/Readme";
56
	}
57
	case FILETYPE_MAP:
58
		return "Maps";
59
	case FILETYPE_MOD:
60
		return "Mods";
61
	case FILETYPE_UNINSTALL:
62
		return "PluginManager/Uninstall";
63
	case FILETYPE_SOUND:
64
		if (!filename.empty() && !CFileIO(filename).CheckFileExtension("wav"))
65
			return "Soundtrack";
66
		return "s";
67
	case FILETYPE_SOUNDTRACK:
68
		return "Soundtrack";
69
	case FILETYPE_EXTRA:
70
		return "PluginManager/Extras";
71
	case FILETYPE_SCREEN:
72
		return "loadscr";
73
	case FILETYPE_ADVERT:
74
		return "PluginManager/Graphics";
75
	case FILETYPE_MISSION:
76
		return "Director";
77
	}
78
	return Utils::String::Null();
79
}
80
 
81
bool C_File::DoesTypeHaveExtraDir(int i)
82
{
83
	switch (i)
84
	{
85
	case FILETYPE_EXTRA:
86
	case FILETYPE_SHIPSCENE:
87
	case FILETYPE_COCKPITSCENE:
88
	case FILETYPE_SHIPMODEL:
89
	case FILETYPE_SHIPOTHER:
90
		return true;
91
	}
92
	return false;
93
}
94
 
95
//////////////////////////////////////////////////////////////////////
1 cycrow 96
// Construction/Destruction
97
//////////////////////////////////////////////////////////////////////
98
 
99
void CProgressInfoDone::DoingFile ( C_File *file )
100
{
101
	m_iDone = 0;
102
 
103
	if ( !m_bDontDoMax )
104
	{
105
		if ( file->GetData() && file->GetDataSize() )
106
			m_lMaxSize = file->GetDataSize();
107
		else
108
			m_lMaxSize = file->GetSize();
109
	}
110
 
111
	m_pOnFile = file;
112
}
113
 
114
void CProgressInfoDone::DoingPackage ( SMultiSpkFile *file )
115
{
116
	m_iDone = 0;
117
 
118
	if ( !m_bDontDoMax )
119
		m_lMaxSize = file->lSize;
120
 
121
	m_pOnPackage = file;
122
}
123
 
124
int C_File::m_iTempNum = 0;
125
 
126
C_File::C_File()
127
{
128
	m_bDontDeleteData = false;
129
	m_bUsedMalloc = false;
130
	m_sData = NULL;
131
	Reset();
132
}
133
 
127 cycrow 134
C_File::C_File(const Utils::String &filename)
1 cycrow 135
{
136
	m_bDontDeleteData = false;
137
	m_bUsedMalloc = false;
138
	m_sData = NULL;
139
	Reset ();
130 cycrow 140
	setFilename(filename);
1 cycrow 141
}
142
 
143
C_File::~C_File()
144
{
145
	DeleteData ();
146
	if ( !m_sTmpFile.Empty() )
147
		remove ( m_sTmpFile.c_str() );
148
}
149
 
150
 
151
/*
152
	Func:	GetDirectory()
153
	Return: Directory String
154
	Desc:	Returns the directory the file goes into, based on m_sDir and Filetype
155
*/
156
CyString C_File::GetDirectory ( CBaseFile *file )
157
{
130 cycrow 158
	return getDirectory(file);
1 cycrow 159
}
160
 
121 cycrow 161
Utils::String C_File::getDirectory(CBaseFile *file) const
162
{
163
	if (IsFakePatch())
164
		return "";
165
 
131 cycrow 166
	Utils::String sDir = _sDir;
121 cycrow 167
 
168
	if ((m_iFileType == FILETYPE_MOD) && (sDir == "Patch"))
169
		return "PluginManager/Patch";
170
 
171
	if ((!sDir.empty()) && (m_iFileType != FILETYPE_README) && sDir != ".")
172
	{
173
		Utils::String dir = sDir.findReplace("\\", "/");
174
		if (file)
175
		{
134 cycrow 176
			dir = dir.findReplace("$scriptname", file->getNameValidFile());
121 cycrow 177
			dir = dir.findReplace("$scriptauthor", file->author());
178
		}
179
		return dir;
180
	}
181
 
130 cycrow 182
	return C_File::GetDirectory(m_iFileType, _sName, file);
121 cycrow 183
}
184
 
128 cycrow 185
CyString C_File::GetNameDirectory(CBaseFile *file)
1 cycrow 186
{
130 cycrow 187
	return getNameDirectory(file);
1 cycrow 188
}
189
 
128 cycrow 190
Utils::String C_File::getNameDirectory(CBaseFile *file) const
191
{
192
	Utils::String dir = getDirectory(file);
193
	if (!dir.empty())
194
		dir += "/";
130 cycrow 195
	return (dir + _sName).findReplace("\\", "/").findReplace("//", "/");
128 cycrow 196
}
197
 
1 cycrow 198
/*
199
	Func:	Reset()
200
	Desc:	Resets the file data, clears all data inside
201
			Clears the Data stream
202
*/
203
void C_File::Reset ()
204
{
205
	m_iLastError = SPKERR_NONE;
206
	m_bLoaded = false;
127 cycrow 207
	m_iFileType = FILETYPE_UNKNOWN;
1 cycrow 208
	m_lSize = 0;
209
	m_iVersion = 0;
210
	m_bSigned = false;
211
	m_iUsed = 0;
212
	m_tTime = 0;
213
	m_lDataSize = m_lUncomprDataSize = 0;
214
	DeleteData ();
215
	m_iDataCompression = 0;
216
	m_bSkip = false;
217
	m_bShared = false;
218
	m_bCompressedToFile = false;
219
	m_bDisabled = false;
220
	m_bUpdatedSignature = false;
221
	m_iPos = -1;
127 cycrow 222
	_iGame = 0;
1 cycrow 223
}
224
 
225
bool C_File::UpdateSigned()
226
{
227
	switch ( m_iFileType )
228
	{
229
		// text files, readmes, screenshots can be always considered to be signed
230
		case FILETYPE_TEXT:
231
		case FILETYPE_README:
232
		case FILETYPE_SCREEN:
233
		case FILETYPE_ADVERT:
234
		case FILETYPE_SOUND:
235
		case FILETYPE_BACKUP:
236
			m_bSigned = true;
237
			break;
238
 
239
		// mods, maps are always not signed
240
		case FILETYPE_MOD:
241
		case FILETYPE_MAP:
242
		case FILETYPE_SHIPOTHER:
243
		case FILETYPE_SHIPMODEL:
244
		case FILETYPE_SHIPSCENE:
245
		case FILETYPE_COCKPITSCENE:
246
			m_bSigned = false;
247
			break;
248
 
249
		// extra files are a special case
250
		case FILETYPE_EXTRA:
251
			if ( this->GetDir().Left(6).Compare("extras") )
252
				m_bSigned = true;
253
			else
254
				m_bSigned = false;
255
			break;
256
 
257
		// script files need to check
258
		case FILETYPE_SCRIPT:
259
		case FILETYPE_UNINSTALL:
260
			m_bSigned = this->ReadSignedFile();
261
			break;
262
 
263
		// mission files
264
		case FILETYPE_MISSION:
265
			m_bSigned = false;
266
			break;
267
	}
268
 
269
	return m_bSigned;
270
}
271
 
272
/*
273
	Func:	DeleteData()
274
	Desc:	Clears the data stream, uses free() if created by malloc, otherwise use delete.
275
*/
276
void C_File::DeleteData ()
277
{
278
	if ( m_sData )
279
	{
280
		if ( m_bUsedMalloc )
281
			free ( m_sData );
282
		else
283
			delete [] m_sData;
284
		m_bDontDeleteData = false;
285
		m_sData = NULL;
286
		m_bLoaded = false;
287
		m_lDataSize = 0;
288
	}
289
	m_bUsedMalloc = false;
290
	m_iDataCompression = SPKCOMPRESS_NONE;
291
}
292
 
293
int C_File::GetTextFileID(CyString filename)
294
{
295
	if ( m_iFileType != FILETYPE_TEXT )
296
		return -1;
297
 
298
	if ( filename.Empty() )
130 cycrow 299
		filename = _sName;
1 cycrow 300
 
301
	CyString textid;
302
	if ( filename.IsIn("-L") || filename.IsIn("-l") )
303
		textid = filename.GetToken("-", 1, 1);
304
	else
305
		textid = filename.GetToken(".", -1).Right(4);
306
 
43 cycrow 307
	if ( textid.IsNumber() ) return textid.ToInt();
308
	return -1;
1 cycrow 309
}
130 cycrow 310
bool C_File::isAutoTextFile ()
1 cycrow 311
{
312
	int textid = GetTextFileID();
313
	if ( textid == -1 ) return false;
314
 
315
	if ( textid <= 3 )
316
		return true;
317
 
318
	// check for original name
127 cycrow 319
	if ( !_sOriginalName.empty() )
1 cycrow 320
	{
127 cycrow 321
		textid = GetTextFileID(_sOriginalName);
1 cycrow 322
		if ( textid >= 0 && textid <= 3 )
323
			return true;
324
	}
325
 
326
	return false;
327
}
328
 
126 cycrow 329
bool C_File::isFileInAddon() const
330
{
331
	switch (m_iFileType)
332
	{
333
		case FILETYPE_SHIPMODEL:
334
		case FILETYPE_SHIPOTHER:
335
		case FILETYPE_SHIPSCENE:
336
		case FILETYPE_COCKPITSCENE:
337
		case FILETYPE_SOUND:
338
			return false;
339
	}
340
 
341
	return true;
342
}
343
 
121 cycrow 344
bool C_File::IsFakePatch() const
1 cycrow 345
{
121 cycrow 346
	if (m_iFileType != FILETYPE_MOD)
1 cycrow 347
		return false;
348
 
130 cycrow 349
	Utils::String name = _sName;
121 cycrow 350
 
351
	if (name.token(".", 1).toLong())
1 cycrow 352
		return true;
353
 
121 cycrow 354
	if (name.left(10) == "FakePatch_")
1 cycrow 355
		return true;
356
 
357
	return false;
358
}
359
 
360
/*
361
########################################################################################################################
362
####################################             File Pointer Functions             ####################################
363
########################################################################################################################
364
*/
365
 
366
/*
367
	Func:	SetFilename
368
	Accept:	filename - String for the filename of disk
369
	Desc:	Sets the file pointer
370
			Reads the file size and last modifed time to store in the class
371
			Splits up the filename and dir path
372
*/
129 cycrow 373
void C_File::SetFilename(CyString filename)
1 cycrow 374
{
129 cycrow 375
	setFilename(filename.ToString());
376
}
377
void C_File::setFilename(const Utils::String &filename)
378
{
379
	Utils::String file = filename.findReplace ( "\\", "/" ).findReplace ( "//", "/" );
1 cycrow 380
 
129 cycrow 381
	_sFullDir = file.tokens("/", 1, -2);
130 cycrow 382
	_sName = file.token("/", -1);
129 cycrow 383
	if ( _sFullDir.right(2) == "/." )
384
		_sFullDir = _sFullDir.left(-2);
1 cycrow 385
 
386
	ReadFileSize ();
387
 
388
	ReadLastModified ();
389
}
390
 
391
 
392
/*
393
	Func:	ReadFromFile
394
	Return:	Boolean - Returns true if read was successfull
395
	Desc:	Reads data from file pointer into data stream
396
			As its read from a file, there will be no compression, so its set to None
397
*/
398
bool C_File::ReadFromFile ()
399
{
129 cycrow 400
	return this->readFromFile(filePointer());
1 cycrow 401
}
402
 
129 cycrow 403
bool C_File::ReadFromFile(CyString filename)
1 cycrow 404
{
129 cycrow 405
	return readFromFile(filename.ToString());
406
}
407
bool C_File::readFromFile(const Utils::String filename)
408
{
52 cycrow 409
	CFileIO File(filename);
410
	if ( !File.startRead() ) {
1 cycrow 411
		m_iLastError = SPKERR_FILEOPEN;
412
		return false;
413
	}
414
 
415
	m_iDataCompression = SPKCOMPRESS_NONE;
416
	m_lDataSize = m_lUncomprDataSize = m_lSize;
417
 
418
	DeleteData ();
419
 
52 cycrow 420
	m_sData = File.readAll((size_t *)&m_lSize);
421
	if ( !m_sData ) { 
422
		m_iLastError = SPKERR_MALLOC; 
1 cycrow 423
		m_lDataSize = 0;
52 cycrow 424
		return false; 
1 cycrow 425
	}
426
 
52 cycrow 427
	m_lDataSize = m_lSize;
428
	m_tTime = File.modifiedTime();
429
 
1 cycrow 430
	m_iLastError = SPKERR_NONE;
431
 
432
	m_bLoaded = true;
433
 
52 cycrow 434
	File.close();
1 cycrow 435
	return true;
436
}
437
 
438
/*
439
	Func:	ReadFromData
440
	Accept:	data - The data stream to read
441
			size - The length of the data stream
442
	Return: Boolean - Return true if successfull
443
	Desc:	Copys data to the data stream in the file
444
			Used when data is already loaded into memory
445
*/
446
bool C_File::ReadFromData ( char *data, long size )
447
{
448
	DeleteData ();
449
 
450
	m_lDataSize = size ;
451
	m_sData = new unsigned char[m_lDataSize];
452
 
453
	memcpy ( m_sData, data, size );
454
 
455
	return true;
456
}
457
 
458
 
58 cycrow 459
bool C_File::readFromFile(CFileIO &File)
52 cycrow 460
{
58 cycrow 461
	return readFromFile(File, File.fileSize(), false);
52 cycrow 462
}
58 cycrow 463
 
464
bool C_File::readFromFile(CFileIO &File, int iSize, bool bDoSize)
51 cycrow 465
{
58 cycrow 466
	if ( !File.isOpened() ) File.startRead();
467
	if ( !File.isOpened() ) return false;
468
 
61 cycrow 469
	m_lDataSize = iSize;
51 cycrow 470
	try {
471
		m_sData = new unsigned char[m_lDataSize];
472
	}
473
	catch(std::exception &e) {
61 cycrow 474
		CLog::logf(CLog::Log_IO, 2, "C_File::readFromFile() unable to malloc, %d (%s)", m_lDataSize, e.what());
51 cycrow 475
		return false;
476
	}
477
 
58 cycrow 478
	if ( bDoSize ) File.readSize();
51 cycrow 479
 
480
	try { 
58 cycrow 481
		File.read(m_sData, m_lDataSize); 
51 cycrow 482
	}
483
	catch(std::exception &e) {
61 cycrow 484
		CLog::logf(CLog::Log_IO, 2, "C_File::readFromFile() unable to read from file, %d (%s)", m_lDataSize, e.what());
51 cycrow 485
		DeleteData ();
486
		m_lDataSize = 0;
487
		return false;
488
	}
489
	return true;
490
}
491
 
43 cycrow 492
void C_File::copyData(const unsigned char *data, size_t size)
493
{
494
	m_lDataSize = (long)size;
495
	delete m_sData;
496
	m_sData = new unsigned char[size];
497
	memcpy(m_sData, data, size);
498
}
1 cycrow 499
 
43 cycrow 500
 
88 cycrow 501
Utils::String C_File::filePointer() const
502
{
129 cycrow 503
	Utils::String fullfile = _sFullDir;
88 cycrow 504
	if ( !fullfile.empty() )
505
		fullfile += "/";
506
 
130 cycrow 507
	if ( !_sName.empty() )
508
		fullfile += _sName;
88 cycrow 509
 
510
	return fullfile;
511
}
127 cycrow 512
 
513
bool C_File::isExternalFile() const
514
{
515
	if (!m_sData && !m_lDataSize)
516
	{
517
		Utils::String file = this->filePointer();
518
		if (!file.empty() && CFileIO::Exists(file))
519
			return true;
520
	}
521
	return false;
522
}
523
 
1 cycrow 524
/*
525
	Func:	GetFilePointer
526
	Desc:	Returns the file pointer name
527
			Joins dir and name together
528
			Works for relative paths as well
529
*/
530
CyString C_File::GetFilePointer ()
531
{
88 cycrow 532
	return filePointer();
1 cycrow 533
}
534
 
535
 
536
void C_File::UpdateSignature()
537
{
538
	m_sSignature = "";
539
 
540
	bool deleteData = false;
541
	if ( !m_sData )
542
	{
543
		if ( !ReadFromFile() )
544
			return;
545
		deleteData = true;
546
	}
547
 
548
	if ( CheckPCK() )
549
		UnPCKFile();
550
 
551
	m_bUpdatedSignature = true;
552
 
553
	if ( !m_sData )
554
		return;
555
 
556
	size_t fPos = m_lDataSize;
557
	if ( fPos > 700 )
558
		fPos = 700;
559
	unsigned char *data = m_sData + (m_lDataSize - fPos);
560
	data[fPos - 1] = '\0';
561
	CyString sData ((char *)data);
562
	int pos = sData.FindPos("</codearray>", 0);
563
	if ( pos != -1 )
564
	{
565
		sData = sData.Right(sData.Length() - pos);
566
		pos = sData.FindPos("<signature>", 0);
567
		int endpos = sData.FindPos("</signature>", 0);
568
		if ( pos != -1 && endpos != -1 )
569
		{
570
			m_sSignature = sData.Mid(pos + 12, endpos - (pos + 12) + 1);
571
			m_sSignature = m_sSignature.Remove('\n').Remove('\r');
572
		}
573
	}
574
 
575
	if ( deleteData )
576
		DeleteData();
577
}
578
 
579
 
580
/*
581
	Func:	ReadFileSize()
582
	Return:	Returns the file size read
583
	Desc:	Opens the file and seeks to the end
584
*/
585
long C_File::ReadFileSize ()
586
{
129 cycrow 587
	CFileIO File(filePointer());
52 cycrow 588
	if ( File.exists() ) m_lSize = File.fileSize();
1 cycrow 589
 
590
	m_lUncomprDataSize = m_lSize;
591
 
592
	return m_lSize;
593
}
594
 
595
/*
596
	Func:	ReadLastModifed()
597
	Desc:	Reads the last modified time of the file and returns
598
			Uses seperate rountines for Windows and Linux
599
*/
600
time_t C_File::ReadLastModified ()
601
{
129 cycrow 602
	Utils::String file = filePointer();
603
	if ( file.empty() )
1 cycrow 604
		return m_tTime;
605
 
606
	#ifndef _WIN32
607
	struct stat attrib;			// create a file attribute structure
608
    stat ( file.c_str(), &attrib);
609
	m_tTime = attrib.st_mtime;
610
	#else
611
	#endif
612
 
613
	return m_tTime;
614
}
615
 
616
bool C_File::CheckValidFilePointer ()
617
{
129 cycrow 618
	return CFileIO::Exists(filePointer());
1 cycrow 619
}
620
 
621
bool C_File::ReadSignedFile()
622
{
623
	if ( (m_iFileType != FILETYPE_SCRIPT) && (m_iFileType != FILETYPE_UNINSTALL) )
624
		return false;
625
 
626
	// check file pointer
129 cycrow 627
	Utils::String file = filePointer();
628
	Utils::String ext = CFileIO(file).extension();
1 cycrow 629
	if ( !ext.Compare("xml") && !ext.Compare("pck") )
630
		return false;
631
 
632
	if ( m_iDataCompression != SPKCOMPRESS_NONE )
633
		return m_bSigned;
634
 
635
	// check file extenstion
636
	if ( (ext.Compare("pck")) || (CheckPCK()) )
637
	{
638
		size_t size = 0;
639
		unsigned char *data = UnPCKFile ( &size );
53 cycrow 640
		if ( (data) && (size) ) {
641
			bool ret = ::ReadSignedFromData ( data, (long)size );
642
			//delete data;
643
			return ret;
644
		}
1 cycrow 645
	}
646
	else if ( (m_sData) && (m_iDataCompression == SPKCOMPRESS_NONE) )
647
		return ::ReadSignedFromData ( m_sData, m_lDataSize );
648
	else
649
	{
53 cycrow 650
		unsigned char pData[5001];
1 cycrow 651
 
53 cycrow 652
		CFileIO File(file);
653
		int iAmount = (File.fileSize() > 5000) ? 5000 : File.fileSize();
654
		if ( File.startRead() ) {
655
			File.seekStart(File.fileSize() - iAmount);
656
			if ( File.read(pData, iAmount, true) ) {
657
				return ::ReadSignedFromData(pData, iAmount);
1 cycrow 658
			}
659
		}
660
	}
661
 
662
	return false;
663
}
664
 
665
int C_File::ReadScriptVersion ()
666
{
54 cycrow 667
	if ( (m_iFileType != FILETYPE_SCRIPT) && (m_iFileType != FILETYPE_UNINSTALL) ) return 0;
1 cycrow 668
 
54 cycrow 669
	if ( (m_sData) && (m_iDataCompression == SPKCOMPRESS_NONE) )
1 cycrow 670
		m_iVersion = ::ReadScriptVersionFromData ( m_sData, m_lDataSize );
54 cycrow 671
	else {
129 cycrow 672
		CFileIO File(filePointer());
54 cycrow 673
		if ( File.startRead() ) {
674
			int iRead = (File.fileSize() > 5000) ? 5000 : File.fileSize();
675
			unsigned char *data = File.read(iRead);
676
			if ( data ) {
677
				m_iVersion = ::ReadScriptVersionFromData(data, iRead);
678
				delete []data;
1 cycrow 679
			}
680
		}
681
	}
682
 
683
	return m_iVersion;
684
}
685
 
686
bool C_File::MatchFile ( C_File *file )
687
{
688
	if ( file->GetFileType() != m_iFileType )
689
		return false;
690
 
131 cycrow 691
	if ( file->dir() != _sDir )
1 cycrow 692
		return false;
693
 
130 cycrow 694
	if ( file->name() != _sName )
125 cycrow 695
	{
696
		// check if the base name matches, but only for certain file extensions
697
		if (file->shouldCheckBaseName())
698
		{
699
			Utils::String baseName = CFileIO(file->GetName()).dir() + "/" + CFileIO(file->GetName()).baseName();
130 cycrow 700
			Utils::String compareBaseName = CFileIO(_sName).dir() + "/" + CFileIO(_sName).baseName();
125 cycrow 701
			if (baseName.Compare(compareBaseName))
702
				return true;
703
		}
704
		return false;
116 cycrow 705
	}
1 cycrow 706
 
707
	return true;
708
}
709
 
710
/*
711
########################################################################################################################
712
####################################              Compression Functions             ####################################
713
########################################################################################################################
714
*/
715
 
716
bool C_File::CompressFile ( CProgressInfo *progress )
717
{
129 cycrow 718
	Utils::String file = this->filePointer();
719
	if ( !CFileIO(this->filePointer()).exists() )
1 cycrow 720
	{
129 cycrow 721
		if ( !this->writeToFile("tempuncompr.dat", m_sData, m_lDataSize) )
1 cycrow 722
			return false;
723
		file = "tempuncompr.dat";
724
	}
725
 
726
	bool ret = false;
727
 
728
	FILE *fIn = fopen(file.c_str(), "rb");
729
	if ( fIn )
730
	{
731
		FILE *fOut = fopen("tempcompr.dat", "wb");
732
		if ( fOut )
733
		{
734
			int err;
735
			if ( progress )
736
				err = zlib_def(fIn, fOut, progress->GetDonePointer());
737
			else
738
				err = zlib_def(fIn, fOut, 0);
739
 
740
			fclose(fOut);
741
			if ( err == Z_OK )
742
			{
743
				DeleteData ();
744
 
54 cycrow 745
				CFileIO File("tempcompr.dat");
746
				File.setAutoDelete(true);
747
				if ( File.startRead() ) {
748
					m_sData = File.readAll((size_t *)&m_lDataSize);
749
					if ( !m_sData ) {
750
						m_iLastError = SPKERR_FILEREAD;
751
						m_lDataSize = 0;
1 cycrow 752
					}
54 cycrow 753
					else {
754
						m_iLastError = SPKERR_NONE;
755
						m_iDataCompression = SPKCOMPRESS_ZLIB;
756
						ret = true;
757
					}
1 cycrow 758
				}
54 cycrow 759
				File.close();
1 cycrow 760
			}
761
		}
762
		fclose(fIn);
763
	}
764
 
52 cycrow 765
	CFileIO::Remove("tempuncompr.dat");
1 cycrow 766
 
767
	return ret;
768
}
769
 
770
bool C_File::ChangeCompression ( int compressionType, CProgressInfo *progress )
771
{
772
	// no data to try to compress
773
	if ( (!m_sData) || (!m_lDataSize) )
774
		return false;
775
 
776
	// laready compressed to correct type
777
	if ( compressionType == m_iDataCompression )
778
		return true;
779
 
780
	// otherwise, lets recompress the file
781
	// first we uncompress the data
782
	if ( !this->UncompressData(progress) )
783
		return false;
784
 
785
	// next we compress to new type
786
	if ( !this->CompressData(compressionType, progress) )
787
		return false;
788
	return true;
789
}
790
 
791
unsigned char *C_File::CompressToData(int compressionType, unsigned long *outSize, CProgressInfo *progress, int level)
792
{
793
	unsigned long comprLen = m_lDataSize;
794
	if ( comprLen < 100 )		comprLen = 200;
795
	else if ( comprLen < 1000 )	comprLen *= 2;
796
	comprLen += 1000;
797
 
798
	switch(compressionType)
799
	{
800
		case SPKCOMPRESS_ZLIB:
801
			{
802
				unsigned char *compr = (unsigned char *)calloc(comprLen, 1);
803
				int err = Z_NOTENOUGH_BUF;
804
				while ( err == Z_NOTENOUGH_BUF )
805
				{
806
					err = compress2 ( compr, &comprLen, (const unsigned char *)m_sData, m_lDataSize, (progress) ? progress->GetDonePointer() : 0, level );
807
					if ( err == Z_NOTENOUGH_BUF )
808
					{
809
						comprLen += (CHUNK * 2);
810
						compr = (unsigned char *)realloc(compr, comprLen);
811
					}
812
					else
813
						break;
814
				}	
815
 
816
				// if its compressed ok, remove old data and use new one
817
				if ( err == Z_OK )
818
				{
819
					unsigned char *retData = new unsigned char[comprLen];
820
					(*outSize) = comprLen;
821
					memcpy(retData, compr, comprLen);
822
					free(compr);
823
					return retData;
824
				}
825
 
826
				free(compr);
827
				return NULL;
828
			}
829
			break;
830
 
831
		case SPKCOMPRESS_LZMA:
832
			{
833
				unsigned char *compr = (unsigned char *)malloc(comprLen);
834
				SRes res = Lzma86_Encode((Byte *)compr, (size_t *)&comprLen, (const Byte *)m_sData, (size_t)m_lDataSize, level, LZMA_DICT, SZ_FILTER_NO, (progress) ? progress->GetDonePointer() : NULL);
835
 
836
				if ( res == SZ_OK )
837
				{
838
					unsigned char *retData = new unsigned char[comprLen];
839
					(*outSize) = comprLen;
840
					memcpy(retData, compr, comprLen);
841
					free(compr);
842
					return retData;
843
				}
844
 
845
				free(compr);
846
				return NULL;
847
			}
848
			break;
849
	}
850
 
851
	return NULL;
852
}
853
 
854
bool C_File::CompressData ( int compressionType, CProgressInfo *progress, int level )
855
{
856
	// no data to try to compress
857
	if ( (!m_sData) || (!m_lDataSize) )
858
		return false;
859
 
860
	// if comopression is set to noe, dont bother
861
	if ( compressionType == SPKCOMPRESS_NONE )
862
		return true;
863
 
864
	if ( compressionType == SPKCOMPRESS_7ZIP )
865
		compressionType = SPKCOMPRESS_LZMA;
866
 
867
	// if its zlib, and we are trying to compress pcked files (ie already zlib compression) then switch to lzma instead
868
	if ( compressionType == SPKCOMPRESS_ZLIB && (this->CheckFileExt("pck") || this->CheckFileExt("cat") || this->CheckFileExt("dat") || this->CheckFileExt("pbb") || this->CheckFileExt("pbd")) )
869
		compressionType = SPKCOMPRESS_LZMA;
870
 
871
	// if its already compressed, no need to compress again
872
	if ( compressionType == m_iDataCompression )
873
		return true;
874
 
875
	// no need to change the compression
876
	if ( m_iDataCompression != SPKCOMPRESS_NONE )
877
		return true;
878
 
879
	m_lUncomprDataSize = m_lDataSize;
880
 
881
	unsigned long comprLen = m_lDataSize;
882
	if ( comprLen < 100 )
883
		comprLen = 200;
884
	else if ( comprLen < 1000 )
885
		comprLen *= 2;
886
	comprLen += 1000;
887
 
888
	// > 500mb (do file compression
889
	if ( comprLen > 500000000 )
890
		return this->CompressFile(progress);
891
 
892
	// best compression, attempt to compress the file multiple times until we get the best one
893
	if ( compressionType == SPKCOMPRESS_BEST )
894
	{
895
		int compress[] = { SPKCOMPRESS_ZLIB, SPKCOMPRESS_LZMA };
896
		int bestCompress = -1;
897
		unsigned int bestSize = 0;
898
		unsigned char *bestCompr = NULL;
899
		for ( int i = 0; i < 2; i++ )
900
		{
901
			unsigned long checkSize = 0;
902
			unsigned char *compr = this->CompressToData(compress[i], &checkSize, progress, level);
903
			if ( compr )
904
			{
905
				if ( checkSize < bestSize || bestCompress == -1 )
906
				{
907
					if ( bestCompr )
908
						delete bestCompr;
909
					bestCompr = compr;
910
					bestCompress = compress[i];
911
					bestSize = checkSize;
912
				}
913
				// not the best, no need to keep it
914
				else
915
					delete compr;
916
			}
917
		}
918
 
919
		if ( bestCompress != -1 && bestCompr )
920
		{
921
			DeleteData ();
922
			m_sData = bestCompr;
923
			m_bUsedMalloc = false;
924
			m_lDataSize = bestSize;
925
			m_iDataCompression = bestCompress;
926
			return true;
927
		}
928
 
929
		if ( bestCompr )
930
			delete bestCompr;
931
	}
932
 
933
	if ( compressionType == SPKCOMPRESS_ZLIB || compressionType == SPKCOMPRESS_LZMA )
934
	{
935
		unsigned char *compr = this->CompressToData(compressionType, &comprLen, progress, level);
936
		if ( compr )
937
		{
938
			DeleteData ();
939
			m_sData = compr;
940
			m_bUsedMalloc = false;
941
			m_lDataSize = comprLen;
942
			m_iDataCompression = compressionType;
943
		}
944
		// we shall always return true, files can be added in non compressed mode
945
		return true;
946
	}
947
 
948
	return false;
949
}
950
 
951
bool C_File::UncompressData ( CProgressInfo *progress )
952
{
953
	// no data to try to uncompress
45 cycrow 954
	if ( (!m_sData) || (!m_lDataSize) ) {
955
		return (m_lSize) ? false : true;
956
	}
1 cycrow 957
 
958
	if ( m_bCompressedToFile )
959
		return false;
960
 
961
	// if comopression is set to none, dont bother
962
	if ( m_iDataCompression == SPKCOMPRESS_NONE )
963
		return true;
964
 
965
	if ( m_iDataCompression == SPKCOMPRESS_ZLIB )
966
	{
967
		unsigned long uncomprLen = m_lUncomprDataSize;
968
		unsigned char *uncompr = new unsigned char[m_lUncomprDataSize];
969
		int err = uncompress ( uncompr, &uncomprLen, (const unsigned char *)m_sData, m_lDataSize );
970
		if ( err == Z_OK )
971
		{
972
			DeleteData ();
973
			m_iDataCompression = SPKCOMPRESS_NONE;
974
			m_lDataSize = uncomprLen;
975
			m_sData = uncompr;
976
			return true;
977
		}
978
 
979
		if ( uncompr )
980
			delete [] uncompr;
981
	}
982
	else if ( m_iDataCompression == SPKCOMPRESS_LZMA )
983
	{
984
		size_t uncomprLen = m_lUncomprDataSize;
985
		unsigned char *uncompr = new unsigned char[m_lUncomprDataSize];
986
		SRes res = Lzma86_Decode(uncompr, &uncomprLen, m_sData, (size_t*)&m_lDataSize);
987
		if ( res == SZ_OK )
988
		{
989
			DeleteData ();
990
			m_iDataCompression = SPKCOMPRESS_NONE;
991
			m_lDataSize = (long)uncomprLen;
992
			m_sData = new unsigned char[m_lDataSize];
993
			memcpy(m_sData, uncompr, m_lDataSize);
994
			delete uncompr;
995
			return true;
996
		}
997
 
998
		if ( uncompr )
999
			delete [] uncompr;
1000
	}
1001
	else if ( m_iDataCompression == SPKCOMPRESS_7ZIP )
1002
	{
1003
		long len = m_lUncomprDataSize;
1004
		unsigned char *compr = LZMADecode_C ( (unsigned char *)m_sData, m_lDataSize, (size_t*)&len, NULL );
1005
		if ( compr )
1006
		{
1007
			DeleteData ();
1008
			m_sData = compr;
1009
			m_lDataSize = len;
1010
			m_iDataCompression = SPKCOMPRESS_NONE;
1011
			return true;
1012
		}
1013
	}
1014
 
1015
	return false;
1016
}
1017
 
1018
unsigned char *C_File::UncompressData ( long *size, CProgressInfo *progress )
1019
{
1020
	// no data to try to uncompress
1021
	if ( (!m_sData) || (!m_lDataSize) )
1022
		return NULL;
1023
 
1024
	//if ( m_bCompressedToFile )
1025
	//	return NULL;
1026
 
1027
	// if comopression is set to none, dont bother
1028
	if ( m_iDataCompression == SPKCOMPRESS_NONE )
1029
	{
1030
		*size = m_lDataSize;
143 cycrow 1031
		unsigned char *uncompr = new unsigned char[m_lDataSize];
1032
		memcpy(uncompr, m_sData, m_lDataSize);
1033
		return uncompr;
1 cycrow 1034
	}
1035
 
1036
	if ( m_iDataCompression == SPKCOMPRESS_ZLIB )
1037
	{
1038
		unsigned long uncomprLen = m_lUncomprDataSize;
1039
		unsigned char *uncompr = new unsigned char[m_lUncomprDataSize];
1040
		int err = uncompress ( uncompr, &uncomprLen, (const unsigned char *)m_sData, m_lDataSize );
1041
		if ( err == Z_OK )
1042
		{
1043
			*size = uncomprLen;
1044
			return uncompr;
1045
		}
1046
		if ( uncompr )
1047
			delete [] uncompr;
1048
	}
1049
	if ( m_iDataCompression == SPKCOMPRESS_7ZIP )
1050
	{
1051
		long len = m_lUncomprDataSize;
1052
		unsigned char *compr = LZMADecode_C ( m_sData, m_lDataSize, (size_t *)&len, NULL );
1053
		if ( compr )
1054
		{
1055
			*size = len;
1056
			return compr;
1057
		}
1058
		if ( compr )
1059
			delete [] compr;
1060
	}
1061
	else if ( m_iDataCompression == SPKCOMPRESS_LZMA )
1062
	{
1063
		size_t uncomprLen = m_lUncomprDataSize;
1064
		unsigned char *uncompr = new unsigned char[m_lUncomprDataSize];
1065
		SRes res = Lzma86_Decode(uncompr, &uncomprLen, m_sData, (size_t*)&m_lDataSize);
1066
		if ( res == SZ_OK )
1067
		{
1068
			*size = (long)uncomprLen;
1069
			return uncompr;
1070
		}
1071
		if ( uncompr )
1072
			delete [] uncompr;
1073
	}
1074
 
1075
	return NULL;
1076
}
1077
 
1078
bool C_File::UncompressToFile ( CyString toFile, CBaseFile *spkfile, bool includedir, CProgressInfo *progress )
1079
{
1080
#ifdef _INCLUDE7ZIP
1081
	if ( (!m_sData) || (!m_lDataSize) )
1082
		return false;
1083
	// if theres a tmp file, open it and check it still exists
1084
	if ( !m_sTmpFile.Empty() )
1085
	{
56 cycrow 1086
		if ( CFileIO::Exists(m_sTmpFile) ) return true;
1 cycrow 1087
		m_sTmpFile = "";
1088
	}
1089
 
1090
	// now uncompress to the file
1091
	CyString file = toFile;
1092
	if ( file.Empty() )
1093
	{
1094
		m_iTempNum++;
1095
		file = CyString("uncompr") + (long)m_iTempNum + ".tmp";
1096
	}
1097
	else
129 cycrow 1098
		file = _getFullFileToDir(file.ToString(), includedir, spkfile);
1 cycrow 1099
 
56 cycrow 1100
	CFileIO File("compr.tmp");
1101
	if ( !File.startWrite() ) return false;
1102
	if ( !File.write(m_sData, m_lDataSize) ) return false;
1103
	File.close();
1104
	if ( LZMADecodeFile ( "compr.tmp", file.c_str(), (CProgressInfo7Zip *)progress ) )
1 cycrow 1105
	{
56 cycrow 1106
		ret = true;
1107
		if ( toFile.Empty() )
1108
			m_sTmpFile = file;
1 cycrow 1109
	}
1110
 
56 cycrow 1111
	CFileIO::Remove("compr.tmp");
1 cycrow 1112
 
1113
	return ret;
1114
#else
1115
	return false;
1116
#endif
1117
}
1118
 
1119
 
129 cycrow 1120
bool C_File::writeFilePointer(unsigned char *cData, long len)
1 cycrow 1121
{
129 cycrow 1122
	return writeToFile(filePointer(), cData, len);
1 cycrow 1123
}
129 cycrow 1124
bool C_File::writeToFile(const Utils::String &filename, unsigned char *cData, long len)
1 cycrow 1125
{
1126
	unsigned char *data = cData;
54 cycrow 1127
	if ( (!len) || (!data) ) {
1 cycrow 1128
		len = m_lDataSize;
1129
		data = m_sData;
1130
	}
1131
 
45 cycrow 1132
	if ( (!len) || (!data) ) {
1133
		if ( m_lSize ) return false;
1134
	}
1 cycrow 1135
 
54 cycrow 1136
	bool ret = false;
1137
 
1 cycrow 1138
	// check for cat file
129 cycrow 1139
	if ( filename.contains("::")) {
1140
		Utils::String catfile = filename.token("::", 1);
1141
		Utils::String file = filename.token( "::", 2);
1 cycrow 1142
 
1143
		CCatFile newcat;
1144
		return newcat.AddData ( catfile, data, len, file, true, true );
1145
	}
54 cycrow 1146
	else {
129 cycrow 1147
		Utils::String filen = filename.findReplace ( "/", "\\" );
54 cycrow 1148
		filen = filen.findReplace ( "\\\\", "\\" );
1 cycrow 1149
 
45 cycrow 1150
		if ( len && data ) {
54 cycrow 1151
			CFileIO File(filen);
1152
			if ( File.startWrite() ) ret = File.write(data, len);
45 cycrow 1153
		}
1 cycrow 1154
	}
1155
 
54 cycrow 1156
	return ret;
1 cycrow 1157
}
1158
 
129 cycrow 1159
bool C_File::writeToDir(const Utils::String &dir, CBaseFile *spkfile, bool includedir, const Utils::String &appendDir, unsigned char *data, long len)
1 cycrow 1160
{
129 cycrow 1161
	Utils::String fullfile = _getFullFileToDir(dir, includedir, spkfile);
1 cycrow 1162
 
129 cycrow 1163
	if (!appendDir.empty())
1 cycrow 1164
	{
129 cycrow 1165
		if (!fullfile.empty())
1 cycrow 1166
			fullfile += "/";
1167
		fullfile += appendDir;
1168
	}
1169
 
129 cycrow 1170
	Utils::String fulldir = fullfile.tokens("/", 1, -2);
1171
	if (!fulldir.empty())
1 cycrow 1172
	{
129 cycrow 1173
		if (!CDirIO(fulldir).Create())
1 cycrow 1174
			return false;
1175
	}
1176
 
129 cycrow 1177
	return writeToFile(fullfile, data, len);
1 cycrow 1178
}
1179
 
134 cycrow 1180
Utils::String C_File::dataSizeString() const
1 cycrow 1181
{
134 cycrow 1182
	return SPK::GetSizeString(m_lDataSize);
1 cycrow 1183
}
1184
CyString C_File::GetUncompressedSizeString ()
1185
{
1186
	return SPK::GetSizeString ( GetUncompressedDataSize() );
1187
}
1188
 
1189
CyString C_File::GetCreationTimeString ()
1190
{
1191
	if ( !m_tTime )
1192
		return NullString;
1193
 
1194
	struct tm   *currDate;
1195
	char    dateString[100];
1196
 
1197
	time_t n = m_tTime;
1198
 
1199
	currDate = localtime(&n);
1200
 
1201
	strftime(dateString, sizeof dateString, "(%d/%m/%Y) %H:%M", currDate);
1202
 
1203
 
1204
	return CyString(dateString);
1205
}
1206
 
1207
bool C_File::CompareNew ( C_File *file )
1208
{
1209
	if ( !m_iVersion )
1210
		ReadScriptVersion ();
1211
 
1212
	// if version, check if its later version
1213
	if ( (m_iVersion) && (file->GetVersion()) )
1214
	{
1215
		if ( m_iVersion > file->GetVersion() )
1216
			return false;
1217
	}
1218
 
1219
	// now check for last modified time
1220
	if ( (m_tTime) && (file->GetLastModified()) )
1221
	{
1222
		if ( m_tTime > file->GetLastModified() )
1223
			return false;
1224
	}
1225
 
1226
	// assume same or newer
1227
	return true;
1228
}
1229
 
126 cycrow 1230
Utils::String GetFileTypeString(int type)
1 cycrow 1231
{
1232
	switch ( type )
1233
	{
1234
		case FILETYPE_SCRIPT:
1235
			return "Script";
1236
		case FILETYPE_TEXT:
1237
			return "Text";
1238
		case FILETYPE_README:
1239
			return "Readme";
1240
		case FILETYPE_MAP:
1241
			return "Map";
1242
		case FILETYPE_MOD:
1243
			return "Mod";
1244
		case FILETYPE_UNINSTALL:
1245
			return "Uninstall";
1246
		case FILETYPE_SOUND:
1247
			return "Sound";
1248
		case FILETYPE_EXTRA:
1249
			return "Extra";
1250
		case FILETYPE_SCREEN:
1251
			return "Screen";
1252
		case FILETYPE_ADVERT:
1253
			return "Advert";
1254
		case FILETYPE_MISSION:
1255
			return "Mission";
1256
		case FILETYPE_BACKUP:
1257
			return "Backup";
1258
		case FILETYPE_SHIPOTHER:
1259
			return "ShipOther";
1260
		case FILETYPE_SHIPMODEL:
1261
			return "ShipModel";
1262
		case FILETYPE_SHIPSCENE:
1263
			return "ShipScene";
1264
		case FILETYPE_COCKPITSCENE:
1265
			return "CockpitScene";
1266
	}
1267
 
126 cycrow 1268
	return Utils::String::Null();
1 cycrow 1269
}
1270
 
127 cycrow 1271
FileType GetFileTypeFromString ( CyString type )
1 cycrow 1272
{
1273
	CyString ltype = type.ToLower();
1274
	if ( ltype == "script" )
1275
		return FILETYPE_SCRIPT;
1276
	else if ( ltype == "text" )
1277
		return FILETYPE_TEXT;
1278
	else if ( ltype == "readme" )
1279
		return FILETYPE_README;
1280
	else if ( ltype == "map" )
1281
		return FILETYPE_MAP;
1282
	else if ( ltype == "mod" )
1283
		return FILETYPE_MOD;
1284
	else if ( ltype == "uninstall" )
1285
		return FILETYPE_UNINSTALL;
1286
	else if ( ltype == "sound" )
1287
		return FILETYPE_SOUND;
1288
	else if ( ltype == "extra" )
1289
		return FILETYPE_EXTRA;
1290
	else if ( ltype == "screen" )
1291
		return FILETYPE_SCREEN;
1292
	else if ( ltype == "advert" )
1293
		return FILETYPE_ADVERT;
1294
	else if ( ltype == "mission" )
1295
		return FILETYPE_MISSION;
1296
	else if ( ltype == "backup" )
1297
		return FILETYPE_BACKUP;
1298
	else if ( ltype == "shipother" )
1299
		return FILETYPE_SHIPOTHER;
1300
	else if ( ltype == "shipmodel" )
1301
		return FILETYPE_SHIPMODEL;
1302
	else if ( ltype == "shipscene" )
1303
		return FILETYPE_SHIPSCENE;
1304
	else if ( ltype == "cockpitscene" )
1305
		return FILETYPE_COCKPITSCENE;
1306
 
127 cycrow 1307
	return FILETYPE_UNKNOWN;
1 cycrow 1308
}
1309
 
1310
 
130 cycrow 1311
Utils::String FormatErrorString(int error, const Utils::String &rest)
1 cycrow 1312
{
1313
	int max = 0;
130 cycrow 1314
	Utils::String *args = 0;
1 cycrow 1315
 
130 cycrow 1316
	if ( !rest.empty() )
1317
		args = rest.tokenise("~", &max);
1 cycrow 1318
 
130 cycrow 1319
	Utils::String errorStr;
1 cycrow 1320
	switch ( error )
1321
	{
1322
		case SPKINSTALL_CREATEDIRECTORY:
1323
			errorStr = "Creating Directory: %1";
1324
			break;
1325
		case SPKINSTALL_CREATEDIRECTORY_FAIL:
1326
			errorStr = "Unable to Creating Directory: %1";
1327
			break;
1328
		case SPKINSTALL_WRITEFILE:
1329
			errorStr = "Writing File: %1";
1330
			break;
1331
		case SPKINSTALL_WRITEFILE_FAIL:
1332
			errorStr = "Unable to Write File: %1";
1333
			break;
1334
		case SPKINSTALL_DELETEFILE:
1335
			errorStr = "Deleting File: %1";
1336
			break;
1337
		case SPKINSTALL_DELETEFILE_FAIL:
1338
			errorStr = "Unable to delete File: %1";
1339
			break;
1340
		case SPKINSTALL_REMOVEDIR:
1341
			errorStr = "Removing Directory: %1";
1342
			break;
1343
		case SPKINSTALL_SKIPFILE:
1344
			errorStr = "Skipping File (older): %1";
1345
			break;
1346
		case SPKINSTALL_ENABLEFILE:
1347
			errorStr = "Enabled File: %1";
1348
			break;
1349
		case SPKINSTALL_DISABLEFILE:
1350
			errorStr = "Disabled File: %1";
1351
			break;
1352
		case SPKINSTALL_ENABLEFILE_FAIL:
1353
			errorStr = "Failed to enable File: %1";
1354
			break;
1355
		case SPKINSTALL_DISABLEFILE_FAIL:
1356
			errorStr = "Failed to disable File: %1";
1357
			break;
1358
		case SPKINSTALL_UNINSTALL_MOVE:
1359
			errorStr = "Moving uninstall file: %1";
1360
			break;
1361
		case SPKINSTALL_UNINSTALL_MOVE_FAIL:
1362
			errorStr = "Unable to Move uninstall file: %1";
1363
			break;
1364
		case SPKINSTALL_UNINSTALL_COPY:
1365
			errorStr = "Coping uninstall file: %1";
1366
			break;
1367
		case SPKINSTALL_UNINSTALL_COPY_FAIL:
1368
			errorStr = "Unable to Copy uninstall file: %1";
1369
			break;
1370
		case SPKINSTALL_UNINSTALL_REMOVE:
1371
			errorStr = "Removing Uninstall file: %1";
1372
			break;
1373
		case SPKINSTALL_UNINSTALL_REMOVE_FAIL:
1374
			errorStr = "Unable to remove Uninstall file: %1";
1375
			break;
1376
		case SPKINSTALL_SHARED:
1377
			errorStr = "Removing Unused Shared file: %1";
1378
			break;
1379
		case SPKINSTALL_SHARED_FAIL:
1380
			errorStr = "Unable to remove Unused Shared file: %1";
1381
			break;
1382
		case SPKINSTALL_ORIGINAL_BACKUP:
1383
			errorStr = "Backing up original file: %1";
1384
			break;
1385
		case SPKINSTALL_ORIGINAL_BACKUP_FAIL:
1386
			errorStr = "Unable to back up original file: %1";
1387
			break;
1388
		case SPKINSTALL_ORIGINAL_RESTORE:
1389
			errorStr = "Restoring original file: %1";
1390
			break;
1391
		case SPKINSTALL_ORIGINAL_RESTORE_FAIL:
1392
			errorStr = "Unable to restore original file: %1";
1393
			break;
1394
		case SPKINSTALL_FAKEPATCH:
1395
			errorStr = "Shifted fake patch: %1 to %2";
1396
			break;
1397
		case SPKINSTALL_FAKEPATCH_FAIL:
1398
			errorStr = "Unable to shift fake patch: %1 to %2";
1399
			break;
1400
		case SPKINSTALL_AUTOTEXT:
1401
			errorStr = "Shifted text file: %1 to %2";
1402
			break;
1403
		case SPKINSTALL_AUTOTEXT_FAIL:
1404
			errorStr = "Unable to shift text file: %1 to %2";
1405
			break;
1406
		case SPKINSTALL_MISSINGFILE:
1407
			errorStr = "File is missing: %1";
1408
			break;
1409
		case SPKINSTALL_ORPHANED:
1410
			errorStr = "Orphaned File removed: %1";
1411
			break;
1412
		case SPKINSTALL_ORPHANED_FAIL:
1413
			errorStr = "Unable to remove Orphaned File: %1";
1414
			break;
1415
	}
1416
 
130 cycrow 1417
	Utils::String ret = errorStr.args(args, max);
1 cycrow 1418
	CLEANSPLIT(args, max)
1419
	return ret;
1420
}
1421
 
1422
 
1423
bool C_File::CheckPCK ()
1424
{
1425
	if ( (m_sData) && (m_lDataSize) && (m_iDataCompression == SPKCOMPRESS_NONE) )
1426
		return IsDataPCK ( m_sData, m_lDataSize );
1427
 
129 cycrow 1428
	Utils::String filename = filePointer();
54 cycrow 1429
	if ( !filename.empty() ) {
1430
		CFileIO File(filename);
1431
		if ( File.startRead() ) {
1432
			unsigned char data[4];
1433
			if ( File.read(data, 3) ) return IsDataPCK ( data, 3 );
1 cycrow 1434
		}
1435
	}
1436
 
54 cycrow 1437
	if ( CheckFileExt("pck") || CheckFileExt("pbb") || CheckFileExt("pbd") ) return true;
1 cycrow 1438
	return false;
1439
}
1440
 
1441
bool C_File::PCKFile()
1442
{
1443
	if ( !m_lDataSize || !m_sData )
1444
	{
1445
		if ( !this->ReadFromFile() )
1446
			return false;
1447
	}
1448
 
1449
	if ( m_lDataSize && m_sData )
1450
	{
1451
		if ( !this->UncompressData() )
1452
			return false;
1453
 
1454
		size_t size;
40 cycrow 1455
		unsigned char *data = PCKData(m_sData, m_lDataSize, &size, false);
1 cycrow 1456
		if ( data && size )
1457
		{
40 cycrow 1458
			m_lUncomprDataSize = m_lDataSize;
1 cycrow 1459
			this->DeleteData();
1460
			m_bUsedMalloc = false;
1461
			m_lDataSize = (long)size;
1462
			m_sData = new unsigned char[size];
1463
			memcpy(m_sData, data, size);
1464
			delete [] data;
1465
		}
1466
 
1467
		return true;
1468
	}
1469
 
1470
	return false;
1471
}
1472
 
1473
unsigned char *C_File::UnPCKFile ( size_t *len )
1474
{
1475
	unsigned char *data = NULL;
1476
	size_t datasize = 0;
1477
 
1478
	if ( CheckValidFilePointer() )
1479
	{
129 cycrow 1480
		CFileIO File(filePointer());
54 cycrow 1481
		if ( File.startRead() ) data = File.readAll(&datasize);
1 cycrow 1482
	}
1483
 
1484
	if ( !data )
1485
	{
1486
		if ( !m_lDataSize )
1487
		{
1488
			if ( !this->ReadFromFile() )
1489
				return NULL;
1490
		}
1491
		datasize = m_lDataSize;
1492
		data = new unsigned char[datasize];
1493
		memcpy ( data, m_sData, datasize );
1494
	}
1495
 
1496
	if ( data )
1497
	{
1498
		unsigned char *newdata = UnPCKData ( data, datasize, len, CheckPCK() );
1499
		delete data;
1500
		return newdata;
1501
	}
1502
 
1503
	return NULL;
1504
}
1505
 
1506
bool C_File::UnPCKFile()
1507
{
1508
	if ( !m_lDataSize || !m_sData )
1509
	{
1510
		if ( !this->ReadFromFile() )
1511
			return false;
1512
	}
1513
	if ( m_lDataSize && m_sData )
1514
	{
1515
		if ( !this->UncompressData() )
1516
			return false;
1517
 
1518
		size_t size;
1519
		unsigned char *data = UnPCKData(m_sData, m_lDataSize, &size, CheckPCK());
1520
		if ( data && size )
1521
		{
1522
			this->DeleteData();
1523
			m_lUncomprDataSize = m_lDataSize;
1524
			m_bUsedMalloc = false;
1525
			m_sData = new unsigned char[size];
1526
			memcpy(m_sData, data, size);
1527
			m_lDataSize = (long)size;
1528
			delete []data;
58 cycrow 1529
			return true;
1 cycrow 1530
		}
1531
	}
1532
 
1533
	return false;
1534
}
1535
 
1536
unsigned char *UnPCKFile ( const char *file, size_t *len, bool nocrypt )
1537
{
54 cycrow 1538
	CFileIO File(file);
1539
	if ( !File.startRead() ) return NULL;
1 cycrow 1540
 
54 cycrow 1541
	size_t size;
1542
	unsigned char *data = File.readAll(&size);
1 cycrow 1543
 
54 cycrow 1544
	if ( data ) {
1 cycrow 1545
		unsigned char *unData = UnPCKData ( data, size, len, nocrypt );
1546
		delete data;
1547
		return unData;
1548
	}
1549
 
1550
	return NULL;
1551
}
1552
 
1553
unsigned char *UnPCKData ( unsigned char *data, size_t datasize, size_t *len ) { return UnPCKData(data, datasize, len, IsDataPCK(data, datasize)); }
1554
unsigned char *UnPCKData ( unsigned char *data, size_t datasize, size_t *len, bool nocrypt )
1555
{
96 cycrow 1556
	bool isPCK = IsDataPCK(data, datasize);
1557
 
1558
	unsigned char *newData = data;
1559
	unsigned char *tempData = NULL;
1560
 
1 cycrow 1561
	if ( nocrypt )
1562
	{
96 cycrow 1563
		tempData = new unsigned char[datasize]; 
1564
		newData = tempData;
1565
		memcpy(newData, data, datasize);
1566
		unsigned char magic = newData[0] ^ 0xC8;
1 cycrow 1567
 
1568
		for ( size_t i = 1; i < datasize; i++ )
96 cycrow 1569
			newData[i] ^= magic;
1570
		++newData;
1 cycrow 1571
		--datasize;
1572
	}
1573
 
1574
	// create data buffer
96 cycrow 1575
	size_t *uncomprLenSize = (size_t*)(newData + (datasize - 4));
1 cycrow 1576
	unsigned long uncomprLen = (unsigned long)*uncomprLenSize;
1577
	if ( uncomprLen > (datasize * 100) )
1578
	{
96 cycrow 1579
		if ( tempData ) delete []tempData;
1 cycrow 1580
		*len = 0;
1581
		return NULL;
1582
	}
41 cycrow 1583
	unsigned char *uncompr = new unsigned char[uncomprLen + 1];
96 cycrow 1584
	if ( !uncompr ) {
1585
		if ( tempData ) delete []tempData;
1 cycrow 1586
		return NULL;
96 cycrow 1587
	}
1 cycrow 1588
	memset ( uncompr, 0, sizeof(uncompr) );
1589
 
1590
 
1591
	// find header size
96 cycrow 1592
	unsigned char *buf = newData + PCKHEADERSIZE;
1 cycrow 1593
 
1594
//	buf = data + (6 + sizeof(time_t));
96 cycrow 1595
	char flag = newData[3];
1 cycrow 1596
 
1597
	if ( flag & GZ_FLAG_EXTRA )
1598
	{
1599
		size_t xlen = *((short int*)(buf));
1600
		buf += xlen;
1601
	}
1602
 
1603
	if ( flag & GZ_FLAG_FILENAME )
1604
	{
1605
		char *origname = (char*)(buf);
1606
		buf += strlen (origname) + 1;
1607
	}
1608
	if ( flag & GZ_FLAG_COMMENT )
1609
	{
1610
		char *comment = (char*)(buf);
1611
		buf += strlen(comment) + 1;
1612
	}
1613
	if ( flag & GZ_FLAG_HCRC )
1614
		buf += 2;
96 cycrow 1615
	long bufSize = (long)(datasize - (buf-newData) - 8);
1 cycrow 1616
 
1617
	int err = uncompress2 ( uncompr, &uncomprLen, buf, bufSize );
1618
	if ( err != Z_OK )
1619
	{
96 cycrow 1620
		if ( tempData ) delete []tempData;
1 cycrow 1621
		delete uncompr;
1622
		*len = 0;
1623
		return NULL;
1624
	}
1625
 
1626
	*len = uncomprLen;
41 cycrow 1627
	uncompr[uncomprLen] = '\0';
96 cycrow 1628
	if ( tempData ) delete []tempData;
1 cycrow 1629
	return uncompr;
1630
}
1631
 
1632
bool IsDataPCK ( const unsigned char *data, size_t size )
1633
{
1634
	if ( size >=3 )
1635
	{
1636
		unsigned char magic=data[0] ^ 0xC8;
1637
		return ((data[1] ^ magic)==0x1F && (data[2] ^ magic)==0x8B);
1638
	}
1639
	else
1640
		return false;
1641
 
1642
}
1643
 
1644
bool ReadSignedFromData ( unsigned char *data, long size )
1645
{
53 cycrow 1646
	bool ret = false;
1647
 
1648
	if ( IsDataPCK ( data, size ) ) {
1 cycrow 1649
		size_t unpckSize = 0;
1650
		unsigned char *unpckData = UnPCKData ( data, size, &unpckSize, false );
53 cycrow 1651
		if ( (unpckData) && (unpckSize) ) {
1652
			ret = ReadSignedFromData ( unpckData, (long)unpckSize );
1653
			delete unpckData;
1654
		}
1655
		return ret;
1 cycrow 1656
	}
1657
 
53 cycrow 1658
	char tag[10000];
1659
 
1 cycrow 1660
	// work backwards
1661
	int pos = size - 1;
43 cycrow 1662
	int max = size - 5000;
1663
	if ( max < 0 ) max = 0;
1 cycrow 1664
	// find the first tage
53 cycrow 1665
	while ( pos > max ) {
1666
		while ( data[pos] != '>' && pos > max ) pos--;
1667
		if ( data[pos] != '>' ) break;
1 cycrow 1668
 
53 cycrow 1669
		// now find the front
1670
		int pos2 = pos - 1;
1671
		while ( data[pos2] != '<' && pos2 > max ) pos2--;
1672
		if ( data[pos2] != '<' ) break;
1 cycrow 1673
 
53 cycrow 1674
		memcpy(tag, data + pos2, pos - pos2);
1675
		tag[pos - pos2] = '\0';
1 cycrow 1676
 
53 cycrow 1677
		Utils::String sTag(tag);
1678
		if ( sTag.Compare("</signature") || sTag.Compare("<signature") ) return true;
1679
		if ( sTag.Compare("</codearray") || sTag.Compare("<codearray") ) return false;
1680
		pos = pos2 - 1;
1 cycrow 1681
	}
1682
 
1683
	return false;
1684
}
1685
 
1686
int ReadScriptVersionFromData ( unsigned char *data, long size )
1687
{
54 cycrow 1688
	int iVersion = 0;
1689
 
1 cycrow 1690
	if ( IsDataPCK ( data, size ) )
1691
	{
1692
		size_t unpckSize = 0;
1693
		unsigned char *unpckData = UnPCKData ( data, size, &unpckSize );
54 cycrow 1694
		if ( (unpckData) && (unpckSize) ) {
1695
			iVersion = ReadScriptVersionFromData ( unpckData, (long)unpckSize );
1696
			delete unpckData;
1697
		}
1698
		return iVersion;
1 cycrow 1699
	}
1700
 
54 cycrow 1701
	// only check the beginning of the file
1702
	int iMax = (size > 5000) ? 5000 : size;
1703
 
1 cycrow 1704
	int pos = 0;
1705
	bool found = false;
1706
	// skip past initial space
54 cycrow 1707
	char tag[21];
1708
	while ( pos < iMax )
1 cycrow 1709
	{
54 cycrow 1710
		// skip past whitespace
1711
		while ( (pos < iMax) && (data[pos] == ' ') ) ++pos;
1712
		// find the first '<'
1713
		while ( (pos < iMax) && (data[pos] != '<') ) ++pos;
1714
		if ( data[pos] != '<' ) break; //not found
1 cycrow 1715
 
54 cycrow 1716
		// find end tag '>'
1717
		int iStartPos = pos;
1718
		while ( (pos < iMax) && (data[pos] != '>') ) ++pos;
1719
		if ( data[pos] != '>' ) break; //not found
1720
		if ( (pos - iStartPos) > 20 ) continue;
1 cycrow 1721
 
54 cycrow 1722
		// check if the tag is what we're looking for
1723
		memcpy(tag, data + iStartPos, pos - iStartPos);
1724
		tag[pos - iStartPos] = '\0';
1725
		Utils::String sTag(tag);
1726
		if ( !sTag.Compare("<version") ) continue;
1727
 
1728
		//extract the tag data
1729
		iStartPos = pos + 1;
1730
		while ( (pos < iMax) && (data[pos] != '<') ) ++pos;
1731
		if ( (pos - iStartPos) > 20 ) continue;
1732
		memcpy(tag, data + iStartPos, pos - iStartPos);
1733
		tag[pos - iStartPos] = '\0';
1734
		return atoi(tag);
1 cycrow 1735
	}
1736
 
1737
	return iVersion;
1738
}
1739
 
131 cycrow 1740
Utils::String C_File::baseName() const
1 cycrow 1741
{
1742
	// remove any directory
130 cycrow 1743
	Utils::String file = _sName.token("/", -1);
1 cycrow 1744
 
1745
	// remove file extension
131 cycrow 1746
	return file.remToken(".", -1);
1 cycrow 1747
}
131 cycrow 1748
CyString C_File::GetBaseName()
1749
{
1750
	return baseName();
1751
}
1 cycrow 1752
 
1753
void C_File::CopyData(C_File *oldFile, bool includeData)
1754
{
1755
	SetFilename(oldFile->GetFullFilename());
131 cycrow 1756
	_sDir = oldFile->dir();
1 cycrow 1757
	m_tTime = oldFile->GetCreationTime();
1758
	m_bShared = oldFile->IsShared();
1759
	m_bSigned = oldFile->IsSigned();
127 cycrow 1760
	m_iFileType = oldFile->fileType();
1 cycrow 1761
	m_lSize = oldFile->GetSize();
1762
	if ( includeData )
1763
	{
1764
		m_lDataSize = oldFile->GetDataSize();
1765
		if ( m_sData )
1766
			this->DeleteData();
1767
		m_sData = NULL;
1768
		if ( oldFile->GetData() && m_lDataSize )
1769
		{
1770
			m_sData = new unsigned char[m_lDataSize];
1771
			m_bUsedMalloc = false;
1772
			memcpy((char *)m_sData, (char *)oldFile->GetData(), m_lDataSize);
1773
		}
1774
		m_lUncomprDataSize = oldFile->GetUncompressedDataSize();
1775
	}
1776
	m_iDataCompression = oldFile->GetCompressionType();
1777
}
1778
 
1779
float GetLibraryVersion() { return (float)LIBRARYVERSION; }
1780
float GetFileFormatVersion() { return (float)FILEVERSION; }
1781
 
1782
CyString C_File::ChangeFileExt(CyString ext)
1783
{
130 cycrow 1784
	_sName = CFileIO(_sName).changeFileExtension(ext.ToString());
1785
	return _sName;
1 cycrow 1786
}
1787
 
130 cycrow 1788
Utils::String C_File::fileExt() const 
1789
{ 
1790
	return _sName.token(".", -1); 
1791
}
1792
 
1793
const Utils::String &C_File::changeFileExt(const Utils::String &ext)
1794
{
1795
	_sName = CFileIO(_sName).changeFileExtension(ext);
1796
	return _sName;
1797
}
1798
 
1 cycrow 1799
bool C_File::CheckPackedExtension()
1800
{
1801
	CyString ext = this->GetFileExt();
1802
	if ( ext == "pck" )
1803
		return true;
1804
	else if ( ext == "pbb" )
1805
		return true;
1806
	else if ( ext == "pbd" )
1807
		return true;
1808
 
1809
	return false;
1810
}
1811
 
125 cycrow 1812
bool C_File::shouldCheckBaseName() const
1813
{
130 cycrow 1814
	Utils::String ext = CFileIO(_sName).extension();
125 cycrow 1815
	if (ext == "xml" || ext == "txt" || ext == "pck")
1816
		return true;
1817
	if (ext == "bod" || ext == "bob" || ext == "pbb" || ext == "pbd")
1818
		return true;
1819
	return false;
1820
}
1821
 
127 cycrow 1822
unsigned int C_File::game() const 
1823
{ 
1824
	return _iGame; 
1825
}
125 cycrow 1826
 
129 cycrow 1827
bool C_File::isForGame(int game) const
1828
{
1829
	if (game > 0)
1830
	{
1831
		if (!_iGame || _iGame == GAME_ALLNEW)
1832
			return true;
1833
		return (_iGame & 1 << game) != 0;
1834
	}
1835
 
1836
	return true;
1837
}
1838
 
1839
int C_File::getForSingleGame() const
1840
{
1841
	int checkGame = _iGame & ~GAME_ALLNEW;
1842
	for (int i = 0; i < 31; ++i)
1843
	{
1844
		if (checkGame == (1 << i))
1845
			return i;
1846
	}
1847
 
1848
	return 0;
1849
}
1850
 
127 cycrow 1851
void C_File::setGame(unsigned int i) 
1852
{ 
1853
	if (i == 0 || i == 1 << 31)
1854
		_iGame = 0;
1855
	else
1856
		_iGame = i; 
1857
}
1858
 
1859
 
115 cycrow 1860
unsigned char *C_File::BobDecompile(size_t *size)
1861
{
1862
	(*size) = 0;
1863
 
129 cycrow 1864
	Utils::String fromFile = this->filePointer();
115 cycrow 1865
	if ( !CFileIO::Exists(fromFile) ) {
129 cycrow 1866
		if ( this->writeToFile(CPackages::tempDirectory() + "bob.tmp") ) {
115 cycrow 1867
			fromFile = CPackages::tempDirectory() + "bob.tmp";
1868
		}
1869
	}
1870
 
1871
	fromFile = fromFile.findReplace("/", "\\");
1872
	Utils::String toFile = CPackages::tempDirectory() + "bod.tmp";
1873
	toFile = toFile.findReplace("/", "\\");
1874
 
1875
	if ( CFileIO::Exists(fromFile) ) {
1876
		if ( X2BC_BOB2BOD(fromFile.c_str(), toFile.c_str()) ) {
1877
			CFileIO F(toFile);
1878
			if ( F.exists() && F.startRead() ) {
1879
				unsigned char *data = F.readAll(size);
1880
				F.close();
1881
				F.remove();
1882
 
1883
				return data;
1884
			}
1885
		}
1886
	}
1887
 
1888
	if ( CFileIO::Exists(CPackages::tempDirectory() + "bob.tmp") )
1889
		CFileIO(CPackages::tempDirectory() + "bob.tmp").remove();
1890
	/*
1891
	Settings settings;
1892
	bob_dom_document doc(&settings);
1893
 
1894
	ibinaryrealfile is;
1895
	otextrealfile os;
1896
	os.open(CPackages::tempDirectory() + "tmp.tmp", filestream::create);
129 cycrow 1897
	is.open(this->filePointer().c_str(), filestream::rdonly);
115 cycrow 1898
 
1899
	if(is.fail() || os.fail()) return NULL;
1900
 
1901
	bool bRes=doc.convert(is, os);
1902
 
1903
	for(bob_dom_document::ErrorIterator &it=doc.errors.begin(); it!=doc.errors.end(); ++it){
1904
		//BOBError(*it);
1905
	}
1906
 
1907
	if ( bRed ) {
1908
		CFileIO F(CPackages::tempDirectory() + "tmp.tmp");
1909
		if ( F.exists() && F.startRead() ) {
1910
			unsigned char *data = F.readAll(size);
1911
			F.close();
1912
			F.remove();
1913
 
1914
			return data;
1915
		}
1916
	}
1917
*/
1918
	return NULL;
1919
}
1920
 
1 cycrow 1921
bool C_File::BobDecompile()
1922
{
1923
	bool bRes=false;
1924
 
1925
 
1926
	CyStringList outData;
1927
	outData.PushBack("// Converted by SPK Libraries\n");
1928
	/*
1929
	bob_with_errors *e=0;
1930
	char *pszTime;
1931
	char *name="";
1932
 
1933
	time_t tm=time(0);
1934
	pszTime=ctime(&tm);
1935
	pszTime[strlen(pszTime)-1]=0;
1936
 
1937
	clearErrors();
1938
 
1939
	os << "// Converted with x2bc from \"" << is.name() << "\" at " << pszTime << endl;
1940
	if(settings->convert()==false)
1941
		os << "// Raw mode - values are not converted" << endl;
1942
	os << endl;
1943
	*/
1944
	/*
1945
	switch(m_sData[0]){
1946
		case bob_dom_bob::hdr_begin:
1947
			{
1948
				bob_dom_bob *bob = new bob_dom_bob(NULL);
1949
				//bRes=bob->load(is);
1950
				//if(bRes) bRes=bob->toFile(os);
1951
				delete bob;
1952
				break;
1953
			}
1954
		case bob_dom_cut::hdr_begin:
1955
			{
1956
				bob_dom_cut *cut = new bob_dom_cut(NULL);
1957
				//bRes=cut->convert(is, os);
1958
				delete cut;
1959
				break;
1960
			}
1961
		default:
1962
			return false;
1963
	}
1964
 
1965
	if(e){
1966
		for(bob_with_errors::ErrorIterator &it=e->errors.begin(); it!=e->errors.end(); ++it){
1967
			bob_error(it->severity, it->code, "%s->%s", name, it->text);
1968
		}
1969
	}
1970
	return bRes;
1971
 
1972
	bob_dom_ibufferstream<unsigned char> is((const unsigned char *)m_sData, m_lDataSize);
1973
	bob_dom_otextrealfile os;
1974
 
1975
	if(is.fail() || os.fail()) return false;
1976
 
1977
	bool bRes=doc.convert(is, os);*/
1978
 
1979
	return bRes;
1980
}
1981
 
1982
bool C_File::BodCompile()
1983
{
1984
	return true;
1985
}
1986
 
1987
bool C_File::RenameScript(CyString baseName)
1988
{
1989
	if ( !m_sData || !m_lDataSize )
1990
	{
1991
		if ( !this->ReadFromFile() )
1992
			return false;
1993
	}
1994
 
1995
	// uncompress the file
1996
	if ( !this->UncompressData() )
1997
		return false;
1998
 
1999
	// un pck the file
2000
	if ( this->CheckFileExt("pck") )
2001
	{
2002
		if ( !this->UnPCKFile() )
2003
			return false;
2004
	}
2005
 
2006
	// now we should have the raw data
2007
	CyString data((const char *)m_sData);
2008
	data.Truncate(m_lDataSize);
2009
	data = data.FindReplace(this->GetBaseName(), baseName);
2010
 
2011
	this->DeleteData();
2012
	m_sData = new unsigned char[data.Length()];
2013
	memcpy(m_sData, data.c_str(), data.Length());
2014
	m_lDataSize = (long)data.Length();
2015
 
2016
	// repck the file
2017
	if ( this->CheckFileExt("pck") )
2018
	{
2019
		if ( !this->PCKFile() )
2020
			return false;
2021
	}
2022
 
2023
 
2024
	return true;
129 cycrow 2025
}
2026
 
2027
Utils::String C_File::_getFullFileToDir(const Utils::String &dir, bool includedir, CBaseFile *file) const
2028
{
2029
	Utils::String fullfile = dir;
2030
	if (includedir)
2031
	{
2032
		Utils::String d = getDirectory(file);
2033
		if (!d.empty())
2034
		{
2035
			if (!fullfile.empty())
2036
				fullfile += "/";
2037
			fullfile += d;
2038
		}
2039
	}
130 cycrow 2040
	if (!_sName.empty())
129 cycrow 2041
	{
2042
		if (!fullfile.empty())
2043
			fullfile += "/";
130 cycrow 2044
		fullfile += _sName;
129 cycrow 2045
	}
2046
 
2047
	fullfile = fullfile.findReplace("\\", "/");
2048
	return fullfile;
2049
}