Subversion Repositories spk

Rev

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