Subversion Repositories spk

Rev

Rev 269 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 cycrow 1
// SpkFile.cpp: implementation of the CSpkFile class.
2
//
3
//////////////////////////////////////////////////////////////////////
4
 
5
#include "BaseFile.h"
6
 
7
//////////////////////////////////////////////////////////////////////
8
// Construction/Destruction
9
//////////////////////////////////////////////////////////////////////
10
 
11
#include "spk.h"
12
 
13
#include "DirIO.h"
14
#include "File_IO.h"
15
#include "CatFile.h"
16
#include "Packages.h"
88 cycrow 17
#include "TextDB.h"
6 cycrow 18
 
46 cycrow 19
#include <Package/InstallText.h>
6 cycrow 20
 
46 cycrow 21
// remove these eventually
22
using namespace SPK;
23
using namespace Package;
6 cycrow 24
 
25
CArchiveFile::~CArchiveFile()
26
{
27
	Delete ();
28
}
29
 
30
CArchiveFile::CArchiveFile() : CBaseFile ()
31
{
32
	SetDefaults ();
33
}
34
 
35
void CBaseFile::SetDefaults ()
36
{
46 cycrow 37
	_setDefaults();
38
 
6 cycrow 39
	m_pIconFile = NULL;
40
 
41
	m_bAutoGenerateUpdateFile = false;
42
	m_SHeader.iValueCompression = SPKCOMPRESS_ZLIB;
43
	m_SHeader2.iFileCompression = SPKCOMPRESS_ZLIB;
44
	m_SHeader2.iDataCompression = SPKCOMPRESS_LZMA;
45
	m_pParent = NULL;
50 cycrow 46
	_changed();
6 cycrow 47
	m_bUpdate = false;
130 cycrow 48
	_bCombineFiles = false;
6 cycrow 49
 
50
	ClearError();
51
 
52
	m_iLoadError = 0;
53
 
54
	m_bFullyLoaded = false;
55
	m_bSigned = false;
56
	m_bEnable = m_bGlobal = m_bProfile = m_bModifiedEnabled = true;
57
	m_bOverrideFiles = false;
58
}
59
 
88 cycrow 60
CBaseFile::CBaseFile() : _pTextDB(NULL)
6 cycrow 61
{
62
	SetDefaults ();
63
}
64
CBaseFile::~CBaseFile()
65
{
66
	Delete();
67
}
68
 
170 cycrow 69
 
203 cycrow 70
Utils::WString CBaseFile::getFullPackageName(int language, const Utils::WString &byString) const
170 cycrow 71
{ 
72
	return getFullPackageName(language, true, byString); 
73
}
203 cycrow 74
Utils::WString CBaseFile::getFullPackageName(int language, bool includeVersion, const Utils::WString &byString) const
170 cycrow 75
{
203 cycrow 76
	Utils::WString p = this->name(language);
170 cycrow 77
	if (includeVersion)
78
	{
203 cycrow 79
		p += L" V";
204 cycrow 80
		p += this->version();
170 cycrow 81
	}
203 cycrow 82
	p += L" ";
83
	p += byString + L" " + this->author();
170 cycrow 84
	return p;
85
}
86
 
203 cycrow 87
Utils::WString CBaseFile::getFullPackageName(const Utils::WString &format, int lang) const
170 cycrow 88
{
89
	if (format.empty())
90
		return getFullPackageName(lang);
91
 
204 cycrow 92
	Utils::WString args[3] = { this->name(lang), this->version(), this->author() };
170 cycrow 93
	return format.args(args, 3);
94
}
95
 
6 cycrow 96
void CBaseFile::Delete ()
97
{
170 cycrow 98
	m_lTempFiles.clear();
6 cycrow 99
	m_lFiles.clear(true);
100
 
101
	if ( m_pIconFile )
102
	{
103
		delete m_pIconFile;
104
		m_pIconFile = NULL;
105
	}
106
 
88 cycrow 107
	if ( _pTextDB ) {
108
		delete _pTextDB;
109
		_pTextDB = NULL;
110
	}
6 cycrow 111
}
112
 
113
 
114
/*
115
##########################################################################################
116
##################                Base Class Functions                  ##################
117
##########################################################################################
118
*/
119
 
170 cycrow 120
const CLinkList<C_File> &CBaseFile::fileList() const
131 cycrow 121
{
170 cycrow 122
	return m_lFiles;
131 cycrow 123
}
170 cycrow 124
CLinkList<C_File> &CBaseFile::fileList(FileType type, CLinkList<C_File>& list) const
125
{ 
126
	for (CListNode<C_File>* node = m_lFiles.Front(); node; node = node->next())
6 cycrow 127
	{
170 cycrow 128
		C_File* f = node->Data();
129
		if (f->GetFileType() == type)
130
			list.push_back(f);
6 cycrow 131
	}
132
 
133
	return list;
134
}
170 cycrow 135
CLinkList<C_File> &CBaseFile::fileList(FileType type)
136
{
137
	m_lTempFiles.clear();
138
	return fileList(type, m_lTempFiles);
139
}
6 cycrow 140
 
13 cycrow 141
C_File *CBaseFile::GetNextFile(C_File *prev) const
6 cycrow 142
{
143
	int type = -1;
144
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
145
	{
146
		C_File *f = node->Data();
147
		if ( type == -1 )
148
		{
149
			if ( f == prev )
150
				type = f->GetFileType();
151
		}
152
		else
153
		{
154
			if ( f->GetFileType() == type )
155
				return f;
156
		}
157
	}
158
 
159
	return NULL;
160
}
161
 
13 cycrow 162
C_File *CBaseFile::GetPrevFile(C_File *next) const
6 cycrow 163
{
164
	if ( !next )
165
		return NULL;
166
 
167
	int type = -1;
168
	for ( CListNode<C_File> *node = m_lFiles.Back(); node; node = node->prev() )
169
	{
170
		C_File *f = node->Data();
171
		if ( type == -1 )
172
		{
173
			if ( f == next )
174
				type = f->GetFileType();
175
		}
176
		else
177
		{
178
			if ( f->GetFileType() == type )
179
				return f;
180
		}
181
	}
182
 
183
	return NULL;
184
}
185
 
13 cycrow 186
C_File *CBaseFile::GetFirstFile(int type) const
6 cycrow 187
{
188
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
189
	{
190
		C_File *f = node->Data();
191
		if ( f->GetFileType() == type )
192
			return f;
193
	}
194
 
195
	return NULL;
196
}
197
 
197 cycrow 198
int CBaseFile::CheckFile(const Utils::WString &filename, float *version )
6 cycrow 199
{
91 cycrow 200
	CFileIO File(filename);
201
	if ( !File.startRead() ) return 0;
210 cycrow 202
	Utils::WString line = File.readEndOfLine();
203
	Utils::WString type = line.token(L";", 1);
51 cycrow 204
	File.close();
6 cycrow 205
 
206
	// check for old version
210 cycrow 207
	if ( line.left(3) == L"HiP" ) return SPKFILE_OLD;
6 cycrow 208
 
209
	// check for format
210 cycrow 210
	if ( version ) *version = line.token(L";", 2);
6 cycrow 211
 
210 cycrow 212
	if ( type == L"BaseCycrow" )	return SPKFILE_BASE;
213
	if ( type == L"SPKCycrow" )	return SPKFILE_SINGLE;
214
	if ( type == L"XSPCycrow" )	return SPKFILE_SINGLESHIP;
215
	if ( type == L"MSPKCycrow" )	return SPKFILE_MULTI;
6 cycrow 216
	return SPKFILE_INVALID;
217
}
218
 
219
void CBaseFile::ClearFileData()
220
{
88 cycrow 221
	for ( CListNode<C_File> *f = m_lFiles.Front(); f; f = f->next() )
6 cycrow 222
	{
88 cycrow 223
		f->Data()->DeleteData();
6 cycrow 224
	}
225
}
226
 
197 cycrow 227
Utils::WString CBaseFile::getNameValidFile() const
6 cycrow 228
{
197 cycrow 229
	Utils::WString name = this->name();
130 cycrow 230
	name.removeChar(':');
231
	name.removeChar('/');
232
	name.removeChar('\\');
233
	name.removeChar('*');
234
	name.removeChar('?');
235
	name.removeChar('"');
236
	name.removeChar('<');
237
	name.removeChar('>');
238
	name.removeChar('|');
239
	return name;
240
}
6 cycrow 241
 
242
void CBaseFile::SwitchFilePointer(C_File *oldFile, C_File *newFile)
243
{
244
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
245
	{
246
		C_File *f = node->Data();
247
		if ( f == oldFile )
248
		{
249
			node->ChangeData(newFile);
250
			break;
251
		}
252
	}
253
}
254
 
255
bool CBaseFile::AnyFileType ( int type )
256
{
257
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
258
	{
259
		C_File *f = node->Data();
260
		if ( f->GetFileType() == type )
261
			return true;
262
	}
263
 
264
	return false;
265
}
266
 
267
void CBaseFile::AddFile ( C_File *file )
268
{
269
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
270
	{
271
		C_File *f = node->Data();
130 cycrow 272
		if ( f->fileType() != file->fileType() )
6 cycrow 273
			continue;
130 cycrow 274
		if ( f->name() != file->name () )
6 cycrow 275
			continue;
170 cycrow 276
		if ( f->dir() != file->dir() )
6 cycrow 277
			continue;
127 cycrow 278
		if ( f->game() != file->game() )
6 cycrow 279
			continue;
280
 
281
		m_lFiles.remove(node, true);
282
		break;
283
	}
284
 
88 cycrow 285
	_addFile(file);
6 cycrow 286
}
287
 
197 cycrow 288
C_File *CBaseFile::addFile(const Utils::WString &file, const Utils::WString &dir, FileType type, int game, bool packed)
127 cycrow 289
{
290
	C_File *newfile = new C_File(file);
178 cycrow 291
	newfile->setDir(dir);
130 cycrow 292
	newfile->setFileType(type);
127 cycrow 293
	newfile->setGame(game);
6 cycrow 294
 
155 cycrow 295
	if (packed)
296
	{
297
		if (newfile->PCKFile())
197 cycrow 298
			newfile->setFilename(CFileIO(newfile->filePointer()).changeFileExtension(L"pck"));
155 cycrow 299
	}
300
 
6 cycrow 301
	// first check if the file already exists
302
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
303
	{
304
		C_File *f = node->Data();
130 cycrow 305
		if ( f->fileType() != newfile->fileType() )
6 cycrow 306
			continue;
130 cycrow 307
		if ( f->name() != newfile->name () )
6 cycrow 308
			continue;
134 cycrow 309
		if ( f->dir() != newfile->dir() )
6 cycrow 310
			continue;
130 cycrow 311
		if (f->game() != newfile->game())
312
		{
313
			//same file, for different game, check if they are the same and combine them
314
			if (_bCombineFiles)
315
			{
316
				char *data = NULL;
317
				char *newData = NULL;
318
				size_t size = 0;
319
				size_t newSize = 0;
320
 
321
				if (f->GetData() && f->GetDataSize())
143 cycrow 322
					data = (char *)f->UncompressData((long *)&size, NULL);
130 cycrow 323
				else if(f->isExternalFile())
324
					data = CFileIO(f->filePointer()).ReadToData(&size);
325
				if (newfile->GetData() && newfile->GetDataSize())
143 cycrow 326
					newData = (char *)f->UncompressData((long *)&newSize, NULL);
130 cycrow 327
				else
328
					newData = CFileIO(newfile->filePointer()).ReadToData(&newSize);
329
 
330
				// compare bytes
331
				bool matched = false;
332
				if (size == newSize)
333
				{
334
					matched = true;
335
					for (unsigned long i = 0; i < size; ++i)
336
					{
337
						if (data[i] != newData[i])
338
						{
339
							matched = false;
340
							break;
341
						}
342
					}
343
				}
344
 
143 cycrow 345
				if (data)
130 cycrow 346
					delete data;
143 cycrow 347
				if (newData)
130 cycrow 348
					delete newData;
349
 
350
				if (matched)
351
				{
352
					if(!f->game() || f->game() == GAME_ALLNEW)
353
						newfile->setGame(0);
354
					else
355
						newfile->setGame(newfile->game() | f->game());
356
					m_lFiles.remove(node, true);
357
					break;
358
				}
359
			}
6 cycrow 360
			continue;
130 cycrow 361
		}
6 cycrow 362
 
363
		// must already exist, delete this one
364
		m_lFiles.remove(node, true);
365
		break;
366
	}
367
 
88 cycrow 368
	_addFile(newfile);
6 cycrow 369
 
370
	return newfile;
371
}
372
 
210 cycrow 373
bool CBaseFile::addFileNow(const Utils::WString &file, const Utils::WString &dir, FileType type, CProgressInfo* progress)
6 cycrow 374
{
170 cycrow 375
	C_File* f = addFile(file, dir, type);
376
	if (!f->ReadFromFile())
6 cycrow 377
		return false;
378
 
379
	// compress the file
170 cycrow 380
	return f->CompressData(m_SHeader2.iDataCompression, progress);
6 cycrow 381
}
382
 
197 cycrow 383
C_File *CBaseFile::appendFile(const Utils::WString &file, int type, int game, bool packed, const Utils::WString &dir, CProgressInfo *progress )
6 cycrow 384
{
155 cycrow 385
	C_File *newfile = addFile(file, dir, static_cast<FileType>(type), game, packed);
6 cycrow 386
	if ( !newfile )
387
		return NULL;
388
 
389
	// read the file into memory
155 cycrow 390
	if (newfile->GetData() && newfile->GetDataSize())
391
	{
392
		// now compress the file
393
		if (newfile->CompressData(m_SHeader2.iDataCompression, progress))
394
			return newfile;
395
	}
6 cycrow 396
	if ( newfile->ReadFromFile () )
397
	{
398
		// now compress the file
399
		if ( newfile->CompressData ( m_SHeader2.iDataCompression, progress ) )
400
			return newfile;
401
	}
402
	else if ( newfile->GetLastError() == SPKERR_MALLOC )
403
	{
404
		if ( newfile->CompressFile ( progress ) )
405
			return newfile;
406
	}
407
 
408
	m_lFiles.pop_back ();
409
	delete newfile;
410
 
411
	return NULL;
412
}
413
 
170 cycrow 414
C_File *CBaseFile::findFileAt(FileType filetype, size_t pos) const
6 cycrow 415
{
170 cycrow 416
	size_t count = 0;
6 cycrow 417
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
418
	{
419
		C_File *file = node->Data();
420
		if ( file->GetFileType() != filetype )
421
			continue;
422
 
423
		if ( count == pos )
424
			return file;
425
 
426
		++count;
427
	}
428
 
429
	return NULL;
430
}
431
 
197 cycrow 432
C_File* CBaseFile::findFile(const Utils::WString &filename, FileType type, const Utils::WString &dir, int game) const
170 cycrow 433
{	
197 cycrow 434
	Utils::WString lfile = CFileIO(filename.lower()).filename();
6 cycrow 435
 
170 cycrow 436
	CListNode<C_File>* node = m_lFiles.Front();
437
	while (node)
6 cycrow 438
	{
170 cycrow 439
		C_File* f = node->Data();
6 cycrow 440
		node = node->next();
441
 
170 cycrow 442
		if (type != f->GetFileType())
6 cycrow 443
			continue;
170 cycrow 444
		if (dir != f->dir())
6 cycrow 445
			continue;
232 cycrow 446
		if (game && (game != f->game()))
6 cycrow 447
			continue;
170 cycrow 448
		if (f->name().lower() == lfile)
6 cycrow 449
			return f;
450
	}
451
	return NULL;
452
}
453
 
210 cycrow 454
bool CBaseFile::removeFile(const Utils::WString& file, FileType type, const Utils::WString& dir, int game)
6 cycrow 455
{
170 cycrow 456
	C_File* f = findFile(file, type, dir, game);
457
	if (!f)
6 cycrow 458
		return false;
172 cycrow 459
	return removeFile(f);
6 cycrow 460
}
461
 
172 cycrow 462
bool CBaseFile::removeFile(C_File *file)
6 cycrow 463
{
172 cycrow 464
	size_t count = 0;
6 cycrow 465
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
466
	{
467
		C_File *f = node->Data();
468
		if ( f == file )
172 cycrow 469
			return removeFile(count);
6 cycrow 470
		++count;
471
	}
472
	return false;
473
}
474
 
172 cycrow 475
bool CBaseFile::removeFile(size_t pos)
6 cycrow 476
{
172 cycrow 477
	if (pos >= static_cast<size_t>(m_lFiles.size()))
6 cycrow 478
		return false;
479
 
480
	C_File *file = m_lFiles.Get ( pos );
481
	m_lFiles.erase ( pos + 1 );
482
 
483
	if ( file )
484
		delete file;
485
 
50 cycrow 486
	_changed();
6 cycrow 487
 
488
	return true;
489
}
490
 
491
 
129 cycrow 492
void CBaseFile::removeAllFiles(FileType type, int game)
6 cycrow 493
{
494
	if ( m_lFiles.empty() )
495
		return;
496
 
497
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
498
	{
129 cycrow 499
		if (game == 0 && node->Data()->game() && node->Data()->game() != GAME_ALLNEW)
500
			continue;
501
		if ( game > -1 )
502
		{
503
			unsigned int fileGame = node->Data()->game() & ~GAME_ALLNEW;
504
			if (fileGame != (1 << game))
505
			{
506
				// just remove the game from file
507
				if (fileGame & (1 << game))
508
					node->Data()->setGame(node->Data()->game() & ~(1 << game));
6 cycrow 509
				continue;
129 cycrow 510
			}
6 cycrow 511
		}
129 cycrow 512
		if ( type == FILETYPE_UNKNOWN || node->Data()->GetFileType() == type )
6 cycrow 513
			node->DeleteData();
514
	}
515
 
516
	m_lFiles.RemoveEmpty();
517
 
50 cycrow 518
	_changed();
6 cycrow 519
}
520
 
521
void CBaseFile::RecompressAllFiles ( int type, CProgressInfo *progress )
522
{
523
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
524
	{
525
		C_File *file = node->Data();
526
		if ( progress )
527
			progress->UpdateFile(file);
528
 
529
		if ( file->GetCompressionType() == type )
530
			continue;
531
 
532
		if ( !file->GetData() )
533
			file->ReadFromFile();
534
 
535
		file->ChangeCompression ( type, progress );
536
	}
537
}
538
 
47 cycrow 539
void CBaseFile::CompressAllFiles ( int type, CProgressInfo *progress, CProgressInfo *overallProgress, int level )
6 cycrow 540
{
47 cycrow 541
	if ( overallProgress ) overallProgress->SetMax(m_lFiles.size());
542
 
543
	int iCount = 0;
6 cycrow 544
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
545
	{
546
		C_File *file = node->Data();
547
		if ( progress )
548
			progress->UpdateFile(file);
549
 
550
		if ( !file->GetData() )
551
			file->ReadFromFile();
552
 
553
		file->CompressData ( type, progress, level );
47 cycrow 554
 
555
		if ( overallProgress ) overallProgress->SetDone(++iCount);
6 cycrow 556
	}
557
}
558
 
559
bool CBaseFile::UncompressAllFiles ( CProgressInfo *progress )
560
{
561
	int countFile = 0;
562
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
563
	{
564
		C_File *fit = node->Data();
565
		if ( progress )
566
		{
567
			progress->UpdateFile ( fit );
568
			progress->UpdateProgress(countFile++, m_lFiles.size());
569
		}
570
 
571
		bool uncomprToFile = false;
572
 
573
		if ( progress )
574
			progress->SwitchSecond();
575
 
127 cycrow 576
		if(!fit->isExternalFile())
6 cycrow 577
		{
127 cycrow 578
			if (!fit->UncompressData(progress))
6 cycrow 579
			{
127 cycrow 580
				if (fit->GetCompressionType() == SPKCOMPRESS_7ZIP)
6 cycrow 581
				{
213 cycrow 582
					if (!fit->uncompressToFile(L"temp", this, false, progress))
127 cycrow 583
						return false;
584
					else
585
					{
586
						uncomprToFile = true;
213 cycrow 587
						fit->setFullDir(L"temp");
127 cycrow 588
					}
6 cycrow 589
				}
127 cycrow 590
 
591
				if (!uncomprToFile)
592
					return false;
6 cycrow 593
			}
594
		}
595
 
596
		if ( progress )
597
			progress->SwitchSecond();
598
	}
599
	return true;
600
}
601
 
170 cycrow 602
size_t CBaseFile::fileSize() const
6 cycrow 603
{
170 cycrow 604
	size_t fullsize = 1000;
6 cycrow 605
 
170 cycrow 606
	for (CListNode<C_File>* node = m_lFiles.Front(); node; node = node->next())
178 cycrow 607
		fullsize += node->Data()->uncompressedDataSize();
6 cycrow 608
 
170 cycrow 609
	if (m_pIconFile)
178 cycrow 610
		fullsize += m_pIconFile->uncompressedDataSize();
6 cycrow 611
 
612
	return fullsize;
613
}
614
 
615
/*
616
	Func:   GetEndOfLine
617
	Input:  id - The file id for the current file to read from
618
	        line - Pointed to hold the line number thats read
619
			upper - true if it converts to uppercase
620
	Return: String - the string it has read
621
	Desc:   Reads a string from a file, simlar to readLine() classes, reads to the end of the line in a file
622
*/
175 cycrow 623
Utils::String CBaseFile::GetEndOfLine ( FILE *id, int *line, bool upper )
6 cycrow 624
{
175 cycrow 625
	Utils::String word;
6 cycrow 626
 
627
	char c = fgetc ( id );
628
	if ( c == -1 )
629
		return "";
630
 
631
	while ( (c != 13) && (!feof(id)) && (c != '\n') )
632
	{
633
		word += c;
634
		c = fgetc ( id );
635
	}
636
 
637
	if ( line )
638
		++(*line);
639
 
640
	if ( upper )
175 cycrow 641
		return word.upper();
6 cycrow 642
 
643
	return word;
644
}
645
 
170 cycrow 646
size_t CBaseFile::countFiles(FileType filetype) const
6 cycrow 647
{
170 cycrow 648
	size_t i = 0;
6 cycrow 649
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
650
	{
651
		C_File *file = node->Data();
652
		if ( file->GetFileType() != filetype )
653
			continue;
654
		++i;
655
	}
656
 
657
	return i;
658
}
659
 
660
/*
661
	Func:   CreateFilesLine
662
	Return: String - returns the full string for files list
663
	Desc:   Creates a signle line list of all the files
664
*/
211 cycrow 665
Utils::WString CBaseFile::createFilesLine(SSPKHeader2 *header, CProgressInfo* progress) const
6 cycrow 666
{
197 cycrow 667
	Utils::WString line;
6 cycrow 668
 
170 cycrow 669
	if (progress)
6 cycrow 670
	{
671
		progress->SetDone(0);
672
		progress->UpdateStatus(STATUS_COMPRESS);
673
	}
674
 
175 cycrow 675
	if (header)
6 cycrow 676
	{
175 cycrow 677
		header->iDataCompression = m_SHeader2.iDataCompression;
678
		header->iFileCompression = m_SHeader2.iFileCompression;
679
		header->lSize = m_SHeader2.lSize;
680
		header->iNumFiles = 0;
681
		header->lFullSize = 0;
6 cycrow 682
	}
683
 
170 cycrow 684
	if (m_pIconFile)
6 cycrow 685
	{
686
		// no data, read it from file
170 cycrow 687
		if (!m_pIconFile->GetData())
688
			m_pIconFile->ReadFromFile();
6 cycrow 689
 
690
		// compress the file
170 cycrow 691
		if (!m_pIconFile->CompressData(m_SHeader2.iDataCompression, progress))
6 cycrow 692
			m_pIconFile->SetDataCompression(SPKCOMPRESS_NONE);
693
 
197 cycrow 694
		line += L"Icon:" + Utils::WString::Number(m_pIconFile->GetDataSize() + (long)4) + L":" + m_pIconFile->uncompressedDataSize() + L":" + (long)m_pIconFile->GetCompressionType() + L":" + _sIconExt + L"\n";
175 cycrow 695
		if (header)
6 cycrow 696
		{
175 cycrow 697
			++header->iNumFiles;
698
			header->lFullSize += (m_pIconFile->GetDataSize() + 4);
6 cycrow 699
		}
700
	}
701
 
170 cycrow 702
	for (CListNode<C_File>* node = m_lFiles.Front(); node; node = node->next())
6 cycrow 703
	{
170 cycrow 704
		C_File* file = node->Data();
705
		if (progress)
706
			progress->UpdateFile(file);
6 cycrow 707
 
708
		// no data, read it from file
170 cycrow 709
		if (!file->GetData())
6 cycrow 710
		{
170 cycrow 711
			if (!file->ReadFromFile())
6 cycrow 712
			{
170 cycrow 713
				if (file->GetLastError() == SPKERR_MALLOC)
6 cycrow 714
				{
170 cycrow 715
					if (!file->CompressFile(progress))
6 cycrow 716
						continue;
717
				}
718
			}
719
		}
720
 
170 cycrow 721
		if (!file->GetData())
6 cycrow 722
			continue;
723
 
724
		// compress the file
170 cycrow 725
		if (!file->CompressData(m_SHeader2.iDataCompression, progress))
6 cycrow 726
		{
727
			file->SetDataCompression(SPKCOMPRESS_NONE);
728
			file->SetUncompressedDataSize(file->GetDataSize());
729
		}
730
 
197 cycrow 731
		Utils::WString command = GetFileTypeString(file->GetFileType());
170 cycrow 732
		if (command.empty())
6 cycrow 733
			continue;
734
 
170 cycrow 735
		if (file->IsShared())
197 cycrow 736
			command = L"$" + command;
6 cycrow 737
 
170 cycrow 738
		if (file->dir().empty())
197 cycrow 739
			line += command + L":" + (file->GetDataSize() + (long)4) + L":" + file->uncompressedDataSize() + L":" + (long)file->GetCompressionType() + L":" + (long)file->GetCreationTime() + L":" + ((file->IsCompressedToFile()) ? L"1" : L"0") + L":" + file->filename() + L":NULL:" + (long)file->game() + L"\n";
6 cycrow 740
		else
197 cycrow 741
			line += command + L":" + (file->GetDataSize() + (long)4) + L":" + file->uncompressedDataSize() + L":" + (long)file->GetCompressionType() + L":" + (long)file->GetCreationTime() + L":" + ((file->IsCompressedToFile()) ? L"1" : L"0") + L":" + file->filename() + L":" + file->dir() + L":" + (long)file->game() + L"\n";
6 cycrow 742
 
175 cycrow 743
		if (header)
6 cycrow 744
		{
175 cycrow 745
			++header->iNumFiles;
746
			header->lFullSize += (file->GetDataSize() + 4);
6 cycrow 747
		}
748
	}
749
 
211 cycrow 750
	return line;
6 cycrow 751
}
752
 
753
/*
754
######################################################################################
755
##########							Reading Functions			    		##########
756
######################################################################################
757
*/
758
 
759
void CBaseFile::ReadAllFilesToMemory ()
760
{
761
	// no file to read from
50 cycrow 762
	if ( this->filename().empty() ) return;
6 cycrow 763
 
764
	// now open the file
58 cycrow 765
	CFileIO File(this->filename());
766
	if ( !File.startRead() ) return;
6 cycrow 767
 
768
	// read the header
197 cycrow 769
	File.readEndOfLineStr();
6 cycrow 770
	// skip past values
58 cycrow 771
	File.seek(4 + m_SHeader.lValueCompressSize);
6 cycrow 772
 
773
	// read the next header
197 cycrow 774
	File.readEndOfLineStr();
6 cycrow 775
	// skip past files
58 cycrow 776
	File.seek(4 + m_SHeader2.lSize);
6 cycrow 777
 
778
	if ( m_pIconFile )
779
	{
780
		if ( (!m_pIconFile->GetData()) && (!m_pIconFile->Skip()) )
51 cycrow 781
			m_pIconFile->readFromFile(File, m_pIconFile->GetDataSize());
6 cycrow 782
		else
58 cycrow 783
			File.seek(4 + m_pIconFile->GetDataSize());
6 cycrow 784
	}
785
 
786
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
787
	{
788
		C_File *fit = node->Data();
789
		if ( (!fit->GetData()) && (!fit->Skip()) )
51 cycrow 790
			fit->readFromFile(File, fit->GetDataSize());
6 cycrow 791
		else
58 cycrow 792
			File.seek(4 + fit->GetDataSize());
6 cycrow 793
	}
794
 
51 cycrow 795
	File.close();
6 cycrow 796
}
797
 
798
bool CBaseFile::ReadFileToMemory(C_File *f)
799
{
62 cycrow 800
	if ( this->filename().empty() || !f ) return false;		// no filename to load from
51 cycrow 801
	if ( f->GetData() && f->GetDataSize() ) return true;	// already loaded the data
802
	if ( !m_lFiles.FindData(f) ) return false;				// unable to find file entry
6 cycrow 803
 
804
	// now open the file
58 cycrow 805
	CFileIO *File = _startRead();
806
	if ( !File ) return false;
6 cycrow 807
 
58 cycrow 808
	if ( m_pIconFile ) File->seek(4 + m_pIconFile->GetDataSize());
51 cycrow 809
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ) {
6 cycrow 810
		C_File *fit = node->Data();
51 cycrow 811
		if (fit == f ) {
58 cycrow 812
			fit->readFromFile(*File, fit->GetDataSize());
6 cycrow 813
			break;
814
		}
58 cycrow 815
		else File->seek(4 + fit->GetDataSize());
6 cycrow 816
	}
817
 
58 cycrow 818
	delete File;
6 cycrow 819
	return true;
820
}
821
 
58 cycrow 822
CFileIO *CBaseFile::_startRead()
6 cycrow 823
{
824
	// no file to read from
58 cycrow 825
	if ( this->filename().empty() ) return NULL;
6 cycrow 826
 
827
	// now open the file
58 cycrow 828
	CFileIO *File = new CFileIO(this->filename());
829
	if ( !File->startRead() ) return NULL;
6 cycrow 830
 
831
	// read the header
197 cycrow 832
	File->readEndOfLineStr();
6 cycrow 833
	// skip past values
58 cycrow 834
	File->seek(4 + m_SHeader.lValueCompressSize);
6 cycrow 835
 
836
	// read the next header
197 cycrow 837
	File->readEndOfLineStr();
6 cycrow 838
	// skip past files
58 cycrow 839
	File->seek(4 + m_SHeader2.lSize);
6 cycrow 840
 
58 cycrow 841
	return File;
842
}
6 cycrow 843
 
88 cycrow 844
void CBaseFile::_addFile(C_File *file, bool dontChange)
845
{
846
	if ( !dontChange ) {
847
		file->UpdateSigned();
848
		_changed();
849
	}
850
	m_lFiles.push_back(file);
851
 
852
	_updateTextDB(file);
853
}
854
 
855
void CBaseFile::_updateTextDB(C_File *file)
856
{
857
	if ( !_pTextDB ) _pTextDB = new CTextDB();
858
 
859
	if ( file->GetFileType() == FILETYPE_TEXT ) {
196 cycrow 860
		Utils::WString baseFile = CFileIO(file->filePointer()).baseName();
861
		int lang = (baseFile.contains(L"-L")) ? baseFile.right(3) : baseFile.truncate(-4);
88 cycrow 862
 
863
		// read in the text file to the database
864
		_pTextDB->parseTextFile(0, 0, file->filePointer(), lang);
865
	}
866
}
867
 
868
void CBaseFile::_resetTextDB()
869
{
870
	if ( _pTextDB ) delete _pTextDB;
871
	_pTextDB = new CTextDB();
872
 
873
	for(CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next()) {
874
		_updateTextDB(node->Data());
875
	}
876
}
877
 
58 cycrow 878
void CBaseFile::ReadIconFileToMemory ()
879
{
880
	if ( !m_pIconFile )	return;
881
	CFileIO *File = _startRead();
882
	if ( !File ) return;
883
 
884
	if ( (!m_pIconFile->GetData()) && (!m_pIconFile->Skip()) )
885
		m_pIconFile->readFromFile(*File, m_pIconFile->GetDataSize());
886
	else
887
		File->seek(4 + m_pIconFile->GetDataSize());
888
 
889
	delete File;
6 cycrow 890
}
891
 
14 cycrow 892
void CBaseFile::_install_adjustFakePatches(CPackages *pPackages)
6 cycrow 893
{
197 cycrow 894
	Utils::WStringList lPatches;
182 cycrow 895
	int startfake = pPackages->findNextFakePatch();
6 cycrow 896
 
269 cycrow 897
	std::vector<C_File*> fakepatches;
898
	for (CListNode<C_File>* node = m_lFiles.Front(); node; node = node->next())
899
	{
900
		C_File* fit = node->Data();
901
		// only do fake patchs
902
		if (!fit->IsFakePatch())
903
			continue;
904
 
905
		// we should only have cat and dat files, but lets check just incase they have been added incorrectly
906
		if (!fit->checkFileExt(L"cat"))
907
			continue;
908
 
909
		if (fakepatches.empty())
910
			fakepatches.push_back(fit);
911
		else
912
		{
913
			bool added = false;
914
			int num = fit->baseName().toInt();
915
			for (auto itr = fakepatches.begin(); itr != fakepatches.end(); itr++)
916
			{
917
				int checkNum = (*itr)->baseName().toInt();
918
				if (num < checkNum) 
919
				{
920
					fakepatches.insert(itr, fit);
921
					added = true;
922
					break;
923
				}
924
			}
925
			if(!added)
926
				fakepatches.push_back(fit);
927
		}
928
	}
929
 
930
	// rename all the cat files
931
	for (auto itr = fakepatches.begin(); itr != fakepatches.end(); itr++)
932
	{
933
		Utils::WString newname = Utils::WString::PadNumber((long)startfake, 2);
934
		lPatches.pushBack((*itr)->baseName(), newname);
935
 
936
		// rename the file
937
		(*itr)->FixOriginalName();
938
		CLog::logf(CLog::Log_Install, 2, L"Adjusting fake patch number, %s => %s", (*itr)->getNameDirectory(this).c_str(), (newname + L"." + (*itr)->fileExt()).c_str());
939
		(*itr)->setName(newname + L"." + (*itr)->fileExt());
940
 
941
		// find the next gap
942
		startfake = pPackages->findNextFakePatch(startfake);
943
	}
944
 
945
	// now rename all the matching dat files
14 cycrow 946
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
947
	{
948
		C_File *fit = node->Data();
949
		// only do fake patchs
950
		if ( !fit->IsFakePatch() )
951
			continue;
952
 
953
		// we should only have cat and dat files, but lets check just incase they have been added incorrectly
269 cycrow 954
		if ( !fit->checkFileExt(L"dat") )
14 cycrow 955
			continue;
956
 
957
		// search for the name on the list
175 cycrow 958
		if (lPatches.contains(fit->baseName()))
959
		{
269 cycrow 960
			Utils::WString newname = lPatches.findString(fit->baseName());
14 cycrow 961
 
269 cycrow 962
			// rename the file
963
			fit->FixOriginalName();
964
			CLog::logf(CLog::Log_Install, 2, L"Adjusting fake patch number, %s => %s", fit->getNameDirectory(this).c_str(), (newname + L"." + fit->fileExt()).c_str());
965
			fit->setName(newname + L"." + fit->fileExt());
14 cycrow 966
		}
967
	}
968
}
969
 
43 cycrow 970
void CBaseFile::_install_renameText(CPackages *pPackages)
14 cycrow 971
{
130 cycrow 972
	int starttext = pPackages->findNextTextFile();
43 cycrow 973
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ) {
974
		C_File *fit = node->Data();
130 cycrow 975
		if ( !fit->isAutoTextFile() )
43 cycrow 976
			continue;
6 cycrow 977
 
197 cycrow 978
		Utils::WString newname = SPK::FormatTextName(starttext, pPackages->GetLanguage(), (pPackages->GetCurrentGameFlags() & EXEFLAG_TCTEXT));
43 cycrow 979
		fit->FixOriginalName();
227 cycrow 980
		CLog::logf(CLog::Log_Install, 2, L"Adjusting text file, %s => %s", fit->getNameDirectory(this).c_str(), (newname + "." + fit->fileExt()).c_str());
130 cycrow 981
		fit->setName(newname + "." + fit->fileExt());
6 cycrow 982
 
43 cycrow 983
		++starttext;
984
	}
985
}
6 cycrow 986
 
50 cycrow 987
bool CBaseFile::_install_setEnabled(bool bEnable, C_File *fit)
988
{
989
	if ( !bEnable )
990
	{
991
		if ( (fit->GetFileType() == FILETYPE_UNINSTALL) || (fit->GetFileType() == FILETYPE_README) || (fit->GetFileType() == FILETYPE_ADVERT) )
992
			bEnable = true;
213 cycrow 993
		else if ( (fit->GetFileType() == FILETYPE_EXTRA) && (fit->dir().left(7).lower() == L"Extras/") )
50 cycrow 994
			bEnable = true;
995
		else if ( (IsPatch()) && (fit->GetFileType() == FILETYPE_MOD) && (!fit->IsFakePatch()) )
996
			bEnable = true;
997
 
227 cycrow 998
		if ( bEnable ) CLog::logf(CLog::Log_Install, 3, L"Filetype(%d) is always enabled, setting enabled flag", fit->GetFileType());
50 cycrow 999
	}
1000
 
1001
	return bEnable;
1002
}
1003
 
197 cycrow 1004
bool CBaseFile::_install_uncompress(C_File *fit, CProgressInfo *progress, Utils::WStringList *errorStr, bool *uncomprToFile)
50 cycrow 1005
{
1006
	*uncomprToFile = false;
134 cycrow 1007
	_sLastError = fit->getNameDirectory(this);
1008
	_iLastError = SPKERR_UNCOMPRESS;
96 cycrow 1009
 
50 cycrow 1010
	if ( !fit->UncompressData ( progress ) )
1011
	{
213 cycrow 1012
		CLog::log(CLog::Log_Install, 2, L"Failed to uncompress data, attempting file decompression");
50 cycrow 1013
		if ( fit->GetCompressionType() == SPKCOMPRESS_7ZIP )
1014
		{
197 cycrow 1015
			if ( fit->uncompressToFile(Utils::WString::Null(), this, false, progress ) )
50 cycrow 1016
				*uncomprToFile = true;
1017
		}
1018
 
1019
		if ( !uncomprToFile )
1020
		{
1021
			if ( errorStr )
175 cycrow 1022
				errorStr->pushBack(_sLastError, ERRORLOG(SPKINSTALL_UNCOMPRESS_FAIL));
213 cycrow 1023
			CLog::log(CLog::Log_Install, 1, L"Unable to decompress file, skipping");
50 cycrow 1024
			return false;
1025
		}
1026
	}
1027
	ClearError ();
1028
 
1029
	return true;
1030
}
1031
 
197 cycrow 1032
bool CBaseFile::_install_checkVersion(C_File *pFile, const Utils::WString &sDestination)
50 cycrow 1033
{
1034
	// new check if we should install the file
1035
	// first get the version
1036
	if ( !m_bOverrideFiles && pFile->ReadScriptVersion() )
1037
	{
213 cycrow 1038
		CLog::log(CLog::Log_Install, 2, L"Checking for existing file version");
50 cycrow 1039
		C_File checkfile;
197 cycrow 1040
		Utils::WString checkfilename = sDestination;
1041
		if ( !checkfilename.empty() ) checkfilename += L"/";
175 cycrow 1042
		checkfilename += pFile->getNameDirectory(this);
1043
		checkfile.setFilename(checkfilename);
127 cycrow 1044
		checkfile.setFileType(pFile->fileType());
50 cycrow 1045
		if ( checkfile.CheckValidFilePointer() ) {
1046
			if ( checkfile.ReadScriptVersion() > pFile->GetVersion() ) {
213 cycrow 1047
				CLog::log(CLog::Log_Install, 1, L"Newer version of the file found in directory, skipping");
50 cycrow 1048
				return false;
1049
			}
1050
		}
1051
	}
1052
 
1053
	return true;
1054
}
1055
 
210 cycrow 1056
Utils::WString CBaseFile::_install_adjustFilepointer(C_File *pFile, bool bEnabled, const Utils::WString &sDestination)
50 cycrow 1057
{
197 cycrow 1058
	Utils::WString filename = sDestination;
1059
	if ( !filename.empty() ) filename += L"/";
50 cycrow 1060
 
130 cycrow 1061
	if ( (IsPatch()) && (pFile->fileType() == FILETYPE_MOD) )
197 cycrow 1062
		pFile->setDir(L"Patch");
50 cycrow 1063
 
160 cycrow 1064
	if ( pFile->isInMod() )
50 cycrow 1065
	{
1066
		if ( bEnabled )
197 cycrow 1067
			pFile->setFilename(filename + pFile->getInMod() + L"::" + pFile->getNameDirectory(this));
50 cycrow 1068
		else
197 cycrow 1069
			pFile->setFilename(filename + L"PluginManager/DisabledFiles.cat::" + pFile->getNameDirectory(this));
50 cycrow 1070
	}
1071
	else
130 cycrow 1072
		pFile->setFilename ( filename + pFile->getNameDirectory(this) );
50 cycrow 1073
 
1074
	if ( !bEnabled )
1075
	{
160 cycrow 1076
		if ( !pFile->isInMod() )
50 cycrow 1077
		{
1078
			if ( pFile->IsFakePatch() )
203 cycrow 1079
				pFile->setFilename ( filename + L"PluginManager/Disabled/FakePatches/FakePatch_" + this->getNameValidFile() + L"_" + this->author() + L"_" + pFile->name());
130 cycrow 1080
			else if ( pFile->isAutoTextFile() )
203 cycrow 1081
				pFile->setFilename ( filename + L"PluginManager/Disabled/TextFiles/Text_" + this->getNameValidFile() + L"_" + this->author() + L"_" + pFile->name());
50 cycrow 1082
			else
197 cycrow 1083
				pFile->setFullDir ( filename + L"PluginManager/Disabled/" + pFile->getDirectory(this) );
50 cycrow 1084
		}
1085
		pFile->SetDisabled(true);
1086
	}
1087
 
227 cycrow 1088
	CLog::logf(CLog::Log_Install, 2, L"Adjusting the file pointer to correct install destintation, %s", pFile->filePointer().c_str());
50 cycrow 1089
 
210 cycrow 1090
	return filename;
50 cycrow 1091
}
1092
 
197 cycrow 1093
C_File *CBaseFile::_install_checkFile(C_File *pFile, Utils::WStringList *errorStr, bool *bDoFile, CLinkList<C_File> *pFileList)
50 cycrow 1094
{
1095
	if ( !pFile->IsFakePatch() && pFile->GetFileType() != FILETYPE_README )
1096
	{
1097
		C_File *cFile;
1098
		for ( cFile = pFileList->First(); cFile; cFile = pFileList->Next() )
1099
		{
1100
			if ( !cFile->MatchFile(pFile) ) continue;
1101
			if ( !m_bOverrideFiles && !cFile->CompareNew(pFile) ) {
175 cycrow 1102
				if ( errorStr ) errorStr->pushBack(pFile->getNameDirectory(this), ERRORLOG(SPKINSTALL_SKIPFILE));
213 cycrow 1103
				CLog::log(CLog::Log_Install, 1, L"Newer version of the file already installed, skipping");
50 cycrow 1104
				*bDoFile = false;
1105
			}
1106
			break;
1107
		}
1108
 
1109
		return cFile;
1110
	}
1111
 
1112
	return NULL;
1113
}
1114
 
197 cycrow 1115
bool CBaseFile::_install_checkFileEnable(C_File *pCheckFile, C_File *fit, const Utils::WString &sDestination, bool bEnabled, Utils::WStringList *errorStr)
50 cycrow 1116
{
1117
	// found a file, check if its in the disabled directory
196 cycrow 1118
	Utils::WString dir = CFileIO(pCheckFile->filePointer()).dir();
1119
	Utils::WString lastDir = CDirIO(dir).topDir().lower();
50 cycrow 1120
 
1121
	// if its disabled, rename it so its enabled
196 cycrow 1122
	if ( ((pCheckFile->IsDisabled()) || (lastDir == L"disabled") || (dir.lower().contains(L"/disabled/"))) && (bEnabled) )
50 cycrow 1123
	{
227 cycrow 1124
		CLog::logf(CLog::Log_Install, 2, L"Existing file, %s, is disabled, re-enabling it", pCheckFile->filePointer().c_str());
50 cycrow 1125
		// first check if the directory exists
160 cycrow 1126
		if ( pCheckFile->isInMod() ) {
197 cycrow 1127
			Utils::WString tofile = pCheckFile->filePointer().token(L"::", 2);
50 cycrow 1128
 
1129
			CCatFile tocat;
197 cycrow 1130
			int err = tocat.open(fit->filePointer().token(L"::", 1), L"", CATREAD_CATDECRYPT, true);
50 cycrow 1131
			if ( (err == CATERR_NONE) || (err == CATERR_CREATED) ) {
181 cycrow 1132
				tocat.appendFile(pCheckFile->filePointer(), tofile);
227 cycrow 1133
				CLog::logf(CLog::Log_Install, 2, L"Adding existing file into new mod File, %s => %s", fit->filePointer().token(L"::", 1).c_str(), tofile.c_str());
50 cycrow 1134
			}
1135
 
1136
			CCatFile fromcat;
197 cycrow 1137
			err = fromcat.open(pCheckFile->filePointer().token(L"::", 1), L"", CATREAD_CATDECRYPT, false);
50 cycrow 1138
			if ( err == CATERR_NONE ) {
175 cycrow 1139
				fromcat.removeFile(tofile);
227 cycrow 1140
				CLog::logf(CLog::Log_Install, 2, L"Removing file from existing mod, %s::%s", pCheckFile->filePointer().token(L"::", 1).c_str(), tofile.c_str());
50 cycrow 1141
			}
1142
 
227 cycrow 1143
			CLog::logf(CLog::Log_Install, 1, L"Adjusting existing file name %s => %s", pCheckFile->filePointer().c_str(), fit->filePointer().c_str());
178 cycrow 1144
			pCheckFile->setFilename(fit->filePointer());
227 cycrow 1145
			CLog::logf(CLog::Log_Install, 2, L"Adjusting In Mod setting, %s => %s", pCheckFile->getInMod().c_str(), fit->getInMod().c_str());
160 cycrow 1146
			pCheckFile->setInMod(fit->getInMod());
50 cycrow 1147
		}
1148
		else {
197 cycrow 1149
			Utils::WString to = pCheckFile->getDirectory(this);
50 cycrow 1150
			CDirIO Dir(sDestination);
160 cycrow 1151
			if ( !Dir.exists(to) ) {
1152
				if ( !Dir.create ( to ) ) {
211 cycrow 1153
					if ( errorStr )	errorStr->pushBack(to, ERRORLOG(SPKINSTALL_CREATEDIRECTORY_FAIL));
50 cycrow 1154
					return false;
1155
				}
211 cycrow 1156
				if ( errorStr )	errorStr->pushBack(to, ERRORLOG(SPKINSTALL_CREATEDIRECTORY));
50 cycrow 1157
			}
1158
 
197 cycrow 1159
			Utils::WString destfile = sDestination + L"/" + pCheckFile->getNameDirectory(this);
1160
			if ( CFileIO::Exists(destfile) ) CFileIO::Remove(destfile);
227 cycrow 1161
			CLog::logf(CLog::Log_Install, 1, L"Adjusting existing filename, %s => %s", pCheckFile->filePointer().c_str(), destfile.c_str());
197 cycrow 1162
			CFileIO::Rename(pCheckFile->filePointer(), destfile);
1163
			pCheckFile->setFilename (sDestination + L"/" + pCheckFile->getNameDirectory(this) );
50 cycrow 1164
		}
1165
		pCheckFile->SetDisabled(false);
1166
 
175 cycrow 1167
		if ( errorStr ) errorStr->pushBack(pCheckFile->getNameDirectory(this), ERRORLOG(SPKINSTALL_ENABLEFILE));
50 cycrow 1168
	}
1169
 
1170
	return true;
1171
}
51 cycrow 1172
 
197 cycrow 1173
bool CBaseFile::_install_createDirectory(CDirIO &Dir, const Utils::WString &sTo, C_File *pFile, Utils::WStringList *errorStr)
51 cycrow 1174
{
134 cycrow 1175
	_sLastError = sTo;
197 cycrow 1176
	if ( !sTo.contains(L"::"))
51 cycrow 1177
	{
121 cycrow 1178
		if ( !Dir.exists(sTo) )
51 cycrow 1179
		{
227 cycrow 1180
			CLog::logf(CLog::Log_Install, 2, L"Creating directory to install file into, %s", sTo.c_str());
160 cycrow 1181
			if ( !Dir.create(sTo) )
51 cycrow 1182
			{
1183
				if ( errorStr )
175 cycrow 1184
					errorStr->pushBack(sTo, ERRORLOG(SPKINSTALL_CREATEDIRECTORY_FAIL));
51 cycrow 1185
				return false;
1186
			}
1187
			if ( errorStr )
175 cycrow 1188
				errorStr->pushBack(sTo, ERRORLOG(SPKINSTALL_CREATEDIRECTORY));
51 cycrow 1189
		}
1190
	}
1191
	else {
227 cycrow 1192
		CLog::logf(CLog::Log_Install, 2, L"Adjusting file extension for file in mod, %s => %s", pFile->filePointer().c_str(), CCatFile::PckChangeExtension(pFile->filePointer()).c_str());
134 cycrow 1193
		pFile->setFilename(CCatFile::PckChangeExtension(pFile->filePointer()));
51 cycrow 1194
	}
1195
 
1196
	return true;
1197
}
1198
 
197 cycrow 1199
void CBaseFile::_install_writeFile(C_File *pFile, const Utils::WString &sDestination, Utils::WStringList *errorStr)
51 cycrow 1200
{
134 cycrow 1201
	_iLastError = SPKERR_WRITEFILE;
1202
	_sLastError = pFile->filePointer();
197 cycrow 1203
	Utils::WString sInstalledFile = pFile->getNameDirectory(this);
51 cycrow 1204
	if ( pFile->IsDisabled() )
1205
	{
134 cycrow 1206
		sInstalledFile = pFile->filePointer().findRemove(sDestination);
51 cycrow 1207
		if ( sInstalledFile[0] == '/' || sInstalledFile[0] == '\\' )
134 cycrow 1208
			sInstalledFile.erase(0, 1);
51 cycrow 1209
	}
1210
 
129 cycrow 1211
	if ( !pFile->writeFilePointer() )
51 cycrow 1212
	{
213 cycrow 1213
		CLog::log(CLog::Log_Install, 1, L"Failed to write the file");
51 cycrow 1214
		if ( errorStr )
175 cycrow 1215
			errorStr->pushBack(sInstalledFile, ERRORLOG(SPKINSTALL_WRITEFILE_FAIL));
51 cycrow 1216
	}
1217
	else
1218
	{
213 cycrow 1219
		CLog::log(CLog::Log_Install, 1, L"File written successfully");
1220
		CLog::log(CLog::Log_Install, 2, L"Checking signed status of the file");
51 cycrow 1221
		pFile->UpdateSigned();
1222
		if ( errorStr )
175 cycrow 1223
			errorStr->pushBack(sInstalledFile, ERRORLOG(SPKINSTALL_WRITEFILE));
51 cycrow 1224
 
1225
		switch(pFile->GetFileType())
1226
		{
1227
			case FILETYPE_SCRIPT:
1228
			case FILETYPE_UNINSTALL:
213 cycrow 1229
				CLog::log(CLog::Log_Install, 2, L"Updating file signature");
160 cycrow 1230
				pFile->updateSignature();
51 cycrow 1231
				break;
1232
		}
1233
	}
1234
}
1235
 
197 cycrow 1236
bool CBaseFile::installFiles(const Utils::WString &destdir, CProgressInfo *progress, CLinkList<C_File> *filelist, Utils::WStringList *errorStr, bool enabled, CPackages *packages )
43 cycrow 1237
{
50 cycrow 1238
	//TODO: add errorStr and progress as member variables
43 cycrow 1239
	if ( enabled ) {
14 cycrow 1240
		this->_install_adjustFakePatches(packages);
43 cycrow 1241
		if ( packages ) this->_install_renameText(packages);
6 cycrow 1242
	}
1243
 
50 cycrow 1244
	bool bFailed = false;
1245
 
6 cycrow 1246
	CDirIO Dir(destdir);
1247
	int fileCount = 0;
1248
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
1249
	{
1250
		C_File *fit = node->Data();
1251
 
50 cycrow 1252
		// start the install process, check if we need to the file enabled or disabled
227 cycrow 1253
		CLog::logf(CLog::Log_Install, 1, L"Preparing to install file: %s", fit->getNameDirectory(this).c_str());
50 cycrow 1254
		bool fileEnabled = _install_setEnabled(enabled, fit);
1255
 
1256
		// check if the file is for the correct game version
147 cycrow 1257
		if (!fit->isForGame(packages->GetGame())) 
1258
		{
227 cycrow 1259
			CLog::logf(CLog::Log_Install, 1, L"File didn't match game version, skipping, %d != %d", fit->game(), packages->GetGame());
147 cycrow 1260
			continue;
6 cycrow 1261
		}
1262
 
50 cycrow 1263
		// update the progress display to show we are processing this file
1264
		if ( progress ) {
1265
			if ( progress->IsSecond() ) progress->SwitchSecond();
6 cycrow 1266
			progress->UpdateFile ( fit );
1267
			progress->UpdateProgress(fileCount++, m_lFiles.size());
1268
			progress->SwitchSecond();
1269
		}
1270
 
1271
		// first uncompress the file
50 cycrow 1272
		//TODO: add this flag to C_File
1273
		bool uncomprToFile;
1274
		if ( !this->_install_uncompress(fit, progress, errorStr, &uncomprToFile) ) {
1275
			bFailed = true;
1276
			continue;
6 cycrow 1277
		}
1278
 
175 cycrow 1279
		bool dofile = _install_checkVersion(fit, destdir);
6 cycrow 1280
 
1281
		// change file pointer
197 cycrow 1282
		Utils::WString sInstallDir = _install_adjustFilepointer(fit, fileEnabled, destdir);
6 cycrow 1283
 
1284
		C_File *adjustPointer = NULL;
1285
 
50 cycrow 1286
		if ( filelist ) {
98 cycrow 1287
			C_File *cFile = _install_checkFile(fit, errorStr, &dofile, filelist);
6 cycrow 1288
 
1289
			// no matching file found, adding to main list
50 cycrow 1290
			if ( !cFile ) filelist->push_back ( fit );
6 cycrow 1291
			else
1292
			{
1293
				// if the file is not enabled, we need to check for any that might be enabled
51 cycrow 1294
				if ( !fileEnabled ) //_install_checkDisabled(cFile, destdir, errorStr);
6 cycrow 1295
				{
50 cycrow 1296
					//TODO: check what this is actually doing
160 cycrow 1297
					if ( !cFile->getUsed() )
6 cycrow 1298
					{
160 cycrow 1299
						CFileIO rFile(cFile->filePointer());
52 cycrow 1300
						if ( rFile.exists() )
6 cycrow 1301
						{
1302
							if ( errorStr )
1303
							{
52 cycrow 1304
								if ( rFile.remove() )
175 cycrow 1305
									errorStr->pushBack(cFile->filePointer().findRemove(destdir), ERRORLOG(SPKINSTALL_DELETEFILE));
6 cycrow 1306
								else
175 cycrow 1307
									errorStr->pushBack(cFile->filePointer().findRemove(destdir), ERRORLOG(SPKINSTALL_DELETEFILE_FAIL));
6 cycrow 1308
							}
1309
						}
160 cycrow 1310
						cFile->setFilename(fit->filePointer());
6 cycrow 1311
						cFile->SetDisabled(true);
1312
					}
1313
					else
1314
					{
160 cycrow 1315
						fit->setFullDir(sInstallDir + fit->getDirectory(this));
51 cycrow 1316
						fit->SetDisabled(false);
6 cycrow 1317
					}
1318
				}
1319
				// move it to enabled
50 cycrow 1320
				else {
175 cycrow 1321
					if ( !this->_install_checkFileEnable(cFile, fit, destdir, fileEnabled, errorStr) ) {
50 cycrow 1322
						bFailed = true;
1323
						continue;
6 cycrow 1324
					}
1325
				}
1326
 
1327
				adjustPointer = cFile;
50 cycrow 1328
				if ( dofile ) adjustPointer->SetCreationTime(fit->GetCreationTime());
6 cycrow 1329
			}
1330
		}
1331
 
1332
		if ( dofile )
1333
		{
1334
			// uncompressed to file, rename and move
1335
			if ( uncomprToFile )
1336
			{
134 cycrow 1337
				_iLastError = SPKERR_WRITEFILE;
197 cycrow 1338
				Utils::WString to = fit->getDirectory(this);
1339
				if ( !fileEnabled )	to = L"PluginManager/Disabled/" + to;
6 cycrow 1340
 
134 cycrow 1341
				if ( !_install_createDirectory(Dir, to, fit, errorStr) ) {
51 cycrow 1342
					bFailed = true;
1343
					continue;
6 cycrow 1344
				}
1345
 
197 cycrow 1346
				bool err = true;
134 cycrow 1347
				_sLastError = to;
197 cycrow 1348
				if ( !fit->getTempFile().empty())
1349
					err = CFileIO::Rename(fit->getTempFile(), to);
51 cycrow 1350
				if ( err ) {
1351
					bFailed = true;
1352
					continue;
1353
				}
6 cycrow 1354
			}
1355
			//otherwise, just extract the file
1356
			else
1357
			{
1358
				// old file is found in list, switch to using new one
50 cycrow 1359
				if ( (filelist) && (adjustPointer) ) {
6 cycrow 1360
					adjustPointer->CopyData(fit, false);
213 cycrow 1361
					CLog::log(CLog::Log_Install, 2, L"Copying data into existing file");
50 cycrow 1362
				}
6 cycrow 1363
 
197 cycrow 1364
				Utils::WString fpointer = fit->filePointer();
134 cycrow 1365
				_iLastError = SPKERR_CREATEDIRECTORY;
211 cycrow 1366
				Utils::WString dir = CFileIO(fit->filePointer()).dir();
6 cycrow 1367
 
175 cycrow 1368
				dir = dir.findRemove(destdir);
149 cycrow 1369
				if (!dir.empty() && (dir[0] == '/' || dir[0] == '\\')) 
1370
					dir.erase(0, 1);
6 cycrow 1371
 
134 cycrow 1372
				if ( !_install_createDirectory(Dir, dir, fit, errorStr) ) {
51 cycrow 1373
					bFailed = true;
1374
					continue;
6 cycrow 1375
				}
1376
 
175 cycrow 1377
				_install_writeFile(fit, destdir, errorStr);
6 cycrow 1378
			}
1379
			ClearError ();
1380
		}
1381
 
1382
		if ( adjustPointer )
1383
		{
213 cycrow 1384
			CLog::log(CLog::Log_Install, 2, L"Adjusting pointers to existing file and deleting new file pointer");
6 cycrow 1385
			node->ChangeData(adjustPointer);
1386
			delete fit;
1387
		}
50 cycrow 1388
 
213 cycrow 1389
		CLog::log(CLog::Log_Install, 1, L"File installation completed");
6 cycrow 1390
	}
1391
 
1392
	// now clear or data memory
213 cycrow 1393
	CLog::log(CLog::Log_Install, 2, L"Delting temporary file data from memory");
51 cycrow 1394
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ) node->Data()->DeleteData();
6 cycrow 1395
 
50 cycrow 1396
	return !bFailed;
6 cycrow 1397
}
1398
 
1399
/*######################################################################################################*/
1400
 
1401
 
1402
/*
1403
	Func:   ParseHeader
1404
	Input:  Header String - string formated directly from the file
1405
	Return: Boolean - If string is a valid header
1406
	Desc:   Splits up the main header string to get all required settings
1407
*/
210 cycrow 1408
bool CBaseFile::_parseHeader(const Utils::WString &header)
6 cycrow 1409
{
210 cycrow 1410
	if ( !this->_checkHeader(header.token(L";", 1)))
6 cycrow 1411
		return false;
1412
 
210 cycrow 1413
	m_SHeader.fVersion = header.token(L";", 2).toFloat();
6 cycrow 1414
	if ( m_SHeader.fVersion > FILEVERSION )
1415
		return false;
1416
 
210 cycrow 1417
	m_SHeader.iValueCompression = header.token(L";", 3).toInt();
1418
	m_SHeader.lValueCompressSize = header.token(L";", 4).toLong();
6 cycrow 1419
 
1420
	return true;
1421
}
1422
 
210 cycrow 1423
bool CBaseFile::_checkHeader(const Utils::WString &header) const
6 cycrow 1424
{
210 cycrow 1425
	if ( header.Compare(L"BaseCycrow") )
6 cycrow 1426
		return true;
1427
	return false;
1428
}
1429
 
1430
/*
1431
	Func:   ParseFileHeader
1432
	Input:  Header String - string formated directly from the file
1433
	Return: Boolean - If string is a valid header
1434
	Desc:   Splits up the file header string to get all required settings
1435
*/
210 cycrow 1436
bool CBaseFile::_parseFileHeader(const Utils::WString &header)
6 cycrow 1437
{
210 cycrow 1438
	if (header.token(L";", 1) != L"FileHeader")
6 cycrow 1439
		return false;
1440
 
210 cycrow 1441
	m_SHeader2.iNumFiles = header.token(L";", 2).toInt();
1442
	m_SHeader2.lSize = header.token(L";", 3).toInt();
1443
	m_SHeader2.lFullSize = header.token(L";", 4).toInt();
1444
	m_SHeader2.iFileCompression = header.token(L";", 5).toInt();
1445
	m_SHeader2.iDataCompression = header.token(L";", 6).toInt();
6 cycrow 1446
 
1447
	return true;
1448
}
1449
 
1450
 
1451
/*
1452
	Func:   ParseValueLine
1453
	Input:  String - single line from a file to set
1454
	Return: Boolean - returns true if value exists
1455
	Desc:   Reads the line and assigns the parameters for the file
1456
*/
207 cycrow 1457
bool CBaseFile::parseValueLine(const Utils::WString &sLine)
6 cycrow 1458
{
207 cycrow 1459
	Utils::WString first = sLine.token(L" ", 1);
1460
	Utils::WString rest  = sLine.tokens(L" ", 2);
6 cycrow 1461
 
207 cycrow 1462
	if ( first.Compare(L"Name:") )					this->setName(rest);
1463
	else if ( first.Compare(L"Author:") )			this->setAuthor(rest);
1464
	else if ( first.Compare(L"Version:") )			this->setVersion(rest);
1465
	else if ( first.Compare(L"fGameVersion:") ) {
6 cycrow 1466
		if ( m_lGames.Back() ) {
207 cycrow 1467
			m_lGames.Back()->Data()->sVersion = rest;
6 cycrow 1468
		}
1469
	}
207 cycrow 1470
	else if ( first.Compare(L"GameVersion:") ) {
6 cycrow 1471
		if ( m_lGames.Back() ) {
197 cycrow 1472
			m_lGames.Back()->Data()->iVersion = rest.toInt();
6 cycrow 1473
		}
1474
	}
207 cycrow 1475
	else if ( first.Compare(L"Game:") )
1476
		this->AddGameCompatability(rest, L"");
1477
	else if ( first.Compare(L"GameCompat:") )
211 cycrow 1478
		this->AddGameCompatability(rest.token(L" ", 1), rest.tokens(L" ", 2));
207 cycrow 1479
	else if ( first.Compare(L"GameCompatExact:") )
211 cycrow 1480
		this->AddGameCompatability(rest.token(L" ", 1), rest.tokens(L" ", 2));
207 cycrow 1481
	else if ( first.Compare(L"Date:") )				this->setCreationDate(rest);
1482
	else if ( first.Compare(L"WebAddress:") )		this->setWebAddress(rest);
1483
	else if ( first.Compare(L"WebSite:") )			this->setWebSite(rest);
1484
	else if ( first.Compare(L"Email:") )				this->setEmail(rest);
1485
	else if ( first.Compare(L"WebMirror1:") || first.Compare(L"Mirror1:") || first.Compare(L"WebMirror:") )
211 cycrow 1486
		this->addWebMirror(rest);
207 cycrow 1487
	else if ( first.Compare(L"WebMirror2:") || first.Compare(L"Mirror2:") )
211 cycrow 1488
		this->addWebMirror(rest);
207 cycrow 1489
	else if ( first.Compare(L"PluginType:") )		this->setPluginType(rest);
1490
	else if ( first.Compare(L"Desc:") )				this->setDescription(rest);
1491
	else if ( first.Compare(L"UninstallAfter:") )	this->addUninstallText(parseLanguage(rest.token(L"|", 1)), false, rest.tokens(L"|", 2));
1492
	else if ( first.Compare(L"UninstallBefore:") )	this->addUninstallText(parseLanguage(rest.token(L"|", 1)), true, rest.tokens(L"|", 2));
1493
	else if ( first.Compare(L"InstallAfter:") )		this->addInstallText(parseLanguage(rest.token(L"|", 1)), false, rest.tokens(L"|", 2));
1494
	else if ( first.Compare(L"InstallBefore:") )	this->addInstallText(parseLanguage(rest.token(L"|", 1)), true, rest.tokens(L"|", 2));
1495
	else if ( first.Compare(L"ScriptName:") )		addName(parseLanguage(rest.token(L":", 1)), rest.token(L":", 2));
1496
	else if ( first.Compare(L"GameChanging:") )		this->setGameChanging(rest);
1497
	else if ( first.Compare(L"EaseOfUse:") )		this->setEaseOfUse(rest);
1498
	else if ( first.Compare(L"Recommended:") )		this->setRecommended(rest);
1499
	else if ( first.Compare(L"NeededLibrary:") )
1500
		this->addNeededLibrary(rest.token(L"||", 1), rest.token(L"||", 2), rest.token(L"||", 3));
1501
	else if ( first.Compare(L"FakePatchBefore:") )
1502
		this->addFakePatchOrder(false, rest.token(L"||", 1), rest.token(L"||", 2));
234 cycrow 1503
	else if (first.Compare(L"FakePatchAfter:"))
207 cycrow 1504
		this->addFakePatchOrder(true, rest.token(L"||", 1), rest.token(L"||", 2));
234 cycrow 1505
	else if (first.Compare(L"Globals:"))
1506
		this->addGlobal(rest.token(L";", 1), rest.tokens(L";", 2));
207 cycrow 1507
	else if ( first.Compare(L"ForumLink:") )			this->setForumLink(rest);
6 cycrow 1508
	else
1509
		return false;
1510
 
1511
	return true;
1512
}
1513
 
207 cycrow 1514
int CBaseFile::parseLanguage(const Utils::WString &lang) const
6 cycrow 1515
{
48 cycrow 1516
	int langID = lang;
1517
	if ( !langID ) {
207 cycrow 1518
		if (lang.Compare(L"english"))		return 44;
1519
		else if (lang.Compare(L"default"))	return 0;
1520
		else if (lang.Compare(L"german"))	return 49;
1521
		else if (lang.Compare(L"russian"))	return 7;
1522
		else if (lang.Compare(L"spanish"))	return 34;
1523
		else if (lang.Compare(L"french"))	return 33;
6 cycrow 1524
	}
1525
 
1526
	return langID;
1527
}
1528
 
1529
/*
1530
	Func:   ReadValues
1531
	Input:  String - values in one long line
1532
	Desc:   splits the values data into each line to read the data
1533
*/
207 cycrow 1534
void CBaseFile::_readValues(const Utils::WString &values)
6 cycrow 1535
{
207 cycrow 1536
	std::vector<Utils::WString> lines;
1537
	values.tokenise(L"\n", lines);
6 cycrow 1538
 
207 cycrow 1539
	for (size_t i = 0; i < lines.size(); i++)
1540
		parseValueLine(lines[i]);
6 cycrow 1541
}
1542
 
1543
/*
1544
	Func:   ParseFilesLine
1545
	Input:  String - single line from a file to set
1546
	Return: Boolean - returns true if value exists
1547
	Desc:   Reads the line and assigns the parameters for the file
1548
*/
210 cycrow 1549
bool CBaseFile::_parseFilesLine(const Utils::WString &line)
6 cycrow 1550
{
210 cycrow 1551
	if ( !line.contains(L":") )
6 cycrow 1552
		return false;
1553
 
210 cycrow 1554
	Utils::WString command = line.token(L":", 1);
6 cycrow 1555
 
210 cycrow 1556
	long size = line.token(L":", 2).toInt();
1557
	long usize = line.token(L":", 3).toInt ();
1558
	long compression = line.token(L":", 4).toInt ();
6 cycrow 1559
 
210 cycrow 1560
	if ( command == L"Icon" )
6 cycrow 1561
	{
210 cycrow 1562
		_sIconExt = line.token(L":", 5);
6 cycrow 1563
		m_pIconFile = new C_File ();
1564
		m_pIconFile->SetDataSize ( size - 4 );
1565
		m_pIconFile->SetDataCompression ( compression );
1566
		m_pIconFile->SetUncompressedDataSize ( usize );
1567
 
1568
		return true;
1569
	}
1570
 
210 cycrow 1571
	time_t time = line.token(L":", 5).toLong();
1572
	bool compressToFile = (line.token(L":", 6).toInt() == 1) ? true : false;
1573
	Utils::WString name  = line.token(L":", 7);
1574
	Utils::WString dir = line.token(L":", 8);
6 cycrow 1575
 
127 cycrow 1576
	if ( name.empty() )
6 cycrow 1577
		return true;
1578
 
1579
	bool shared = false;
210 cycrow 1580
	if ( command.left(1) == L"$" )
6 cycrow 1581
	{
1582
		shared = true;
127 cycrow 1583
		command.erase(0, 1);
6 cycrow 1584
	}
1585
 
127 cycrow 1586
	FileType type = FILETYPE_UNKNOWN;
210 cycrow 1587
	if ( command == L"Script" )
6 cycrow 1588
		type = FILETYPE_SCRIPT;
210 cycrow 1589
	else if ( command == L"Text" )
6 cycrow 1590
		type = FILETYPE_TEXT;
210 cycrow 1591
	else if ( command == L"Readme" )
6 cycrow 1592
		type = FILETYPE_README;
210 cycrow 1593
	else if ( command == L"Map" )
6 cycrow 1594
		type = FILETYPE_MAP;
210 cycrow 1595
	else if ( command == L"Mod" )
6 cycrow 1596
		type = FILETYPE_MOD;
210 cycrow 1597
	else if ( command == L"Uninstall" )
6 cycrow 1598
		type = FILETYPE_UNINSTALL;
210 cycrow 1599
	else if ( command == L"Sound" )
6 cycrow 1600
		type = FILETYPE_SOUND;
210 cycrow 1601
	else if ( command == L"Mission" )
6 cycrow 1602
		type = FILETYPE_MISSION;
210 cycrow 1603
	else if ( command == L"Extra" )
6 cycrow 1604
		type = FILETYPE_EXTRA;
210 cycrow 1605
	else if ( command == L"Screen" )
6 cycrow 1606
		type = FILETYPE_SCREEN;
210 cycrow 1607
	else if ( command == L"Backup" )
6 cycrow 1608
		type = FILETYPE_BACKUP;
210 cycrow 1609
	else if ( command == L"Advert" )
6 cycrow 1610
		type = FILETYPE_ADVERT;
210 cycrow 1611
	else if ( command == L"ShipScene" )
6 cycrow 1612
		type = FILETYPE_SHIPSCENE;
210 cycrow 1613
	else if ( command == L"CockpitScene" )
6 cycrow 1614
		type = FILETYPE_COCKPITSCENE;
210 cycrow 1615
	else if ( command == L"ShipOther" )
6 cycrow 1616
		type = FILETYPE_SHIPOTHER;
210 cycrow 1617
	else if ( command == L"ShipModel" )
6 cycrow 1618
		type = FILETYPE_SHIPMODEL;
1619
 
127 cycrow 1620
	if (type == FILETYPE_UNKNOWN)
6 cycrow 1621
		return false;
1622
 
127 cycrow 1623
	C_File *file = new C_File();
6 cycrow 1624
 
210 cycrow 1625
	if (dir.left(5).Compare(L"GAME_")) {
1626
		unsigned int iGame = dir.token(L"_", 2).toInt();
130 cycrow 1627
		if (!iGame)
1628
			file->setGame(0);
1629
		else
1630
			file->setGame(1 << 31 | 1 << iGame);
210 cycrow 1631
		dir = Utils::WString::Null();
6 cycrow 1632
	} 
210 cycrow 1633
	else if ( line.countToken(L":") >= 9 ) 
127 cycrow 1634
	{
210 cycrow 1635
		Utils::WString game = line.token(L":", 9);
1636
		if (game.contains(L"_"))
130 cycrow 1637
		{
210 cycrow 1638
			unsigned int iGame = game.token(L"_", 2).toInt();
130 cycrow 1639
			if (iGame)
1640
				file->setGame(1 << 31 | 1 << iGame);
1641
			else
1642
				file->setGame(0);
1643
		}
127 cycrow 1644
		else
1645
		{
1646
			int iGame = game.toInt();
1647
			if (iGame & (1 << 31))
1648
				file->setGame(iGame);
130 cycrow 1649
			else if (!iGame)
1650
				file->setGame(0);
127 cycrow 1651
			else
1652
				file->setGame(1 << 31 | 1 << iGame);
1653
		}
6 cycrow 1654
	}
1655
 
210 cycrow 1656
	if (dir.Compare(L"NULL")) {
1657
		dir = Utils::WString::Null();
127 cycrow 1658
	}
1659
 
1660
	file->setFileType(type);
6 cycrow 1661
	file->SetCreationTime ( time );
178 cycrow 1662
	file->setName(name);
1663
	file->setDir(dir);
6 cycrow 1664
	file->SetDataSize ( size - 4 );
1665
	file->SetDataCompression ( compression );
1666
	file->SetUncompressedDataSize ( usize );
1667
	file->SetShared ( shared );
1668
	file->SetCompressedToFile ( compressToFile );
1669
 
88 cycrow 1670
	_addFile(file, true);
6 cycrow 1671
 
1672
	return true;
1673
}
1674
 
1675
 
1676
/*
1677
	Func:   ParseFiles
1678
	Input:  String - values in one long line
1679
	Desc:   splits the files data into each line to read the data
1680
*/
211 cycrow 1681
void CBaseFile::_readFiles(const Utils::WString &values)
6 cycrow 1682
{
211 cycrow 1683
	std::vector<Utils::WString> lines;
1684
	values.tokenise(L"\n", lines);
6 cycrow 1685
 
211 cycrow 1686
	for (size_t i = 0; i < lines.size(); i++)
175 cycrow 1687
		_parseFilesLine(lines[i]);
6 cycrow 1688
}
1689
 
1690
 
1691
 
1692
/*
1693
	Func:   ReadFile
1694
	Input:  filename - the name of the file to open and read
1695
			readdata - If falses, dont read the files to memory, just read the headers and values
1696
	Return: boolean - return ture if acceptable format
1697
	Desc:   Opens and reads the spk file and loads all data into class
1698
*/
210 cycrow 1699
bool CBaseFile::readFile(const Utils::WString &filename, int readtype, CProgressInfo *progress)
130 cycrow 1700
{
1701
	CFileIO File(filename);
58 cycrow 1702
	if ( !File.startRead() ) return false;
6 cycrow 1703
 
58 cycrow 1704
	bool ret = this->readFile(File, readtype, progress);
130 cycrow 1705
	if ( ret ) this->setFilename(filename);
6 cycrow 1706
 
58 cycrow 1707
	File.close();
6 cycrow 1708
	return ret;
1709
}
51 cycrow 1710
 
109 cycrow 1711
int CBaseFile::_read_Header(CFileIO &File, int iReadType, int iMaxProgress, CProgressInfo *pProgress)
6 cycrow 1712
{
51 cycrow 1713
	int doneLen = 0;
6 cycrow 1714
 
51 cycrow 1715
	// read data to memory
208 cycrow 1716
	unsigned char *readData = 0;
51 cycrow 1717
	try {
1718
		readData = new unsigned char[m_SHeader.lValueCompressSize];
1719
	}
1720
	catch (std::exception &e) {
227 cycrow 1721
		CLog::logf(CLog::Log_IO, 2, L"CBaseFile::_read_Header() unable to malloc [header], %d (%hs)", m_SHeader.lValueCompressSize, e.what());
51 cycrow 1722
		return -1;
1723
	}
6 cycrow 1724
 
208 cycrow 1725
	if (!readData)
1726
		return -1;
1727
 
51 cycrow 1728
	unsigned char size[4];
109 cycrow 1729
	File.read(size, 4);
1730
	File.read(readData, m_SHeader.lValueCompressSize);
6 cycrow 1731
 
51 cycrow 1732
	unsigned long uncomprLen = (size[0] << 24) + (size[1] << 16) + (size[2] << 8) + size[3];
6 cycrow 1733
 
51 cycrow 1734
	// check for zlib compression
1735
	if ( m_SHeader.iValueCompression == SPKCOMPRESS_ZLIB ) {
1736
		// uncomress the data
1737
		try {
6 cycrow 1738
			unsigned char *uncompr = new unsigned char[uncomprLen];
1739
			int err = uncompress ( uncompr, &uncomprLen, readData, m_SHeader.lValueCompressSize );
1740
			// update the progress for each section
51 cycrow 1741
			if ( iReadType != SPKREAD_ALL && pProgress ) pProgress->UpdateProgress(2, iMaxProgress);
208 cycrow 1742
			if (err == Z_OK) 
1743
			{
211 cycrow 1744
				if (m_SHeader.fVersion < 4.4f)
209 cycrow 1745
				{
1746
					std::string data((const char*)uncompr);
1747
					_readValues(std::wstring(data.begin(), data.end()));
1748
				}
1749
				else
1750
				{
1751
					const wchar_t* data = (const wchar_t*)uncompr;
1752
					_readValues(Utils::WString(data));
1753
				}
208 cycrow 1754
			}
6 cycrow 1755
			doneLen = uncomprLen;
208 cycrow 1756
			delete []uncompr;
6 cycrow 1757
		}
51 cycrow 1758
		catch (std::exception &e) {
227 cycrow 1759
			CLog::logf(CLog::Log_IO, 2, L"CBaseFile::_read_Header() unable to malloc [uncompr], %d (%hs)", uncomprLen, e.what());
53 cycrow 1760
			delete []readData;
51 cycrow 1761
			return -1;
6 cycrow 1762
		}
51 cycrow 1763
	}
1764
	else if ( m_SHeader.iValueCompression == SPKCOMPRESS_7ZIP ) {
1765
		long len = uncomprLen;
1766
		unsigned char *compr = LZMADecode_C ( readData, m_SHeader.lValueCompressSize, (size_t*)&len, NULL );
1767
		// update the progress for each section
1768
		if ( iReadType != SPKREAD_ALL && pProgress ) pProgress->UpdateProgress(2, iMaxProgress);
6 cycrow 1769
 
208 cycrow 1770
		if (compr) 
1771
		{
211 cycrow 1772
			if (m_SHeader.fVersion <= 4.4f)
209 cycrow 1773
			{
1774
				std::string data((const char*)compr);
1775
				_readValues(std::wstring(data.begin(), data.end()));
1776
			}
1777
			else
1778
			{
1779
				const wchar_t* data = (const wchar_t*)compr;
1780
				_readValues(Utils::WString(data));
1781
			}
208 cycrow 1782
		}
6 cycrow 1783
	}
51 cycrow 1784
	// no compression
1785
	else
208 cycrow 1786
	{
211 cycrow 1787
		if (m_SHeader.fVersion <= 4.4f)
209 cycrow 1788
		{
1789
			std::string data((const char*)readData);
1790
			_readValues(std::wstring(data.begin(), data.end()));
1791
		}
1792
		else
1793
		{
1794
			const wchar_t* data = (const wchar_t*)readData;
1795
			_readValues(Utils::WString(data));
1796
		}
208 cycrow 1797
	}
6 cycrow 1798
 
53 cycrow 1799
	delete []readData;
6 cycrow 1800
 
51 cycrow 1801
	return doneLen;
1802
}
6 cycrow 1803
 
109 cycrow 1804
int CBaseFile::_read_FileHeader(CFileIO &File, int iReadType, int iMaxProgress, int iDoneLen, CProgressInfo *pProgress)
51 cycrow 1805
{
1806
	unsigned char *readData;
1807
	try {
1808
		readData = new unsigned char[m_SHeader2.lSize];
1809
	}
1810
	catch (std::exception &e) {
227 cycrow 1811
		CLog::logf(CLog::Log_IO, 2, L"CBaseFile::_read_FileHeader() unable to malloc [header], %d (%hs)", m_SHeader2.lSize, e.what());
51 cycrow 1812
		return -1;
1813
	}
6 cycrow 1814
 
51 cycrow 1815
	unsigned char size[4];
109 cycrow 1816
	File.read(size, 4);
1817
	File.read(readData, m_SHeader2.lSize);
6 cycrow 1818
 
51 cycrow 1819
	unsigned long uncomprLen = (size[0] << 24) + (size[1] << 16) + (size[2] << 8) + size[3];
6 cycrow 1820
 
51 cycrow 1821
	// check for zlib compression
1822
	if ( m_SHeader.iValueCompression == SPKCOMPRESS_ZLIB ) {
1823
		if ( uncomprLen < (unsigned long)iDoneLen ) uncomprLen = iDoneLen;
6 cycrow 1824
 
51 cycrow 1825
		try {
6 cycrow 1826
			unsigned char *uncompr = new unsigned char[uncomprLen];
1827
			int err = uncompress ( uncompr, &uncomprLen, readData, m_SHeader2.lSize );
1828
			// update the progress for each section
51 cycrow 1829
			if ( iReadType != SPKREAD_ALL && pProgress ) pProgress->UpdateProgress(5, iMaxProgress);
211 cycrow 1830
			if (err == Z_OK)
1831
			{
1832
//#pragma warning(disable:4244)
1833
				if (m_SHeader.fVersion < 4.4f)
1834
				{
1835
					std::string data((char*)uncompr);
1836
					_readFiles(std::wstring(data.begin(), data.end()));
1837
				}
1838
				else
1839
				{
1840
					std::wstring data((wchar_t*)uncompr);
1841
					_readFiles(data);
1842
				}
1843
//#pragma warning(enable:4244)
1844
			}
1845
			delete[] uncompr;
6 cycrow 1846
		}
51 cycrow 1847
		catch (std::exception &e) {
227 cycrow 1848
			CLog::logf(CLog::Log_IO, 2, L"CBaseFile::_read_FileHeader() unable to malloc [uncompr], %d (%hs)", uncomprLen, e.what());
53 cycrow 1849
			delete []readData;
51 cycrow 1850
			return -1;
6 cycrow 1851
		}
1852
 
1853
	}
51 cycrow 1854
	else if ( m_SHeader.iValueCompression == SPKCOMPRESS_7ZIP )
1855
	{
1856
		long len = uncomprLen;
1857
		unsigned char *compr = LZMADecode_C ( readData, m_SHeader2.lSize, (size_t*)&len, NULL );
1858
		// update the progress for each section
1859
		if ( iReadType != SPKREAD_ALL && pProgress ) pProgress->UpdateProgress(5, iMaxProgress);
213 cycrow 1860
		if (compr) 
1861
		{
1862
			if (m_SHeader.fVersion < 4.4f)
1863
			{
1864
				std::string data((char*)compr);
1865
				_readFiles(std::wstring(data.begin(), data.end()));
1866
			}
1867
			else
1868
			{
1869
				std::wstring data((wchar_t*)compr);
1870
				_readFiles(data);
1871
			}
1872
		}
51 cycrow 1873
	}
1874
	else
213 cycrow 1875
	{
1876
		if (m_SHeader.fVersion < 4.4f)
1877
		{
1878
			std::string data((char*)readData);
1879
			_readFiles(std::wstring(data.begin(), data.end()));
1880
		}
1881
		else
1882
		{
1883
			std::wstring data((wchar_t*)readData);
1884
			_readFiles(data);
1885
		}
1886
	}
6 cycrow 1887
 
53 cycrow 1888
	delete []readData;
51 cycrow 1889
	return true;
1890
}
1891
 
58 cycrow 1892
bool CBaseFile::readFile(CFileIO &File, int readtype, CProgressInfo *progress)
51 cycrow 1893
{
1894
	ClearError ();
1895
 
1896
	// first read the header
197 cycrow 1897
	if ( !_parseHeader(File.readEndOfLineStr()) ) return false;
51 cycrow 1898
	if ( readtype == SPKREAD_HEADER ) return true;
1899
 
1900
	// update the progress for each section
1901
	int maxProgress = (readtype == SPKREAD_VALUES) ? 3 : 6;
1902
	if ( readtype != SPKREAD_ALL && progress ) progress->UpdateProgress(1, maxProgress);
1903
 
1904
	long doneLen = 0;
1905
	// next read the data values for the spk files
109 cycrow 1906
	if ( m_SHeader.lValueCompressSize ) doneLen = this->_read_Header(File, readtype, maxProgress, progress);
51 cycrow 1907
 
1908
	// update the progress for each section
1909
	if ( readtype != SPKREAD_ALL && progress ) progress->UpdateProgress(3, maxProgress);
1910
	if ( readtype == SPKREAD_VALUES ) return true;
1911
 
1912
	// next should be the next header
197 cycrow 1913
	if ( !_parseFileHeader(File.readEndOfLineStr()) ) return false;
51 cycrow 1914
 
1915
	// clear the current file list
1916
	m_lFiles.clear(true);
88 cycrow 1917
	if ( _pTextDB ) {
1918
		delete _pTextDB;
1919
		_pTextDB = NULL;
1920
	}
51 cycrow 1921
 
1922
	// update the progress for each section
1923
	if ( readtype != SPKREAD_ALL && progress ) progress->UpdateProgress(4, maxProgress);
1924
 
109 cycrow 1925
	if ( m_SHeader2.lSize ) this->_read_FileHeader(File, readtype, maxProgress, doneLen, progress);
51 cycrow 1926
 
6 cycrow 1927
	// file mismatch
1928
	long numfiles = m_lFiles.size();
51 cycrow 1929
	if ( m_pIconFile ) ++numfiles;
1930
	if ( m_SHeader2.iNumFiles != numfiles ) {
134 cycrow 1931
		_iLastError = SPKERR_FILEMISMATCH;
6 cycrow 1932
		return false;
1933
	}
1934
 
1935
	// update the progress for each section
51 cycrow 1936
	if ( readtype != SPKREAD_ALL && progress )	progress->UpdateProgress(6, maxProgress);
6 cycrow 1937
 
51 cycrow 1938
	if ( readtype == SPKREAD_ALL ) {
6 cycrow 1939
		int fileCount = 2;
58 cycrow 1940
		if ( m_pIconFile ) m_pIconFile->readFromFile(File, m_pIconFile->GetDataSize());
6 cycrow 1941
 
51 cycrow 1942
		// ok finally we need to read all the file
1943
		for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ) {
58 cycrow 1944
			node->Data()->readFromFile(File, node->Data()->GetDataSize());
51 cycrow 1945
			if ( progress )	progress->UpdateProgress(fileCount++, m_lFiles.size() + 2);
6 cycrow 1946
		}
1947
 
1948
		m_bFullyLoaded = true;
1949
	}
1950
 
1951
	return true;
1952
}
1953
 
1954
bool CBaseFile::IsMod()
1955
{
1956
	// check for any mod files that are not fake patchs
1957
	for ( CListNode<C_File> *fNode = m_lFiles.Front(); fNode; fNode = fNode->next() )
1958
	{
1959
		C_File *f = fNode->Data();
1960
		if ( f->GetFileType() != FILETYPE_MOD )
1961
			continue;
1962
 
1963
		if ( !f->IsFakePatch() )
1964
			return true;
1965
	}
1966
 
1967
	return false;
1968
}
1969
 
13 cycrow 1970
bool CBaseFile::IsFakePatch() const
6 cycrow 1971
{
1972
	// check for any mod files that are not fake patchs
1973
	for ( CListNode<C_File> *fNode = m_lFiles.Front(); fNode; fNode = fNode->next() )
1974
	{
1975
		C_File *f = fNode->Data();
1976
		if ( f->GetFileType() != FILETYPE_MOD )
1977
			continue;
1978
 
1979
		if ( f->IsFakePatch() )
1980
			return true;
1981
	}
1982
 
1983
	return false;
1984
}
1985
 
207 cycrow 1986
Utils::WString CBaseFile::createValuesLine () const
6 cycrow 1987
{
203 cycrow 1988
	Utils::WString values(L"Name: ");
1989
	values += this->name() + L"\n";
1990
	values += L"Author: " + this->author() + L"\n";
204 cycrow 1991
	values += L"Version: " + this->version() + L"\n";
206 cycrow 1992
	if ( !this->creationDate().empty() )values += L"Date: "			+ this->creationDate()	+ L"\n";
1993
	if ( !this->webAddress().empty() )	values += L"WebAddress: "	+ this->webAddress()	+ L"\n";
1994
	if ( !this->webSite().empty() )		values += L"WebSite: "		+ this->webSite()		+ L"\n";
1995
	if ( !this->email().empty() )		values += L"Email: "		+ this->email()			+ L"\n";
1996
	if ( !this->forumLink().empty() )	values += L"ForumLink: "	+ this->forumLink()		+ L"\n";
49 cycrow 1997
 
208 cycrow 1998
	for(auto itr = webMirrors().begin(); itr != webMirrors().end(); itr++)
1999
		values += Utils::WString(L"WebMirror: ") + (*itr)->str + L"\n";
48 cycrow 2000
	if ( !this->description().empty() ) {
206 cycrow 2001
		Utils::WString desc = this->description();
203 cycrow 2002
		desc = desc.findReplace(L"<newline>", L"<br>");
213 cycrow 2003
		desc = desc.findReplace(L"\n", L"<br>");
203 cycrow 2004
		desc.remove(L'\r');
2005
		values += L"Desc: " + desc + L"\n";
6 cycrow 2006
	}
2007
 
2008
	for ( CListNode<SGameCompat> *gc = m_lGames.Front(); gc; gc = gc->next() ) {
46 cycrow 2009
		if ( !gc->Data()->sVersion.empty() )
203 cycrow 2010
			values += Utils::WString(L"GameCompatExact: ") + (long)gc->Data()->iGame + L" " + gc->Data()->sVersion + L"\n";
6 cycrow 2011
		else
203 cycrow 2012
			values += Utils::WString(L"GameCompat: ") + (long)gc->Data()->iGame + L" " + (long)gc->Data()->iVersion + L"\n";
6 cycrow 2013
	}
2014
 
175 cycrow 2015
	if (computeSigned(true))
203 cycrow 2016
		values += L"Signed\n";
6 cycrow 2017
 
46 cycrow 2018
	for ( int j = 0; j < 2; j++ ) {
2019
		const CInstallText *text;
203 cycrow 2020
		Utils::WString textStart;
46 cycrow 2021
		switch(j) {
203 cycrow 2022
			case 0:	textStart = L"Uninstall"; text = this->uninstallText(); break;
2023
			case 1: textStart = L"Install"; text = this->installText(); break;
46 cycrow 2024
		}
2025
		for ( unsigned int i = 0; i < text->count(); i++ ) {
2026
			int iLang = text->language(i);
206 cycrow 2027
			if ( !text->getBefore(iLang).empty() ) values += textStart + L"Before: " + (long)iLang + L"|" + text->getBefore(iLang) + L"\n";
2028
			if ( !text->getAfter(iLang).empty() ) values += textStart + L"After: " + (long)iLang + L"|" + text->getAfter(iLang) + L"\n";
46 cycrow 2029
		}
6 cycrow 2030
	}
2031
 
203 cycrow 2032
	values += Utils::WString(L"GameChanging: ") + (long)gameChanging() + L"\n";
2033
	values += Utils::WString(L"EaseOfUse: ") + (long)easeOfUse() + L"\n";
2034
	values += Utils::WString(L"Recommended: ") + (long)recommended() + L"\n";
6 cycrow 2035
 
170 cycrow 2036
	for(auto itr = namesList()->begin(); itr != namesList()->end(); itr++)
204 cycrow 2037
		values += Utils::WString(L"ScriptName: ") + (long)(*itr)->iLanguage + L":" + (*itr)->sName + L"\n";
6 cycrow 2038
 
14 cycrow 2039
	for ( CListNode<SNeededLibrary> *libNode = m_lNeededLibrarys.Front(); libNode; libNode = libNode->next() ) {
6 cycrow 2040
		SNeededLibrary *l = libNode->Data();
204 cycrow 2041
		values += L"NeededLibrary: " + l->sName + L"||" + l->sAuthor + L"||" + l->sMinVersion + L"\n";
6 cycrow 2042
	}
2043
 
160 cycrow 2044
	for (auto itr = _lFakePatchBefore.begin(); itr != _lFakePatchBefore.end(); itr++)
207 cycrow 2045
		values += L"FakePatchBefore: " + (*itr)->str + L"||" + (*itr)->data + L"\n";
160 cycrow 2046
	for (auto itr = _lFakePatchAfter.begin(); itr != _lFakePatchAfter.end(); itr++)
207 cycrow 2047
		values += L"FakePatchAfter: " + (*itr)->str + L"||" + (*itr)->data + L"\n";
6 cycrow 2048
 
203 cycrow 2049
	values += Utils::WString(L"PluginType: ") + (long)this->pluginType() + L"\n";
6 cycrow 2050
 
234 cycrow 2051
	for (auto itr = _lGlobals.begin(); itr != _lGlobals.end(); itr++)
2052
		values += L"Globals: " + (*itr)->str + L";" + (*itr)->data + L"\n";
2053
 
207 cycrow 2054
	return values;
6 cycrow 2055
}
2056
 
2057
 
2058
/*
2059
	Func:   WriteFile
2060
	Input:  filename - The filename of the spk file to write to
2061
	Desc:   Writes the data to an spk file
2062
*/
210 cycrow 2063
bool CBaseFile::writeFile(const Utils::WString &filename, CProgressInfo *progress) const
6 cycrow 2064
{
52 cycrow 2065
	CFileIO File(filename);
175 cycrow 2066
	if ( File.startWrite() ) return writeData(File, progress);
52 cycrow 2067
	return false;
6 cycrow 2068
}
2069
 
175 cycrow 2070
bool CBaseFile::writeHeader(CFileIO &file, int valueheader, int valueComprLen) const
6 cycrow 2071
{
52 cycrow 2072
	return file.write("BaseCycrow;%.2f;%d;%d\n", FILEVERSION, valueheader, valueComprLen);
6 cycrow 2073
}
2074
 
175 cycrow 2075
bool CBaseFile::writeData(CFileIO &file, CProgressInfo *progress ) const
6 cycrow 2076
{
2077
	int valueheader = m_SHeader.iValueCompression, fileheader = m_SHeader.iValueCompression;
2078
	if ( valueheader == SPKCOMPRESS_7ZIP )
2079
		valueheader = SPKCOMPRESS_ZLIB;
2080
	if ( fileheader == SPKCOMPRESS_7ZIP )
2081
		fileheader = SPKCOMPRESS_ZLIB;
2082
 
2083
	// get the script values
207 cycrow 2084
	Utils::WString values = this->createValuesLine();
209 cycrow 2085
	const char* data = (const char*)values.c_str();
6 cycrow 2086
 
2087
	// compress the values
209 cycrow 2088
	int valueUncomprLen = (int)(wcslen(values.c_str()) * sizeof(wchar_t)) / sizeof(char);
6 cycrow 2089
	unsigned long valueComprLen = 0;
2090
	unsigned char *valueCompr = NULL;
2091
	bool compressed = false;
208 cycrow 2092
 
6 cycrow 2093
	if ( valueheader == SPKCOMPRESS_ZLIB )
2094
	{
2095
		valueComprLen = valueUncomprLen;
2096
		if ( valueComprLen < 100 )
2097
			valueComprLen = 200;
2098
		else if ( valueComprLen < 1000 )
2099
			valueComprLen *= 2;
2100
 
2101
		valueCompr = (unsigned char *)calloc((unsigned int)valueComprLen, 1);
209 cycrow 2102
		int err = compress ( (unsigned char *)valueCompr, &valueComprLen, (const unsigned char *)data, (unsigned long)valueUncomprLen, 0 );
6 cycrow 2103
		if ( err == Z_OK )
2104
			compressed = true;
2105
	}
2106
 
2107
	if ( !compressed )
2108
	{
2109
		valueComprLen = valueUncomprLen;
2110
		valueCompr = (unsigned char *)calloc((unsigned int)valueComprLen, 1);
209 cycrow 2111
		memcpy ( valueCompr, (const unsigned char *)data, valueComprLen );
6 cycrow 2112
		valueheader = SPKCOMPRESS_NONE;
2113
	}
2114
 
2115
	// write the main header to the file
175 cycrow 2116
	if ( !this->writeHeader(file, valueheader, valueComprLen) )	return false;
6 cycrow 2117
 
2118
	// write the compressed data to file
52 cycrow 2119
	file.put(static_cast<unsigned char>(valueUncomprLen >> 24));
2120
	file.put(static_cast<unsigned char>(valueUncomprLen >> 16));
2121
	file.put(static_cast<unsigned char>(valueUncomprLen >> 8));
2122
	file.put(static_cast<unsigned char>(valueUncomprLen));
2123
	file.write(valueCompr, valueComprLen);
6 cycrow 2124
	free ( valueCompr );
2125
 
2126
	// now compress the files header
2127
	// create the files values
175 cycrow 2128
	SSPKHeader2 header;
211 cycrow 2129
	Utils::WString files = createFilesLine(&header, progress);
175 cycrow 2130
 
6 cycrow 2131
	// compress the files values
211 cycrow 2132
	long fileUncomprLen = (long)((wcslen(files.c_str()) * sizeof(wchar_t)) / sizeof(char)), fileComprLen = fileUncomprLen;
6 cycrow 2133
	unsigned char *fileCompr = NULL;
2134
 
2135
	compressed = false;
2136
	if ( fileUncomprLen )
2137
	{
2138
		if ( fileheader == SPKCOMPRESS_ZLIB )
2139
		{
2140
			if ( fileComprLen < 100 )
2141
				fileComprLen = 200;
2142
			else if ( fileComprLen < 1000 )
2143
				fileComprLen *= 2;
2144
			fileCompr = (unsigned char *)calloc((unsigned int)fileComprLen, 1);
211 cycrow 2145
			int err = compress ( (unsigned char *)fileCompr, (unsigned long *)&fileComprLen, (const unsigned char *)files.c_str(), (unsigned long)fileUncomprLen, 0 );
6 cycrow 2146
			if ( err == Z_OK )
2147
				compressed = true;
2148
		}
2149
	}
2150
 
2151
	// if unable to compress, store it as plain text
2152
	if ( !compressed )
2153
	{
2154
		fileComprLen = fileUncomprLen;
2155
		fileCompr = (unsigned char *)calloc((unsigned int)fileComprLen, 1);
211 cycrow 2156
		memcpy ( fileCompr, (const unsigned char *)files.c_str(), fileComprLen );
6 cycrow 2157
		fileheader = SPKCOMPRESS_NONE;
2158
	}
2159
 
2160
	// now write the file header
175 cycrow 2161
	header.lSize = fileComprLen;
2162
	file.write("FileHeader;%d;%ld;%ld;%d;%d\n", header.iNumFiles, header.lSize, header.lFullSize, fileheader, header.iDataCompression);
6 cycrow 2163
 
52 cycrow 2164
	file.put(static_cast<unsigned char>(fileUncomprLen >> 24));
2165
	file.put(static_cast<unsigned char>(fileUncomprLen >> 16));
2166
	file.put(static_cast<unsigned char>(fileUncomprLen >> 8));
2167
	file.put(static_cast<unsigned char>(fileUncomprLen));
2168
	file.write(fileCompr, fileComprLen);
6 cycrow 2169
	free ( fileCompr );
2170
 
2171
	if ( progress )
2172
	{
2173
		progress->UpdateStatus(STATUS_WRITE);
2174
		progress->SetDone(0);
2175
		long max = 0;
88 cycrow 2176
		for ( CListNode<C_File> *file = m_lFiles.Front(); file; file = file->next() )
2177
			max += file->Data()->GetDataSize();
6 cycrow 2178
		if ( m_pIconFile )
2179
			max += m_pIconFile->GetDataSize();
2180
		progress->SetMax(max);
2181
	}
2182
 
2183
	// now finally, write all the file data
52 cycrow 2184
	if ( m_pIconFile ) {
2185
		if ( progress )	progress->UpdateFile(m_pIconFile);
178 cycrow 2186
		file.writeSize(m_pIconFile->uncompressedDataSize());
52 cycrow 2187
		file.write(m_pIconFile->GetData(), m_pIconFile->GetDataSize());
2188
		if ( progress )	progress->IncDone(m_pIconFile->GetDataSize());
6 cycrow 2189
	}
2190
 
2191
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
2192
	{
52 cycrow 2193
		C_File *f = node->Data();
2194
		if ( progress )	progress->UpdateFile(f);
178 cycrow 2195
		file.writeSize(f->uncompressedDataSize());
52 cycrow 2196
		unsigned char *data = f->GetData();
2197
		size_t remaining = f->GetDataSize();
2198
		while ( remaining )	{
6 cycrow 2199
			size_t writeSize = WRITECHUNK;
52 cycrow 2200
			if ( writeSize > remaining ) writeSize = remaining;
6 cycrow 2201
 
52 cycrow 2202
			if ( file.write(data, writeSize) ) {
2203
				data += writeSize;
2204
				remaining -= writeSize;
2205
			}
6 cycrow 2206
 
52 cycrow 2207
			if ( progress ) progress->IncDone((int)writeSize);
6 cycrow 2208
		}
2209
	}
2210
 
2211
	return true;
2212
}
2213
 
210 cycrow 2214
bool CBaseFile::extractFile(C_File *file, const Utils::WString &dir, bool includedir, CProgressInfo *progress)
131 cycrow 2215
{
2216
	if (ReadFileToMemory(file))
6 cycrow 2217
	{
2218
		// now finally, uncompress the file
2219
		long len = 0;
131 cycrow 2220
		unsigned char *data = file->UncompressData(&len, progress);
2221
		if (!data)
6 cycrow 2222
		{
2223
			// attempt a file decompress
131 cycrow 2224
			if (file->GetCompressionType() == SPKCOMPRESS_7ZIP)
6 cycrow 2225
			{
178 cycrow 2226
				if (file->uncompressToFile(dir, this, includedir, progress))
6 cycrow 2227
					return true;
2228
			}
2229
			return false;
2230
		}
2231
 
210 cycrow 2232
		if (!file->writeToDir(dir, this, includedir, Utils::WString::Null(), data, len))
6 cycrow 2233
			return false;
2234
 
2235
		return true;
2236
 
2237
	}
2238
	else
2239
		return false;
2240
}
210 cycrow 2241
bool CBaseFile::extractFile(C_File *file, const Utils::WString &dir, unsigned int game, const Utils::WStringList &gameAddons, bool includedir, CProgressInfo *progress)
131 cycrow 2242
{
2243
	if (ReadFileToMemory(file))
2244
	{
2245
		CDirIO Dir(dir);
197 cycrow 2246
		Utils::WString addonDir;
131 cycrow 2247
		if (file->isFileInAddon())
2248
		{
2249
			int addonGame = file->getForSingleGame();
2250
			if (!addonGame) addonGame = game;
6 cycrow 2251
 
131 cycrow 2252
			if (addonGame > 0)
197 cycrow 2253
				addonDir = gameAddons.findString(Utils::WString::Number(addonGame));
131 cycrow 2254
		}
2255
 
2256
		if (!addonDir.empty())
2257
			Dir.cd(addonDir);
2258
 
2259
		// create directory first
2260
		Dir.create(file->getDirectory(this));
2261
 
2262
		// now finally, uncompress the file
2263
		long len = 0;
2264
		unsigned char *data = file->UncompressData(&len, progress);
2265
		if (!data)
2266
		{
2267
			// attempt a file decompress
2268
			if (file->GetCompressionType() == SPKCOMPRESS_7ZIP)
2269
			{
210 cycrow 2270
				if (file->uncompressToFile(Dir.dir(), this, includedir, progress))
131 cycrow 2271
					return true;
2272
			}
2273
			return false;
2274
		}
2275
 
210 cycrow 2276
		if (!file->writeToDir(Dir.dir(), this, includedir, Utils::WString::Null(), data, len))
131 cycrow 2277
			return false;
2278
 
2279
		return true;
2280
 
2281
	}
2282
	else
2283
		return false;
2284
}
2285
 
210 cycrow 2286
bool CBaseFile::extractFile(int filenum, const Utils::WString &dir, unsigned int game, const Utils::WStringList &gameAddons, bool includedir, CProgressInfo *progress)
131 cycrow 2287
{
2288
	// invalid valus
2289
	if (filenum < 0)
2290
		return false;
2291
	// out of range
2292
	if (filenum > m_lFiles.size())
2293
		return false;
2294
 
2295
	// get the file pointer
2296
	C_File *file = m_lFiles.Get(filenum);
2297
	return extractFile(file, dir, game, gameAddons, includedir, progress);
2298
}
2299
 
210 cycrow 2300
bool CBaseFile::extractFile(int filenum, const Utils::WString &dir, bool includedir, CProgressInfo *progress)
131 cycrow 2301
{
2302
	// invalid valus
2303
	if (filenum < 0)
2304
		return false;
2305
	// out of range
2306
	if (filenum > m_lFiles.size())
2307
		return false;
2308
 
2309
	// get the file pointer
2310
	C_File *file = m_lFiles.Get(filenum);
175 cycrow 2311
	return extractFile(file, dir, includedir, progress);
131 cycrow 2312
}
2313
 
210 cycrow 2314
bool CBaseFile::extractAll(const Utils::WString &dir, int game, const Utils::WStringList &gameAddons, bool includedir, CProgressInfo *progress)
6 cycrow 2315
{
2316
	// no file to read from
129 cycrow 2317
	if (this->filename().empty())
6 cycrow 2318
		return false;
2319
 
2320
	// now open the file
58 cycrow 2321
	CFileIO *File = _startRead();
129 cycrow 2322
	if (!File) return false;
6 cycrow 2323
 
2324
	// now were in the file section
2325
	// skip past each one
129 cycrow 2326
	if (m_pIconFile) File->seek(4 + m_pIconFile->GetDataSize());
6 cycrow 2327
 
134 cycrow 2328
	for (CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next()) 
2329
	{
6 cycrow 2330
		C_File *fit = node->Data();
2331
 
134 cycrow 2332
		if ((!fit->GetDataSize()) || (!fit->GetData())) 
2333
		{
2334
			if (!fit->readFromFile(*File, fit->GetDataSize())) 
2335
				return false;
6 cycrow 2336
		}
2337
		else
58 cycrow 2338
			File->seek(fit->GetDataSize());
6 cycrow 2339
 
129 cycrow 2340
		if (game && !fit->isForGame(game))
2341
			continue;
2342
 
134 cycrow 2343
		if (progress)	
2344
			progress->UpdateFile(fit);
2345
 
129 cycrow 2346
		CDirIO Dir(dir);
210 cycrow 2347
		Utils::WString addonDir;
129 cycrow 2348
		if (fit->isFileInAddon())
2349
		{
2350
			int addonGame = fit->getForSingleGame();
2351
			if (!addonGame) addonGame = game;
2352
 
2353
			if (addonGame > 0)
210 cycrow 2354
				addonDir = gameAddons.findString(Utils::WString::Number(addonGame));
6 cycrow 2355
		}
2356
 
129 cycrow 2357
		if (!addonDir.empty())
2358
			Dir.cd(addonDir);
2359
 
6 cycrow 2360
		// create directory first
315 cycrow 2361
		if (!Dir.create(fit->getDirectory(this)))
2362
			continue;
6 cycrow 2363
 
2364
		long size = 0;
129 cycrow 2365
		unsigned char *data = fit->UncompressData(&size, progress);
2366
		if ((!data) && (fit->GetCompressionType() == SPKCOMPRESS_7ZIP)) {
210 cycrow 2367
			if (!fit->uncompressToFile(Dir.dir(), this, includedir, progress)) return false;
6 cycrow 2368
		}
210 cycrow 2369
		else if ((!data) || (!fit->writeToDir(Dir.dir(), this, includedir, Utils::WString::Null(), data, size))) return false;
6 cycrow 2370
	}
2371
 
58 cycrow 2372
	delete File;
6 cycrow 2373
	return true;
2374
}
2375
 
2376
 
175 cycrow 2377
bool CBaseFile::computeSigned(bool updateFiles) const
6 cycrow 2378
{
252 cycrow 2379
	// any globals?
2380
	if (!_lGlobals.empty())
2381
		return false;
2382
 
175 cycrow 2383
	for (CListNode<C_File>* node = m_lFiles.Front(); node; node = node->next())
6 cycrow 2384
	{
175 cycrow 2385
		C_File* file = node->Data();
2386
		if (updateFiles)
6 cycrow 2387
			file->UpdateSigned();
2388
		// extra, text, soundtrack, readmes and screen files do not require a modified game directly
175 cycrow 2389
		if ((file->GetFileType() == FILETYPE_EXTRA) || (file->GetFileType() == FILETYPE_TEXT) || (file->GetFileType() == FILETYPE_SOUND) || (file->GetFileType() == FILETYPE_SCREEN) || (file->GetFileType() == FILETYPE_README))
6 cycrow 2390
			continue;
2391
		// mods and maps always need modified game
175 cycrow 2392
		else if ((file->GetFileType() == FILETYPE_MOD) || (file->GetFileType() == FILETYPE_MAP))
2393
			return false;
6 cycrow 2394
 
2395
		// else should be a script file, script or uninstall type
2396
		// all scripts must be signed, if any are not, then no signed status
175 cycrow 2397
		if (!file->IsSigned())
2398
			return false;
6 cycrow 2399
	}
2400
 
175 cycrow 2401
	return true;
2402
}
2403
 
2404
bool CBaseFile::updateSigned(bool updateFiles)
2405
{
2406
	m_bSigned = computeSigned(updateFiles);
6 cycrow 2407
	return m_bSigned;
2408
}
2409
 
203 cycrow 2410
bool CBaseFile::isPackageNeeded(const Utils::WString &scriptName, const Utils::WString &author)
6 cycrow 2411
{
2412
	for ( CListNode<SNeededLibrary> *node = m_lNeededLibrarys.Front(); node; node = node->next() )
2413
	{
2414
		SNeededLibrary *l = node->Data();
2415
		if ( l->sName.Compare(scriptName) && l->sAuthor.Compare(author) )
2416
			return true;
2417
	}
2418
 
2419
	return false;
2420
}
2421
 
203 cycrow 2422
SNeededLibrary *CBaseFile::findPackageNeeded(const Utils::WString &scriptName, const Utils::WString &author)
6 cycrow 2423
{
2424
	for ( CListNode<SNeededLibrary> *node = m_lNeededLibrarys.Front(); node; node = node->next() )
2425
	{
2426
		SNeededLibrary *l = node->Data();
2427
		if ( l->sName.Compare(scriptName) && l->sAuthor.Compare(author) )
2428
			return l;
2429
	}
2430
 
2431
	return NULL;
2432
}
2433
 
207 cycrow 2434
void CBaseFile::removeFakePatchOrder(const Utils::WString &scriptName, const Utils::WString &author)
6 cycrow 2435
{
160 cycrow 2436
	removeFakePatchOrder(true, scriptName, author);
2437
	removeFakePatchOrder(false, scriptName, author);
6 cycrow 2438
}
207 cycrow 2439
void CBaseFile::removeFakePatchOrder(bool after, const Utils::WString &scriptName, const Utils::WString &author)
6 cycrow 2440
{
207 cycrow 2441
	Utils::WStringList *list;
6 cycrow 2442
	if ( after )
160 cycrow 2443
		list = &_lFakePatchAfter;
6 cycrow 2444
	else
160 cycrow 2445
		list = &_lFakePatchBefore;
6 cycrow 2446
 
160 cycrow 2447
	int found = list->findStringAndData(scriptName, author);
2448
	while (found != -1)
6 cycrow 2449
	{
160 cycrow 2450
		list->removeAt(found);
2451
		found = list->findStringAndData(scriptName, author);
6 cycrow 2452
	}
2453
}
2454
 
207 cycrow 2455
void CBaseFile::addFakePatchOrder(bool after, const Utils::WString &scriptName, const Utils::WString &author)
6 cycrow 2456
{
207 cycrow 2457
	Utils::WStringList *list;
6 cycrow 2458
	if ( after )
160 cycrow 2459
		list = &_lFakePatchAfter;
6 cycrow 2460
	else
160 cycrow 2461
		list = &_lFakePatchBefore;
6 cycrow 2462
 
2463
	// check if the package already exists
160 cycrow 2464
	if (!list->containsStringAndData(scriptName, author))
6 cycrow 2465
	{
160 cycrow 2466
		// cant have it on both list
2467
		removeFakePatchOrder(!after, scriptName, author);
2468
 
2469
		list->pushBack(scriptName, author);
6 cycrow 2470
	}
2471
}
204 cycrow 2472
void CBaseFile::addNeededLibrary(const Utils::WString &scriptName, const Utils::WString &author, const Utils::WString &minVersion)
6 cycrow 2473
{
203 cycrow 2474
	SNeededLibrary *l = this->findPackageNeeded(scriptName, author);
6 cycrow 2475
	if ( !l )
2476
	{
2477
		l = new SNeededLibrary;
2478
		l->sName = scriptName;
2479
		l->sAuthor = author;
2480
		m_lNeededLibrarys.push_back(l);
2481
	}
2482
	l->sMinVersion = minVersion;
2483
}
2484
 
203 cycrow 2485
void CBaseFile::removePackageNeeded(const Utils::WString &scriptName, const Utils::WString &author)
6 cycrow 2486
{
203 cycrow 2487
	SNeededLibrary *l = this->findPackageNeeded(scriptName, author);
6 cycrow 2488
	if ( l )
2489
	{
2490
		m_lNeededLibrarys.remove(l);
2491
		delete l;
2492
	}
2493
}
2494
 
2495
void CBaseFile::ClearNeededPackages()
2496
{
203 cycrow 2497
	SNeededLibrary *ns = this->findPackageNeeded(L"<package>", L"<author>");
204 cycrow 2498
	Utils::WString version;
46 cycrow 2499
	if ( ns ) version = ns->sMinVersion;
2500
 
6 cycrow 2501
	for ( CListNode<SNeededLibrary> *node = m_lNeededLibrarys.Front(); node; node = node->next() )
2502
		node->DeleteData();
2503
	m_lNeededLibrarys.clear();
2504
 
203 cycrow 2505
	if ( !version.empty() )	this->addNeededLibrary(L"<package>", L"<author>", version);
6 cycrow 2506
}
2507
 
2508
 
210 cycrow 2509
bool CBaseFile::GeneratePackagerScript(bool wildcard, Utils::WStringList *list, int game, const Utils::WStringList &gameAddons, bool datafile)
6 cycrow 2510
{
210 cycrow 2511
	list->pushBack(L"#");
2512
	list->pushBack(L"# Packager Script");
2513
	list->pushBack(L"# -- Generated by SPK Libraries V" + Utils::WString::FromFloat(GetLibraryVersion(), 2) + L" --");
2514
	list->pushBack(L"#");
2515
	list->pushBack(L"");
6 cycrow 2516
	if ( !datafile )
2517
	{
210 cycrow 2518
		list->pushBack(L"# Variable for your game directory, where to get files from");
2519
		list->pushBack(L"# $PATH variable is used to get the current path");
2520
		list->pushBack(L"Variable: $GAMEDIR $PATH");
2521
		list->pushBack(L"");
6 cycrow 2522
	}
210 cycrow 2523
	list->pushBack(L"# The name of the script");
2524
	list->pushBack(L"Name: " + this->name());
2525
	list->pushBack(L"");
2526
	list->pushBack(L"# The author of the script, ie, you");
2527
	list->pushBack(L"Author: " + this->author());
2528
	list->pushBack(L"");
2529
	list->pushBack(L"# The creation data, when it was created");
6 cycrow 2530
	if ( datafile )
210 cycrow 2531
		list->pushBack(L"Date: " + this->creationDate());
50 cycrow 2532
	else {
210 cycrow 2533
		list->pushBack(L"# $DATE variable is used to get the current date");
2534
		list->pushBack(L"Date: $DATE");
6 cycrow 2535
	}
210 cycrow 2536
	list->pushBack(L"");
2537
	list->pushBack(L"# The version of script");
6 cycrow 2538
	if ( datafile )
210 cycrow 2539
		list->pushBack(L"Version: " + this->version());
6 cycrow 2540
	else
2541
	{
210 cycrow 2542
		list->pushBack(L"# $ASK variable is used to get an input when creating");
2543
		list->pushBack(L"Version: $ASK");
6 cycrow 2544
	}
210 cycrow 2545
	list->pushBack(L"");
6 cycrow 2546
 
2547
	if ( !m_lGames.empty() ) {
210 cycrow 2548
		list->pushBack(L"# The game version the script is for <game> <version> (can have multiple games)");
6 cycrow 2549
		for ( SGameCompat *g = m_lGames.First(); g; g = m_lGames.Next() ) {
126 cycrow 2550
			if (game > 0 && g->iGame != game)
2551
				continue;
2552
 
197 cycrow 2553
			Utils::WString game = CBaseFile::ConvertGameToString(g->iGame);
6 cycrow 2554
 
46 cycrow 2555
			if ( !g->sVersion.empty() )
6 cycrow 2556
			{
197 cycrow 2557
				game += L" ";
46 cycrow 2558
				game += g->sVersion;
6 cycrow 2559
			}
2560
			else
2561
			{
197 cycrow 2562
				game += L" ";
6 cycrow 2563
				game += (long)g->iVersion;
2564
			}
2565
 
210 cycrow 2566
			list->pushBack(L"Game: " + game);
6 cycrow 2567
		}
2568
 
210 cycrow 2569
		list->pushBack(L"");
6 cycrow 2570
	}
2571
 
48 cycrow 2572
	if ( !this->description().empty() ) {
210 cycrow 2573
		list->pushBack(L"# The description of the script, displays when installing");
2574
		list->pushBack(L"Description: " + this->description());
2575
		list->pushBack(L"");
6 cycrow 2576
	}
2577
 
49 cycrow 2578
	if ( !this->webSite().empty() ) {
210 cycrow 2579
		list->pushBack(L"# A link to the website for the script, ie for an online help page");
2580
		list->pushBack(L"WebSite: " + this->webSite());
2581
		list->pushBack(L"");
6 cycrow 2582
	}
2583
 
49 cycrow 2584
	if ( !this->forumLink().empty() ) {
210 cycrow 2585
		list->pushBack(L"# A direct link to the thread in the egosoft forum");
2586
		list->pushBack(L"ForumLink: " + this->forumLink());
2587
		list->pushBack(L"");
6 cycrow 2588
	}
2589
 
49 cycrow 2590
	if ( !this->webAddress().empty() ) {
210 cycrow 2591
		list->pushBack(L"# A link to the address for the update file");
2592
		list->pushBack(L"WebAddress: " + this->webAddress());
2593
		list->pushBack(L"");
6 cycrow 2594
	}
2595
 
49 cycrow 2596
	if ( !this->email().empty() ) {
210 cycrow 2597
		list->pushBack(L"# The email address of the author, to allow users to contract if needed");
2598
		list->pushBack(L"Email: " + this->email());
2599
		list->pushBack(L"");
6 cycrow 2600
	}
2601
 
208 cycrow 2602
	if (webMirrors().size())
6 cycrow 2603
	{
210 cycrow 2604
		list->pushBack(L"# A link to the mirror address for the update file, can have many of these");
208 cycrow 2605
		for(auto itr = webMirrors().begin(); itr != webMirrors().end(); itr++)
210 cycrow 2606
			list->pushBack(Utils::WString(L"WebMirror: ") + (*itr)->str);
2607
		list->pushBack(L"");
6 cycrow 2608
	}
2609
 
2610
	if ( m_bAutoGenerateUpdateFile )
2611
	{
210 cycrow 2612
		list->pushBack(L"# Auto generate the package update file when created");
2613
		list->pushBack(L"GenerateUpdateFile");
6 cycrow 2614
	}
2615
 
2616
	if ( m_lNeededLibrarys.size() )
2617
	{
210 cycrow 2618
		list->pushBack(L"# Needed Library dependacies, require these to be installed");
6 cycrow 2619
		for ( CListNode<SNeededLibrary> *node = m_lNeededLibrarys.Front(); node; node = node->next() )
210 cycrow 2620
			list->pushBack(L"Depend: " + node->Data()->sName + L"|" + node->Data()->sMinVersion + L"|" + node->Data()->sAuthor);
6 cycrow 2621
 
210 cycrow 2622
		list->pushBack(L"");
6 cycrow 2623
	}
2624
 
46 cycrow 2625
	if ( !_noRatings() )
6 cycrow 2626
	{
210 cycrow 2627
		list->pushBack(L"# Ratings Values, 0 to 5, <ease> <changing> <recommended>");
2628
		list->pushBack(Utils::WString(L"Ratings: ") + (long)easeOfUse() + L" " + (long)gameChanging() + L" " + (long)recommended());
2629
		list->pushBack(L"");
6 cycrow 2630
	}
2631
 
170 cycrow 2632
	if (namesList()->size())
6 cycrow 2633
	{
210 cycrow 2634
		list->pushBack(L"# Package names, uses different names for different languages");
170 cycrow 2635
		for(auto itr = namesList()->begin(); itr != namesList()->end(); itr++)
210 cycrow 2636
			list->pushBack(Utils::WString("ScriptName: ") + (long)(*itr)->iLanguage + L" " + (*itr)->sName);
2637
		list->pushBack(L"");
6 cycrow 2638
	}
2639
 
46 cycrow 2640
	for ( int j = 0; j < 2; j++ ) {
206 cycrow 2641
		Utils::WString installText = (j == 0) ? L"Install" : L"Uninstall";
46 cycrow 2642
		const CInstallText *pText = (j == 0) ? this->installText() : this->uninstallText();
2643
		if ( pText->any() )
6 cycrow 2644
		{
210 cycrow 2645
			list->pushBack(L"# " + installText + L" Texts, display text before and/or after " + installText + L"ing to inform the use of special conditions");
46 cycrow 2646
			for ( unsigned int i = 0; i < pText->count(); i++ ) {
2647
				long iLang = pText->language(i);
210 cycrow 2648
				if ( !pText->getBefore(iLang).empty() )	list->pushBack(installText + "Before: " + iLang + L" " + pText->getBefore(iLang));
2649
				if ( !pText->getAfter(iLang).empty()  )	list->pushBack(installText + "After: " + iLang + L" " + pText->getAfter(iLang));
46 cycrow 2650
			}
210 cycrow 2651
			list->pushBack(L"");
6 cycrow 2652
		}
2653
	}
2654
 
210 cycrow 2655
	list->pushBack(L"# Plugin Type, the type the plugin is, mainly used to show users the type, types include: Normal, Stable, Experimental, Cheat, Mod");
48 cycrow 2656
	switch ( this->pluginType() )
6 cycrow 2657
	{
2658
		case PLUGIN_NORMAL:
210 cycrow 2659
			list->pushBack(L"PluginType: Normal");
6 cycrow 2660
			break;
2661
		case PLUGIN_STABLE:
210 cycrow 2662
			list->pushBack(L"PluginType: Stable");
6 cycrow 2663
			break;
2664
		case PLUGIN_EXPERIMENTAL:
210 cycrow 2665
			list->pushBack(L"PluginType: Experimental");
6 cycrow 2666
			break;
2667
		case PLUGIN_CHEAT:
210 cycrow 2668
			list->pushBack(L"PluginType: Cheat");
6 cycrow 2669
			break;
2670
		case PLUGIN_MOD:
210 cycrow 2671
			list->pushBack(L"PluginType: Mod");
6 cycrow 2672
			break;
2673
	}
210 cycrow 2674
	list->pushBack(L"");
6 cycrow 2675
 
239 cycrow 2676
	if (!_lGlobals.empty())
2677
	{
2678
		list->pushBack(L"# Globals, add global overrides to a package when generating the globals file, to override game settings");
2679
		for (auto itr = _lGlobals.begin(); itr != _lGlobals.end(); itr++)
2680
			list->pushBack(L"Global: " + (*itr)->str + L";" + (*itr)->data);
2681
		list->pushBack(L"");
2682
	}
2683
 
6 cycrow 2684
	return true;
2685
}
2686
 
210 cycrow 2687
bool CBaseFile::GeneratePackagerScriptFile(bool wildcard, Utils::WStringList *list, int game, const Utils::WStringList &gameAddons)
6 cycrow 2688
{
2689
	// now do files and wildcards
197 cycrow 2690
	Utils::WStringList files;
6 cycrow 2691
	for ( CListNode<C_File> *f = m_lFiles.Front(); f; f = f->next() )
2692
	{
127 cycrow 2693
		if (game && !(f->Data()->game() & 1 << game))
126 cycrow 2694
			continue;
6 cycrow 2695
 
197 cycrow 2696
		Utils::WString name = L"$GAMEDIR/";
126 cycrow 2697
 
127 cycrow 2698
		// addon directory?
2699
		unsigned int checkGame = f->Data()->game() & ~(1 << 31);
2700
		unsigned int foundGame = 0;
2701
		for (int i = 0; i < 31; ++i)
2702
		{
2703
			if (checkGame == 1 << i)
2704
			{
2705
				foundGame = i;
2706
				break;
2707
			}
2708
		}
2709
 
2710
		if (foundGame)
2711
		{
210 cycrow 2712
			Utils::WString str = gameAddons.findString(Utils::WString::Number(foundGame));
127 cycrow 2713
			if(!str.empty())
197 cycrow 2714
				name += str + L"/";
127 cycrow 2715
		}
2716
 
6 cycrow 2717
		bool done = false;
2718
		if ( wildcard )
2719
		{
197 cycrow 2720
			Utils::WString base = f->Data()->baseName();
131 cycrow 2721
			if ( f->Data()->fileType() == FILETYPE_SCRIPT )
6 cycrow 2722
			{
197 cycrow 2723
				if ( base.token(L".", 1).Compare(L"plugin") || base.token(L".", 1).Compare(L"lib") )
6 cycrow 2724
				{
197 cycrow 2725
					name += f->Data()->getDirectory(this) + "/" + base.tokens(L".", 1, 2) + L".*";
6 cycrow 2726
					done = true;
2727
				}
197 cycrow 2728
				else if ( base.token(L".", 1).Compare(L"al") && !base.token(L".", 2).Compare(L"plugin") )
6 cycrow 2729
				{
197 cycrow 2730
					name += f->Data()->getDirectory(this) + L"/" + base.tokens(L".", 1, 2) + L".*";
6 cycrow 2731
					done = true;
2732
				}
2733
			}
131 cycrow 2734
			else if ( f->Data()->fileType() == FILETYPE_TEXT )
6 cycrow 2735
			{
197 cycrow 2736
				if ( base.contains(L"-L") )
6 cycrow 2737
				{
197 cycrow 2738
					name += f->Data()->getDirectory(this) + L"/" + base.token(L"-L", 1) + L"-L*";
6 cycrow 2739
					done = true;
2740
				}
2741
				else
2742
				{
197 cycrow 2743
					name += f->Data()->getDirectory(this) + L"/*" + base.right(4) + L".*";
6 cycrow 2744
					done = true;
2745
				}
2746
			}
2747
		}
2748
 
2749
		if ( !done )
131 cycrow 2750
			name += f->Data()->getNameDirectory(this);
6 cycrow 2751
 
131 cycrow 2752
		if ( !f->Data()->dir().empty() )
6 cycrow 2753
		{
197 cycrow 2754
			name += L"|";
131 cycrow 2755
			name += f->Data()->dir();
6 cycrow 2756
		}
197 cycrow 2757
		Utils::WString s = L"GAME ";
127 cycrow 2758
		if (!f->Data()->game() || f->Data()->game() == GAME_ALLNEW)
2759
			s += CBaseFile::ConvertGameToString(f->Data()->game());
2760
		else
2761
		{
2762
			bool first = true;
2763
			for (int i = 0; i < 31; ++i) 
2764
			{
2765
				if (f->Data()->game() & 1 << i)
2766
				{
2767
					if (first)
2768
						first = false;
2769
					else
210 cycrow 2770
						s += L"|";
127 cycrow 2771
					s += CBaseFile::ConvertGameToString(i);
2772
				}
2773
			}
2774
		}
2775
 
197 cycrow 2776
		s += L" " + name;
126 cycrow 2777
		if(!files.contains(s))
178 cycrow 2778
			files.pushBack(s, f->Data()->fileTypeString());
6 cycrow 2779
	}
2780
 
2781
 
126 cycrow 2782
	if ( !files.empty() )
6 cycrow 2783
	{
210 cycrow 2784
		list->pushBack(L"# Files List, all the files to add, can include wild cards");
126 cycrow 2785
		for(auto itr = files.begin(); itr != files.end(); itr++)
210 cycrow 2786
			list->pushBack((*itr)->data + L": " + (*itr)->str);
2787
		list->pushBack(L"");
6 cycrow 2788
	}
2789
 
2790
	return true;
2791
}
2792
 
203 cycrow 2793
Utils::WString CBaseFile::getAutosaveName() const
6 cycrow 2794
{
210 cycrow 2795
	return this->name() + L"-V" + this->version() + L"-" + this->creationDate().findReplace(L"/", L".");
6 cycrow 2796
}
2797
 
233 cycrow 2798
void CBaseFile::addGlobal(const Utils::WString& global, const Utils::WString& setting)
2799
{
2800
	if (!_lGlobals.changeData(global, setting))
2801
		_lGlobals.pushBack(global, setting);
2802
}
2803
 
2804
void CBaseFile::removeGlobal(const Utils::WString& global)
2805
{
2806
	_lGlobals.remove(global);
2807
}
2808
 
237 cycrow 2809
void CBaseFile::clearGlobals()
2810
{
2811
	_lGlobals.clear();
2812
}
233 cycrow 2813
 
6 cycrow 2814
bool CBaseFile::CheckGameCompatability(int game)
2815
{
2816
	if ( m_lGames.empty() )
2817
		return true; // no game compatability added, assume its ok for all
2818
 
2819
	for ( CListNode<SGameCompat> *node = m_lGames.Front(); node; node = node->next() ) {
2820
		if ( node->Data()->iGame == 0 || node->Data()->iGame == game )
2821
			return true;
2822
	}
2823
	return false;
2824
}
2825
 
197 cycrow 2826
bool CBaseFile::checkGameVersionCompatability(int game, const Utils::WString &sVersion, int iVersion) const
6 cycrow 2827
{
170 cycrow 2828
	if (m_lGames.empty())
6 cycrow 2829
		return true; // no game compatability added, assume its ok for all
2830
 
2831
	bool foundAll = false;
2832
	for ( CListNode<SGameCompat> *node = m_lGames.Front(); node; node = node->next() ) {
2833
		if ( node->Data()->iGame == 0 )
2834
			foundAll = true;
2835
		else if ( node->Data()->iGame == game ) { // now check the version
46 cycrow 2836
			if ( node->Data()->sVersion.empty() ) {
170 cycrow 2837
				if (node->Data()->sVersion.compareVersion(sVersion) == COMPARE_OLDER)
6 cycrow 2838
					return false;
2839
				return true;
2840
			}
2841
			else {
2842
				if ( node->Data()->iVersion > iVersion )
2843
					return false;
2844
				return true;
2845
			}
2846
		}
2847
	}
2848
	return foundAll;
2849
}
2850
 
2851
bool CBaseFile::RemoveGameCompatability(int game)
2852
{
2853
	for ( CListNode<SGameCompat> *node = m_lGames.Front(); node; node = node->next() ) {
2854
		if ( node->Data()->iGame == game ) {
2855
			m_lGames.remove(node);
50 cycrow 2856
			_changed();
6 cycrow 2857
			return true;
2858
		}
2859
	}
2860
 
2861
	return false;
2862
}
2863
 
2864
SGameCompat *CBaseFile::GetGameCompatability(int game)
2865
{
2866
	for ( CListNode<SGameCompat> *node = m_lGames.Front(); node; node = node->next() ) {
2867
		if ( node->Data()->iGame == game ) {
2868
			return node->Data();
2869
		}
2870
	}
2871
 
2872
	return NULL;
2873
}
2874
 
210 cycrow 2875
void CBaseFile::AddGameCompatability(int game, const Utils::WString &version)
6 cycrow 2876
{
2877
	// first check if we already have it on the list
2878
	SGameCompat *Found = this->GetGameCompatability(game);
2879
	if ( !Found ) {
2880
		Found = new SGameCompat;
2881
		m_lGames.push_back(Found);
2882
	}
2883
 
2884
	Found->iGame = game;
2885
	Found->iVersion = -1;
210 cycrow 2886
	Found->sVersion = L"";
6 cycrow 2887
 
210 cycrow 2888
	if ( version.contains(L".") || !version.isNumber() )
2889
		Found->sVersion = version;
6 cycrow 2890
	else
210 cycrow 2891
		Found->iVersion = version;
50 cycrow 2892
	_changed();
6 cycrow 2893
}
2894
 
196 cycrow 2895
Utils::WString CBaseFile::_replaceFilename(const Utils::WString &fname)
131 cycrow 2896
{
196 cycrow 2897
	Utils::WString filename = fname;
213 cycrow 2898
	Utils::WString cdate = this->creationDate().findReplace(L"/", L".").remove(' ');
196 cycrow 2899
	if (filename.contains(L"$AUTOSAVE"))
131 cycrow 2900
	{
2901
		if (this->GetType() == TYPE_XSP)
196 cycrow 2902
			filename = filename.findReplace(L"$AUTOSAVE", L"$NAME-V$VERSION-$CDATE.xsp");
131 cycrow 2903
		else
196 cycrow 2904
			filename = filename.findReplace(L"$AUTOSAVE", L"$NAME-V$VERSION-$CDATE.spk");
131 cycrow 2905
	}
203 cycrow 2906
	filename = filename.findReplace(L"$NAME", this->name().remove(L' '));
2907
	filename = filename.findReplace(L"$AUTHOR", this->author().remove(L' '));
199 cycrow 2908
	filename = filename.findReplace(L"$DATE", cdate);
2909
	filename = filename.findReplace(L"$CDATE", cdate);
2910
	filename = filename.findReplace(L"$VERSION", this->version());
131 cycrow 2911
 
2912
	return filename;
2913
}
197 cycrow 2914
bool CBaseFile::loadPackageData(const Utils::WString &sFirst, const Utils::WString &sRest, const Utils::WString &sMainGame, Utils::WStringList &otherGames, Utils::WStringList &gameAddons, CProgressInfo *progress)
6 cycrow 2915
{
207 cycrow 2916
	if (sFirst.Compare(L"Name"))					this->setName(sRest);
2917
	else if (sFirst.Compare(L"Author"))				this->setAuthor(sRest);
2918
	else if (sFirst.Compare(L"ScriptName"))			addName(parseLanguage(sRest.token(L" ", 1)), sRest.tokens(L" ", 2));
2919
	else if (sFirst.Compare(L"UninstallBefore"))	this->addUninstallText(parseLanguage(sRest.token(L" ", 1)), true, sRest.tokens(L" ", 2));
2920
	else if (sFirst.Compare(L"UninstallAfter"))		this->addUninstallText(parseLanguage(sRest.token(L" ", 1)), false, sRest.tokens(L" ", 2));
2921
	else if (sFirst.Compare(L"InstallBefore"))		this->addInstallText(parseLanguage(sRest.token(L" ", 1)), true, sRest.tokens(L" ", 2));
2922
	else if (sFirst.Compare(L"InstallAfter"))		this->addInstallText(parseLanguage(sRest.token(L" ", 1)), false, sRest.tokens(L" ", 2));
211 cycrow 2923
	else if (sFirst.Compare(L"Date"))				this->setCreationDate(sRest);
2924
	else if (sFirst.Compare(L"Version"))			this->setVersion(sRest);
197 cycrow 2925
	else if (sFirst.Compare(L"GameVersion"))
211 cycrow 2926
		this->AddGameCompatability(-1, sRest);
197 cycrow 2927
	else if (sFirst.Compare(L"PluginType")) {
134 cycrow 2928
		if (sRest.isNumber())						this->setPluginType(sRest);
197 cycrow 2929
		else if (sRest.Compare(L"Normal"))			this->setPluginType(PLUGIN_NORMAL);
2930
		else if (sRest.Compare(L"Stable"))			this->setPluginType(PLUGIN_STABLE);
2931
		else if (sRest.Compare(L"Experimental"))	this->setPluginType(PLUGIN_EXPERIMENTAL);
2932
		else if (sRest.Compare(L"Cheat"))			this->setPluginType(PLUGIN_CHEAT);
2933
		else if (sRest.Compare(L"Mod"))				this->setPluginType(PLUGIN_MOD);
6 cycrow 2934
	}
2935
	// new version
197 cycrow 2936
	else if (sFirst.Compare(L"GenerateUpdateFile"))
6 cycrow 2937
		m_bAutoGenerateUpdateFile = true;
197 cycrow 2938
	else if (sFirst.Compare(L"Game"))
6 cycrow 2939
	{
197 cycrow 2940
		Utils::WString sGame = sRest.token(L" ", 1);
211 cycrow 2941
		this->AddGameCompatability(CBaseFile::GetGameFromString(sGame), sRest.token(L" ", 2));
6 cycrow 2942
	}
211 cycrow 2943
	else if (sFirst.Compare(L"Description"))		this->setDescription(sRest);
197 cycrow 2944
	else if (sFirst.Compare(L"AutoSave") || sFirst.Compare(L"AutoExport") || sFirst.Compare(L"AutoRarExport") || sFirst.Compare(L"AutoZipExport"))
6 cycrow 2945
	{
196 cycrow 2946
		Utils::WString filename = _replaceFilename(sRest);
6 cycrow 2947
 
197 cycrow 2948
		if (sFirst.Compare(L"AutoZipExport") || sFirst.Compare(L"AutoExport"))
211 cycrow 2949
			this->setExportFilename(CFileIO(filename).changeFileExtension(L"zip"));
197 cycrow 2950
		else if (sFirst.Compare(L"AutoRarExport"))
211 cycrow 2951
			this->setExportFilename(CFileIO(filename).changeFileExtension(L"rar"));
6 cycrow 2952
		else
197 cycrow 2953
			this->setFilename(filename);
6 cycrow 2954
	}
211 cycrow 2955
	else if (sFirst.Compare(L"WebSite"))		this->setWebSite(sRest);
213 cycrow 2956
	else if (sFirst.Compare(L"ForumLink") || sFirst.Compare(L"Forum")) this->setForumLink(sRest);
211 cycrow 2957
	else if (sFirst.Compare(L"Email"))			this->setEmail(sRest);
2958
	else if (sFirst.Compare(L"WebAddress"))		this->setWebAddress(sRest);
197 cycrow 2959
	else if (sFirst.Compare(L"WebMirror"))
211 cycrow 2960
		this->addWebMirror(sRest);
197 cycrow 2961
	else if (sFirst.Compare(L"WebMirror1"))
211 cycrow 2962
		this->addWebMirror(sRest);
197 cycrow 2963
	else if (sFirst.Compare(L"WebMirror2"))
211 cycrow 2964
		this->addWebMirror(sRest);
197 cycrow 2965
	else if (sFirst.Compare(L"Ftp"))
210 cycrow 2966
		_sFtpAddr = sRest;
197 cycrow 2967
	else if (sFirst.Compare(L"Ratings"))		_setRatings(sRest.token(L" ", 1), sRest.token(L" ", 2), sRest.token(L" ", 3));
2968
	else if (sFirst.Compare(L"EaseOfUse"))		setEaseOfUse(sRest);
2969
	else if (sFirst.Compare(L"GameChanging"))	setGameChanging(sRest);
2970
	else if (sFirst.Compare(L"Recommended"))	setRecommended(sRest);
2971
	else if (sFirst.Compare(L"Depend"))
6 cycrow 2972
	{
197 cycrow 2973
		Utils::WString version = sRest.token(L"|", 2);
2974
		Utils::WString name = sRest.token(L"|", 1);
2975
		Utils::WString author = sRest.tokens(L"|", 3);
6 cycrow 2976
 
211 cycrow 2977
		this->addNeededLibrary(name, author, version);
6 cycrow 2978
	}
197 cycrow 2979
	else if (sFirst.Compare(L"DependPackage"))
6 cycrow 2980
	{
2981
		CPackages p;
182 cycrow 2982
		CBaseFile *spk = p.openPackage(sRest, 0, 0, SPKREAD_VALUES);
134 cycrow 2983
		if (spk)
6 cycrow 2984
		{
203 cycrow 2985
			this->addNeededLibrary(spk->name(), spk->author(), spk->version());
6 cycrow 2986
			delete spk;
2987
		}
2988
	}
197 cycrow 2989
	else if (sFirst.Compare(L"Icon"))
6 cycrow 2990
	{
197 cycrow 2991
		C_File *icon = new C_File(sRest);
134 cycrow 2992
		if (icon->ReadFromFile())
211 cycrow 2993
			this->setIcon(icon, CFileIO(sRest).extension());
6 cycrow 2994
	}
197 cycrow 2995
	else if (sFirst.Compare(L"CombineGameFiles"))
2996
		_bCombineFiles = sRest.Compare(L"true") || sRest.Compare(L"yes") || sRest.toInt();
2997
	else if (sFirst.Compare(L"UpdateFile"))
134 cycrow 2998
		this->createUpdateFile(sRest);
197 cycrow 2999
	else if (sFirst.Compare(L"ExportZip"))
131 cycrow 3000
	{
196 cycrow 3001
		Utils::WString ext = L"zip";
197 cycrow 3002
		Utils::WString game = sRest.word(1);
196 cycrow 3003
		Utils::WString file = _replaceFilename(CFileIO(sRest.words(2)).fullFilename());
197 cycrow 3004
		if (game.contains(L"|"))
131 cycrow 3005
		{
197 cycrow 3006
			std::vector<Utils::WString> games;
3007
			if(game.tokenise(L"|", games))
131 cycrow 3008
			{
197 cycrow 3009
				for (size_t i = 0; i < games.size(); ++i)
131 cycrow 3010
				{
211 cycrow 3011
					unsigned int g = CBaseFile::GetGameFromString(games[i]);
197 cycrow 3012
					Utils::WString filename = CFileIO(file).dir() + L"/" + CFileIO(file).baseName() + L"_" + CBaseFile::ConvertGameToString(g) + L"." + ext;
211 cycrow 3013
					this->addAutoExport(g, filename);
131 cycrow 3014
				}
3015
			}
3016
		}
3017
		else
3018
		{
211 cycrow 3019
			unsigned int g = CBaseFile::GetGameFromString(game);
197 cycrow 3020
			Utils::WString filename = CFileIO(file).dir() + L"/" + CFileIO(file).baseName() + L"_" + CBaseFile::ConvertGameToString(g) + L"." + ext;
211 cycrow 3021
			this->addAutoExport(g, filename);
131 cycrow 3022
		}
3023
	}
197 cycrow 3024
	else if (sFirst.Compare(L"Extract"))
131 cycrow 3025
	{
197 cycrow 3026
		Utils::WString game = sRest.word(1);
196 cycrow 3027
		Utils::WString dir = CDirIO(sRest.words(2)).dir();
197 cycrow 3028
		if (game.contains(L"|"))
131 cycrow 3029
		{
197 cycrow 3030
			std::vector<Utils::WString> games;
3031
			if (game.tokenise(L"|", games))
131 cycrow 3032
			{
197 cycrow 3033
				for(size_t i = 0; i < games.size(); ++i)
211 cycrow 3034
					this->addAutoExtract(CBaseFile::GetGameFromString(games[i]), dir);
131 cycrow 3035
			}
3036
		}
3037
		else
211 cycrow 3038
			this->addAutoExtract(CBaseFile::GetGameFromString(game), dir);
131 cycrow 3039
	}
239 cycrow 3040
	else if (sFirst.Compare(L"Global"))
3041
		this->addGlobal(sRest.token(L";", 1), sRest.token(L";", 2));
6 cycrow 3042
	else
3043
	{
197 cycrow 3044
		Utils::WString checkType = sFirst;
6 cycrow 3045
		bool shared = false;
197 cycrow 3046
		if (checkType.left(6).Compare(L"Shared"))
6 cycrow 3047
		{
14 cycrow 3048
			checkType = sFirst.right(-6);
6 cycrow 3049
			shared = true;
3050
		}
155 cycrow 3051
		bool packed = false;
197 cycrow 3052
		if (checkType.right(3).Compare(L"PCK"))
155 cycrow 3053
		{
3054
			checkType = sFirst.left(-3);
3055
			packed = true;
3056
		}
6 cycrow 3057
 
3058
		// now check type name
127 cycrow 3059
		FileType filetype = GetFileTypeFromString(checkType);
3060
		if (filetype != FILETYPE_UNKNOWN)
197 cycrow 3061
			this->addFileScript(filetype, shared, packed, sRest, sMainGame, otherGames, gameAddons, progress);
213 cycrow 3062
		else if ( !checkType.Compare(L"changelog") )
6 cycrow 3063
			return false;
3064
	}
3065
 
3066
	return true;
3067
}
3068
 
197 cycrow 3069
void CBaseFile::addFileScript(FileType filetype, bool shared, bool packed, const Utils::WString &sRest, const Utils::WString &sMainGame, Utils::WStringList &otherGames, Utils::WStringList &gameAddons, CProgressInfo *progress)
6 cycrow 3070
{
197 cycrow 3071
	Utils::WString dir;
3072
	Utils::WString rest = sRest;
127 cycrow 3073
 
211 cycrow 3074
	unsigned int mainGame = CBaseFile::GetGameFromString(sMainGame);
127 cycrow 3075
	unsigned int game = 0;
197 cycrow 3076
	if ( rest.token(L" ", 1).left(4).Compare(L"GAME") ) {
3077
		Utils::WString gameStr = rest.token(L" ", 2);
3078
		if (gameStr.contains(L"|"))
127 cycrow 3079
		{
197 cycrow 3080
			std::vector<Utils::WString> games;
3081
			gameStr.tokenise(L"|", games);
3082
			for (size_t i = 0; i < games.size(); ++i)
127 cycrow 3083
			{
211 cycrow 3084
				unsigned int g = CBaseFile::GetGameFromString(games[i]);
127 cycrow 3085
				if (g)
3086
					game |= 1 << g;
3087
			}
3088
		}
3089
		else
131 cycrow 3090
		{
211 cycrow 3091
			unsigned int g = CBaseFile::GetGameFromString(gameStr);
131 cycrow 3092
			if (g)
3093
				game = 1 << g;
3094
		}
197 cycrow 3095
		rest = rest.tokens(L" ", 3);
6 cycrow 3096
	}
127 cycrow 3097
	if (game)
3098
		game |= 1 << 31;
6 cycrow 3099
 
197 cycrow 3100
	if (rest.contains(L"|"))
127 cycrow 3101
	{
197 cycrow 3102
		dir = rest.tokens(L"|", 2);
3103
		rest = rest.token(L"|", 1);
6 cycrow 3104
	}
3105
 
197 cycrow 3106
	rest = rest.findReplace(L"\\", L"/");
6 cycrow 3107
 
3108
	// wild cards
197 cycrow 3109
	if ( rest.containsAny(L"*?") )
6 cycrow 3110
	{
102 cycrow 3111
		CDirIO Dir(CFileIO(rest).dir());
197 cycrow 3112
		Utils::WStringList dirList;
160 cycrow 3113
		if(Dir.dirList(dirList))
6 cycrow 3114
		{
160 cycrow 3115
			for(auto itr = dirList.begin(); itr != dirList.end(); itr++)
6 cycrow 3116
			{
196 cycrow 3117
				Utils::WString file = Dir.file((*itr)->str);
127 cycrow 3118
				if (file.match(rest))
6 cycrow 3119
				{
98 cycrow 3120
					int addGame = game;
3121
					// check if the file exists in the subdirectory too, if it does, add for each game
3122
					if ( game == GAME_ALL && !sMainGame.empty() && !otherGames.empty() ) {
3123
						CFileIO F(file);
197 cycrow 3124
						for(Utils::WString g = otherGames.firstString(); !g.empty(); g = otherGames.nextString()) {
3125
							Utils::WString checkDir = F.dir() + L"/" + g;
121 cycrow 3126
							if ( CDirIO(checkDir).exists(F.filename()) ) {
98 cycrow 3127
								addGame = mainGame;
211 cycrow 3128
								C_File *newfile = this->appendFile(CDirIO(checkDir).file(F.filename()), filetype, CBaseFile::GetGameFromString(g), packed, dir);
134 cycrow 3129
								if (newfile && progress)
3130
									progress->UpdateFile(newfile);
98 cycrow 3131
								if ( newfile ) newfile->SetShared(shared);
3132
							}
3133
						}
3134
					}
3135
 
197 cycrow 3136
					C_File *newfile = this->appendFile(file, filetype, addGame, packed, dir);
134 cycrow 3137
					if (newfile && progress)
3138
						progress->UpdateFile(newfile);
6 cycrow 3139
					if ( newfile )
3140
						newfile->SetShared(shared);
3141
				}
3142
			}
3143
		}
3144
	}
3145
	else
3146
	{
127 cycrow 3147
		unsigned int addGame = game;
98 cycrow 3148
		// check if the file exists in the subdirectory too, if it does, add for each game
3149
		if ( game == GAME_ALL && !sMainGame.empty() && !otherGames.empty() ) {
3150
			CFileIO F(rest);
197 cycrow 3151
			for(Utils::WString g = otherGames.firstString(); !g.empty(); g = otherGames.nextString()) {
3152
				Utils::WString checkDir = F.dir() + L"/" + g;
121 cycrow 3153
				if ( CDirIO(checkDir).exists(F.filename()) ) {
98 cycrow 3154
					addGame = mainGame;
211 cycrow 3155
					C_File *newfile = this->appendFile(CDirIO(checkDir).file(F.filename()), filetype, CBaseFile::GetGameFromString(g), packed, dir);
134 cycrow 3156
					if (newfile && progress)
3157
						progress->UpdateFile(newfile);
98 cycrow 3158
					if ( newfile ) newfile->SetShared(shared);
3159
				}
3160
			}
3161
		}
3162
 
127 cycrow 3163
		unsigned int checkGame = addGame & ~(1 << 31);
3164
		unsigned int foundGame = 0;
3165
		for (int i = 0; i < 31; ++i)
3166
		{
3167
			if (1 << i == checkGame)
3168
			{
3169
				foundGame = i;
3170
				break;
3171
			}
3172
		}
3173
 
3174
		C_File *file = NULL;
3175
		if (foundGame)
3176
		{
197 cycrow 3177
			Utils::WString addon = gameAddons.findString(Utils::WString::Number(foundGame));
127 cycrow 3178
			if (!addon.empty())
3179
			{
197 cycrow 3180
				Utils::WString dir = C_File::GetDirectory(filetype, rest, this);
3181
				Utils::WString filename = rest;
130 cycrow 3182
				if (CCatFile::IsAddonDir(dir) && !filename.contains(addon))
3183
				{
197 cycrow 3184
					filename = filename.findReplace(dir + L"/", addon + L"/" + dir + L"/");
155 cycrow 3185
					file = this->appendFile(filename, filetype, addGame, packed, dir);
130 cycrow 3186
				}
127 cycrow 3187
			}
3188
		}
3189
 
3190
		if(!file)
155 cycrow 3191
			file = this->appendFile(rest, filetype, addGame, packed, dir);
127 cycrow 3192
 
134 cycrow 3193
		if (file && progress)
3194
			progress->UpdateFile(file);
127 cycrow 3195
		if (file)
6 cycrow 3196
			file->SetShared(shared);
3197
	}
3198
}
3199
 
3200
 
197 cycrow 3201
Utils::WString CBaseFile::fileSizeString() const { return SPK::GetSizeString ( this->fileSize() ); }
6 cycrow 3202
 
52 cycrow 3203
// used for a multiple spk file
197 cycrow 3204
unsigned char *CBaseFile::createData(size_t *size, CProgressInfo *progress)
6 cycrow 3205
{
213 cycrow 3206
	if ( this->writeFile(L"temp.dat", progress) ) {
197 cycrow 3207
		CFileIO File(L"temp.dat");
52 cycrow 3208
		File.setAutoDelete(true);
3209
		return File.readAll(size);
6 cycrow 3210
	}
3211
	return NULL;
3212
}
3213
 
3214
 
210 cycrow 3215
void CBaseFile::convertNormalMod(C_File *f, const Utils::WString &to) const
6 cycrow 3216
{
170 cycrow 3217
	C_File *match = this->findMatchingMod(f);
6 cycrow 3218
	if ( match )
3219
	{
3220
		// file link
3221
		if ( !match->GetData() )
3222
			match->ReadFromFile();
178 cycrow 3223
		match->changeBaseName(to);
6 cycrow 3224
	}
3225
 
3226
	// file link
3227
	if ( !f->GetData() )
3228
		f->ReadFromFile();
3229
 
178 cycrow 3230
	f->changeBaseName(to);
6 cycrow 3231
}
3232
 
170 cycrow 3233
void CBaseFile::convertAutoText(C_File *f) const
6 cycrow 3234
{
197 cycrow 3235
	Utils::WString to;
3236
	if ( f->baseName().contains(L"-L") )
3237
		to = L"0000-L" + f->baseName().token(L"-L", 2);
213 cycrow 3238
	else if ( f->baseName().contains(L"-l") )
197 cycrow 3239
		to = L"0000-L" + f->baseName().token(L"-l", 2);
6 cycrow 3240
	else
197 cycrow 3241
		to = f->baseName().left(-4) + L"0000";
6 cycrow 3242
 
3243
	// file link
3244
	if ( !f->GetData() )
3245
		f->ReadFromFile();
3246
 
178 cycrow 3247
	f->changeBaseName(to);
6 cycrow 3248
}
3249
 
170 cycrow 3250
void CBaseFile::convertFakePatch(C_File *f) const
6 cycrow 3251
{
3252
	// find next available fake patch
3253
	int num = 0;
3254
 
3255
	bool found = true;
3256
	while ( found )
3257
	{
3258
		++num;
3259
		found = false;
211 cycrow 3260
		Utils::WString find = Utils::WString::PadNumber(num, 2);
6 cycrow 3261
		for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
3262
		{
3263
			if ( node->Data()->GetFileType() != FILETYPE_MOD )
3264
				continue;
3265
			if ( !node->Data()->IsFakePatch() )
3266
				continue;
170 cycrow 3267
			if ( node->Data()->baseName().Compare(find) )
6 cycrow 3268
			{
3269
				found = true;
3270
				break;
3271
			}
3272
		}
3273
	}
3274
 
211 cycrow 3275
	Utils::WString to = Utils::WString::PadNumber(num, 2);
170 cycrow 3276
	C_File *match = this->findMatchingMod(f);
6 cycrow 3277
 
3278
	// file link
3279
	if ( !f->GetData() )
3280
		f->ReadFromFile();
3281
 
178 cycrow 3282
	f->changeBaseName(to);
6 cycrow 3283
	if ( match )
3284
	{
3285
		// file link
3286
		if ( !match->GetData() )
3287
			match->ReadFromFile();
178 cycrow 3288
		match->changeBaseName(to);
6 cycrow 3289
	}
3290
}
3291
 
170 cycrow 3292
C_File *CBaseFile::findMatchingMod(C_File *f) const
6 cycrow 3293
{
3294
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() )
3295
	{
3296
		if ( node->Data()->GetFileType() != FILETYPE_MOD )
3297
			continue;
3298
 
178 cycrow 3299
		if ( f->fileExt().Compare(node->Data()->fileExt()) )
6 cycrow 3300
			continue;
3301
 
178 cycrow 3302
		if ( f->baseName().Compare(node->Data()->baseName()) )
6 cycrow 3303
			return node->Data();
3304
	}
3305
 
3306
	return NULL;
3307
}
3308
 
210 cycrow 3309
void CBaseFile::renameFile(C_File *f, const Utils::WString &baseName) const
6 cycrow 3310
{
3311
	if ( f->GetFileType() == FILETYPE_MOD )
3312
	{
170 cycrow 3313
		C_File *match = this->findMatchingMod(f);
6 cycrow 3314
		if ( match )
178 cycrow 3315
			match->changeBaseName(baseName);
6 cycrow 3316
	}
3317
 
3318
	// need to edit the file
134 cycrow 3319
	if (f->GetFileType() == FILETYPE_SCRIPT || f->GetFileType() == FILETYPE_UNINSTALL)
178 cycrow 3320
		f->renameScript(baseName);
6 cycrow 3321
 
178 cycrow 3322
	f->changeBaseName(baseName);
6 cycrow 3323
}
3324
 
196 cycrow 3325
Utils::WString CBaseFile::createUpdateFile(const Utils::WString &dir) const
6 cycrow 3326
{
203 cycrow 3327
	Utils::WString file = this->getNameValidFile() + L"_" + this->author() + L".dat";
134 cycrow 3328
	file.removeChar(' ');
6 cycrow 3329
 
203 cycrow 3330
	Utils::WStringList write;
3331
	write.pushBack(L"Package: " + this->name());
3332
	write.pushBack(L"Author: " + this->author());
204 cycrow 3333
	write.pushBack(L"Version: " + this->version());
203 cycrow 3334
	write.pushBack(L"File: " + CFileIO(this->filename()).filename());
6 cycrow 3335
 
197 cycrow 3336
	CFileIO File(dir + L"/" + file);
134 cycrow 3337
	if (File.writeFile(&write))
102 cycrow 3338
		return File.fullFilename();
196 cycrow 3339
	return Utils::WString::Null();
6 cycrow 3340
}
3341
 
197 cycrow 3342
Utils::WString CBaseFile::ErrorString(int error, const Utils::WString &errorStr)
6 cycrow 3343
{
197 cycrow 3344
	if (error == SPKERR_NONE) return Utils::WString::Null();
6 cycrow 3345
 
197 cycrow 3346
	Utils::WString err;
6 cycrow 3347
 
126 cycrow 3348
	switch (error)
6 cycrow 3349
	{
126 cycrow 3350
	case SPKERR_MALLOC:
197 cycrow 3351
		err = L"Memory Failed";
126 cycrow 3352
		break;
3353
	case SPKERR_FILEOPEN:
197 cycrow 3354
		err = L"Failed to open file";
126 cycrow 3355
		break;
3356
	case SPKERR_FILEREAD:
197 cycrow 3357
		err = L"Failed to read file";
126 cycrow 3358
		break;
3359
	case SPKERR_UNCOMPRESS:
197 cycrow 3360
		err = L"Failed to Uncompress";
126 cycrow 3361
		break;
3362
	case SPKERR_WRITEFILE:
197 cycrow 3363
		err = L"Failed to write file";
126 cycrow 3364
		break;
3365
	case SPKERR_CREATEDIRECTORY:
197 cycrow 3366
		err = L"Failed to create directory";
126 cycrow 3367
		break;
3368
	case SPKERR_FILEMISMATCH:
197 cycrow 3369
		err = L"File count mismatch";
126 cycrow 3370
		break;
6 cycrow 3371
	}
3372
 
134 cycrow 3373
	if (!err.empty())
6 cycrow 3374
	{
134 cycrow 3375
		if (!errorStr.empty())
6 cycrow 3376
		{
197 cycrow 3377
			err += L" (";
3378
			err += errorStr + L")";
6 cycrow 3379
		}
3380
		return err;
3381
	}
3382
 
197 cycrow 3383
	return Utils::WString::Number((long)error);
6 cycrow 3384
}
3385
 
210 cycrow 3386
bool CBaseFile::saveToArchive(const Utils::WString &filename, int game, const CGameExe *exes, CProgressInfo *progress)
131 cycrow 3387
{
3388
	CDirIO Dir(CFileIO(filename).dir());
3389
	if (!Dir.exists())
3390
		Dir.create();
3391
 
210 cycrow 3392
	HZIP hz = CreateZip(filename.c_str(), 0);
126 cycrow 3393
	if (!hz) return false;
6 cycrow 3394
 
3395
	// read files and compress
3396
	ReadAllFilesToMemory();
126 cycrow 3397
	if (!UncompressAllFiles(progress))
6 cycrow 3398
	{
3399
		CloseZip(hz);
3400
		return false;
3401
	}
3402
 
126 cycrow 3403
	for (CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next())
6 cycrow 3404
	{
126 cycrow 3405
		if (game != -1) {
127 cycrow 3406
			if (game && !(node->Data()->game() & (1 << game)))
6 cycrow 3407
				continue;
127 cycrow 3408
			// extracting for all games, so ignore files that have a game set
3409
			if (!game && node->Data()->game() && node->Data()->game() != GAME_ALLNEW)
6 cycrow 3410
				continue;
3411
		}
197 cycrow 3412
		Utils::WString fname = node->Data()->getNameDirectory(this);
126 cycrow 3413
 
3414
		// use the addon directory
3415
		if (node->Data()->isFileInAddon() && exes)
3416
		{
127 cycrow 3417
			unsigned int whatGame = game;
126 cycrow 3418
			if (game == -1)
127 cycrow 3419
			{
3420
				unsigned int checkGame = node->Data()->game() & ~GAME_ALLNEW;
3421
				whatGame = 0;
3422
				for (int i = 0; i < 31; ++i)
3423
				{
3424
					if (1 << i == checkGame)
3425
					{
3426
						whatGame = i;
3427
						break;
3428
					}
3429
				}
3430
			}
126 cycrow 3431
 
127 cycrow 3432
			if (whatGame > 0)
126 cycrow 3433
			{
197 cycrow 3434
				SGameExe *e = exes->game(whatGame - 1);
127 cycrow 3435
				if (e)
3436
				{
3437
					if (e->iFlags & EXEFLAG_ADDON)
197 cycrow 3438
						fname = e->sAddon + L"/" + fname;
127 cycrow 3439
				}
126 cycrow 3440
			}
3441
		}
3442
 
6 cycrow 3443
		// create the directory
197 cycrow 3444
		//wsprintf(buf, L"%hs", fname.c_str());
127 cycrow 3445
		if (node->Data()->isExternalFile())
3446
		{
3447
			CFileIO file(node->Data()->filePointer());
3448
			size_t size = 0;
3449
			unsigned char *data = file.readAll(&size);
197 cycrow 3450
			ZipAdd(hz, fname.c_str(), data, size);
127 cycrow 3451
			delete data;
3452
		}
3453
		else
197 cycrow 3454
			ZipAdd(hz, fname.c_str(), node->Data()->GetData(), node->Data()->GetDataSize());
6 cycrow 3455
	}
3456
 
109 cycrow 3457
	// if its a ship, then add any generated files
3458
	this->addGeneratedFiles(hz);
3459
 
6 cycrow 3460
	// add the data file
210 cycrow 3461
	Utils::WStringList list;
3462
	Utils::WStringList addons;
127 cycrow 3463
	if ( this->GeneratePackagerScript(false, &list, game, addons, true) )
6 cycrow 3464
	{
210 cycrow 3465
		if ( CFileIO(L"test.tmp").writeFile(&list) )
6 cycrow 3466
		{
3467
			ZipAdd(hz, L"pluginmanager.txt", L"test.tmp");
210 cycrow 3468
			CFileIO::Remove(L"test.tmp");
6 cycrow 3469
		}
3470
	}
3471
 
3472
	CloseZip(hz);
3473
 
3474
	return true;
3475
}
3476
 
210 cycrow 3477
int CBaseFile::GetGameFromString(const Utils::WString &sGame)
6 cycrow 3478
{
3479
	int iGame = GAME_ALL;
210 cycrow 3480
	if ( sGame.Compare(L"ALL") )
6 cycrow 3481
		iGame = GAME_ALL;
210 cycrow 3482
	else if ( sGame.Compare(L"X3") )
6 cycrow 3483
		iGame = GAME_X3;
210 cycrow 3484
	else if ( sGame.Compare(L"X2") )
6 cycrow 3485
		iGame = GAME_X2;
210 cycrow 3486
	else if ( sGame.Compare(L"X3TC") )
6 cycrow 3487
		iGame = GAME_X3TC;
210 cycrow 3488
	else if (sGame.Compare(L"X3AP"))
6 cycrow 3489
		iGame = GAME_X3AP;
210 cycrow 3490
	else if (sGame.Compare(L"X3FL"))
126 cycrow 3491
		iGame = GAME_X3FL;
13 cycrow 3492
	else if ( sGame.isNumber() )
3493
		iGame = sGame;
6 cycrow 3494
 
3495
	return iGame;
3496
}
3497
 
197 cycrow 3498
Utils::WString CBaseFile::ConvertGameToString(int iGame)
6 cycrow 3499
{
197 cycrow 3500
	Utils::WString game = L"ALL";
6 cycrow 3501
 
3502
	switch(iGame) {
3503
		case GAME_ALL:
127 cycrow 3504
		case GAME_ALLNEW:
197 cycrow 3505
			game = L"ALL";
6 cycrow 3506
			break;
3507
		case GAME_X2:
197 cycrow 3508
			game = L"X2";
6 cycrow 3509
			break;
3510
		case GAME_X3:
197 cycrow 3511
			game = L"X3";
6 cycrow 3512
			break;
3513
		case GAME_X3TC:
197 cycrow 3514
			game = L"X3TC";
6 cycrow 3515
			break;
3516
		case GAME_X3AP:
197 cycrow 3517
			game = L"X3AP";
6 cycrow 3518
			break;
126 cycrow 3519
		case GAME_X3FL:
197 cycrow 3520
			game = L"X3FL";
126 cycrow 3521
			break;
6 cycrow 3522
		default:
3523
			game = (long)iGame;
3524
	}
3525
 
3526
	return game;
3527
}
3528
 
3529
bool CBaseFile::IsGameInPackage(int game)
3530
{
3531
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ) {
3532
		if ( node->Data()->GetGame() == game )
3533
			return true;
3534
	}
3535
 
3536
	return false;
3537
}
3538
 
3539
bool CBaseFile::IsAnyGameInPackage()
3540
{
3541
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ) {
3542
		if ( node->Data()->GetGame() )
3543
			return true;
3544
	}
3545
 
3546
	return false;
3547
}
3548
 
211 cycrow 3549
Utils::WString builtInWares()
88 cycrow 3550
{
211 cycrow 3551
	Utils::WString str;
3552
	str += L"28;0;0;0;0;59;5753;0;35714;1;1;0;35714;-100000;0;0;SS_WARE_SW_NEW1;\n";
3553
	str += L"28;0;0;0;0;60;5763;0;33232;1;1;0;33232;0;1043;0;SS_WARE_SW_NEW2;\n";
3554
	str += L"28;0;0;0;0;61;5773;0;21428;1;1;0;21428;0;1043;0;SS_WARE_SW_NEW3;\n";
3555
	str += L"28;0;0;0;0;62;5783;0;56;1;1;0;56;-100000;0;0;SS_WARE_SW_NEW4;\n";
3556
	str += L"28;0;0;0;0;63;5793;0;88;1;1;0;88;-100000;0;0;SS_WARE_SW_NEW5;\n";
3557
	str += L"28;0;0;0;0;64;5803;0;283;1;1;0;283;-100000;0;0;SS_WARE_SW_NEW6;\n";
3558
	str += L"28;0;0;0;0;65;5813;0;383;1;1;0;383;-100000;0;0;SS_WARE_SW_NEW7;\n";
3559
	str += L"28;0;0;0;0;66;5823;0;1389;1;1;0;1389;-100000;1043;0;SS_WARE_SW_NEW8;\n";
3560
	str += L"28;0;0;0;0;67;5833;0;3396;1;1;0;3396;-100000;0;0;SS_WARE_SW_NEW9;\n";
3561
	str += L"28;0;0;0;0;68;5843;0;4215;1;1;0;4215;-100000;0;0;SS_WARE_SW_NEW10;\n";
3562
	str += L"28;0;0;0;0;69;5853;0;5635;1;1;0;5635;-100000;0;0;SS_WARE_SW_NEW11;\n";
3563
	str += L"28;0;0;0;0;70;5863;0;65735;1;1;0;65735;-100000;0;0;SS_WARE_SW_NEW12;\n";
3564
	str += L"28;0;0;0;0;71;5873;0;17857;1;1;0;17857;333;1043;0;SS_WARE_SW_NEW13;\n";
3565
	str += L"28;0;0;0;0;72;5883;0;21428;1;1;0;21428;0;1043;0;SS_WARE_SW_NEW14;\n";
3566
	str += L"28;0;0;0;0;73;5893;0;324515;1;1;0;324515;-100000;0;0;SS_WARE_SW_NEW15;\n";
3567
	str += L"28;0;0;0;0;74;5903;0;638508;1;1;0;638508;-100000;0;0;SS_WARE_SW_NEW16;\n";
3568
	str += L"28;0;0;0;0;75;5913;0;225755;1;1;0;225755;-100000;0;0;SS_WARE_SW_NEW17;\n";
3569
	str += L"28;0;0;0;0;76;5923;0;1931535;1;1;0;1931535;1000;0;0;SS_WARE_SW_NEW18;\n";
3570
	str += L"28;0;0;0;0;77;5933;0;2209150;1;1;0;2209150;-100000;0;0;SS_WARE_SW_NEW19;\n";
3571
	str += L"28;0;0;0;0;78;5943;0;6727565;1;1;0;6727565;-100000;0;0;SS_WARE_SW_NEW20;\n";
3572
	str += L"28;0;0;0;0;85;9999;0;105;1;5;0;105;0;1043;0;SS_WARE_SW_X3TC_1;\n";
3573
	str += L"28;0;0;0;0;86;15053;0;105;1;5;0;105;0;1043;0;SS_WARE_SW_X3TC_2;\n";
3574
	str += L"28;0;0;0;0;87;15063;0;105;1;5;0;105;0;1043;0;SS_WARE_SW_X3TC_3;\n";
3575
	str += L"28;0;0;0;0;88;15073;0;105;1;5;0;105;0;1043;0;SS_WARE_SW_X3TC_4;\n";
3576
	str += L"28;0;0;0;0;89;15083;0;105;1;5;0;105;0;1043;0;SS_WARE_SW_X3TC_5;\n";
3577
	str += L"28;0;0;0;0;90;15093;0;105;1;5;0;105;0;1043;0;SS_WARE_SW_X3TC_6;\n";
88 cycrow 3578
 
3579
	return str;
3580
}
3581
 
197 cycrow 3582
void CBaseFile::_addWaresToList(int iLang, CLinkList<SWareEntry> &list, const Utils::WString &wares, enum WareTypes eType)
88 cycrow 3583
{
254 cycrow 3584
	if (_pTextDB)
3585
	{
3586
		std::vector<Utils::WString> w;
3587
		wares.tokenise(L"\n", w);
3588
 
3589
		for (size_t i = 0; i < w.size(); i++) {
3590
			int textId = w[i].token(L";", 7).toLong();
3591
			int useLang = iLang;
3592
			if (!_pTextDB->exists(useLang, 17, textId))
3593
				useLang = 44;
3594
			if (!_pTextDB->exists(useLang, 17, textId))
3595
				useLang = 49;
3596
			if (_pTextDB->exists(useLang, 17, textId)) {
3597
				SWareEntry* ware = new SWareEntry;
3598
				ware->name = _pTextDB->get(useLang, 17, textId);
3599
				ware->description = _pTextDB->get(useLang, 17, textId + 1);
3600
				ware->id = w[i].token(L";", -2);
3601
				ware->relval = w[i].token(L";", 9).toLong();
3602
				ware->notority = w[i].token(L";", 14).toLong();
3603
				ware->type = eType;
3604
				ware->position = i;
3605
				ware->package = this;
3606
				list.push_back(ware);
3607
			}
88 cycrow 3608
		}
3609
	}
3610
}
3611
 
197 cycrow 3612
bool CBaseFile::readWares(int iLang, CLinkList<SWareEntry> &list, const Utils::WString &empWares)
88 cycrow 3613
{
254 cycrow 3614
	if (_pTextDB)
3615
	{
3616
		_pTextDB->setLanguage(iLang);
88 cycrow 3617
 
254 cycrow 3618
		// now go through all emp wares and get the ones we have text for
3619
		_addWaresToList(iLang, list, empWares, Ware_EMP);
3620
		_addWaresToList(iLang, list, builtInWares(), Ware_BuiltIn);
88 cycrow 3621
 
254 cycrow 3622
		return true;
3623
	}
3624
 
3625
	return false;
89 cycrow 3626
}
88 cycrow 3627
 
89 cycrow 3628
bool CBaseFile::_readCommands(int iLang, int iStartID, CLinkList<SCommandSlot> &list)
3629
{
254 cycrow 3630
	if (_pTextDB)
3631
	{
3632
		_pTextDB->setLanguage(iLang);
89 cycrow 3633
 
254 cycrow 3634
		for (int i = 2; i <= 13; i++) {
3635
			for (int j = 0; j < 64; j++) {
3636
				int id = (i * 100) + j;
3637
				if (_pTextDB->exists(iLang, iStartID + 2, id)) {
3638
					SCommandSlot* slot = new SCommandSlot;
3639
					list.push_back(slot);
3640
 
3641
					slot->id = _pTextDB->get(iLang, iStartID, id);
3642
					slot->name = _pTextDB->get(iLang, iStartID + 2, id);
3643
					slot->shortName = _pTextDB->get(iLang, iStartID + 3, id);
3644
					slot->info = _pTextDB->get(iLang, iStartID + 14, id);
3645
					slot->slot = id;
3646
					slot->package = this;
3647
				}
3648
			}
3649
		}
3650
 
3651
		for (int i = 1400; i <= 2000; i++) {
3652
			if (_pTextDB->exists(iLang, iStartID + 2, i)) {
3653
				SCommandSlot* slot = new SCommandSlot;
89 cycrow 3654
				list.push_back(slot);
3655
 
254 cycrow 3656
				slot->id = _pTextDB->get(iLang, iStartID, i);
3657
				slot->name = _pTextDB->get(iLang, iStartID + 2, i);
3658
				slot->shortName = _pTextDB->get(iLang, iStartID + 3, i);
3659
				slot->info = _pTextDB->get(iLang, iStartID + 14, i);
3660
				slot->slot = i;
89 cycrow 3661
				slot->package = this;
254 cycrow 3662
			}
89 cycrow 3663
		}
3664
 
254 cycrow 3665
		for (int i = 6000; i <= 9999; i++) {
3666
			if (_pTextDB->exists(iLang, iStartID + 2, i)) {
3667
				SCommandSlot* slot = new SCommandSlot;
3668
				list.push_back(slot);
89 cycrow 3669
 
254 cycrow 3670
				slot->id = _pTextDB->get(iLang, iStartID, i);
3671
				slot->name = _pTextDB->get(iLang, iStartID + 2, i);
3672
				slot->shortName = _pTextDB->get(iLang, iStartID + 3, i);
3673
				slot->info = _pTextDB->get(iLang, iStartID + 14, i);
3674
				slot->slot = i;
3675
				slot->package = this;
3676
			}
89 cycrow 3677
		}
3678
 
254 cycrow 3679
		return true;
89 cycrow 3680
	}
3681
 
254 cycrow 3682
	return false;
88 cycrow 3683
}
3684
 
89 cycrow 3685
bool CBaseFile::readWingCommands(int iLang, CLinkList<SCommandSlot> &list)
3686
{
3687
	return _readCommands(iLang, 2028, list);
3688
}
3689
 
3690
bool CBaseFile::readCommands(int iLang, CLinkList<SCommandSlot> &list)
3691
{
3692
	return _readCommands(iLang, 2008, list);
3693
}
3694
 
6 cycrow 3695
int CBaseFile::FindFirstGameInPackage()
3696
{
3697
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ) {
3698
		if ( node->Data()->GetGame() )
3699
			return node->Data()->GetGame();
3700
	}
3701
 
3702
	return 0;
3703
}
3704
bool CBaseFile::IsMultipleGamesInPackage()
3705
{
3706
	int game = 0;
3707
	for ( CListNode<C_File> *node = m_lFiles.Front(); node; node = node->next() ) {
3708
		if ( node->Data()->GetGame() ) {
3709
			if ( game != node->Data()->GetGame() )
3710
				return true;
3711
			game = node->Data()->GetGame();
3712
		}
3713
	}
3714
 
3715
	return false;
3716
}