Subversion Repositories spk

Rev

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