Subversion Repositories spk

Rev

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

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