Subversion Repositories spk

Rev

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