Subversion Repositories spk

Rev

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

Rev Author Line No. Line
93 cycrow 1
 
2
#include "OriginalFiles.h"
3
#include "File.h"
4
#include "Logging/Log.h"
5
#include "BaseFile.h"
6
#include "spk.h"
7
//#include "ProgressInfo.h"
8
 
9
namespace SPK {
10
 
170 cycrow 11
	void AddLogEntry(int type, CyString args, CyStringList* errors)
12
	{
13
		if (errors) errors->PushBack(args, ERRORLOG_OLD(type));
14
	}
15
	void AddLogEntry(int type, const Utils::String &args, Utils::CStringList* errors)
16
	{
17
		if (errors) errors->pushBack(args, ERRORLOG(type));
18
	}
93 cycrow 19
 
20
 
21
COriginalFiles::COriginalFiles(const Utils::String &dir) : _sDir(dir)
22
{
23
}
24
 
25
COriginalFiles::~COriginalFiles(void)
26
{
27
	reset();
28
}
29
 
30
int COriginalFiles::count() const
31
{
32
	return _lFiles.size();
33
}
34
 
35
/**
36
 * Check for original file
37
 *
38
 * Checks if the file is an original file or not
39
 */
40
bool COriginalFiles::isOriginal(C_File *f) const
41
{
42
	if ( _getFile(f) )
43
		return true;
44
	return false;
45
}
46
 
105 cycrow 47
void COriginalFiles::installed(CBaseFile *package)
48
{
49
	for ( CListNode<C_File> *oNode = _lFiles.Front(); oNode; oNode = oNode->next() )
50
	{
51
		C_File *of = oNode->Data();
170 cycrow 52
		for ( CListNode<C_File> *checkNode = package->fileList().Front(); checkNode; checkNode = checkNode->next() )
105 cycrow 53
		{
54
			C_File *f = checkNode->Data();
55
 
56
			// match the same filetype
57
			if ( of->GetFileType() != f->GetFileType() )
58
				continue;
59
 
60
			// same file
158 cycrow 61
			if ( of->filename().Compare(f->filename()) )
105 cycrow 62
				_storeOverride(f);
63
		}
64
	}
65
}
66
 
93 cycrow 67
void COriginalFiles::backup(CBaseFile *package, CyStringList *errors)
68
{
69
	// backup any original files before installing
70
	CLog::log(CLog::Log_Install, 3, "Checking for any original files to backup");
71
	CDirIO oDir(_sDir + "/PluginManager/Original");
72
	for ( CListNode<C_File> *oNode = _lFiles.Front(); oNode; oNode = oNode->next() )
73
	{
74
		C_File *of = oNode->Data();
170 cycrow 75
		for ( CListNode<C_File> *checkNode = package->fileList().Front(); checkNode; checkNode = checkNode->next() )
93 cycrow 76
		{
77
			C_File *f = checkNode->Data();
78
 
79
			// match the same filetype
80
			if ( of->GetFileType() != f->GetFileType() )
81
				continue;
82
 
83
			// same file
158 cycrow 84
			if ( of->filename().Compare(f->filename()) )
93 cycrow 85
			{
86
				// check if original file already exists (assume already backed up)
87
				if ( !backupFile(of, errors) )
88
					continue;
89
				break;
90
			}
91
		}
92
	}
93
}
94
 
95
bool COriginalFiles::backupFile(C_File *f, CyStringList *errors)
96
{
121 cycrow 97
	Utils::String newDir = "PluginManager/Original/" + f->getDirectory(NULL);
93 cycrow 98
	CDirIO oDir(_sDir);
158 cycrow 99
	if ( oDir.exists(newDir + "/" + f->filename()) )
93 cycrow 100
		return true;
101
 
102
	// make sure the directory exissts
121 cycrow 103
	if ( !oDir.exists(newDir) )
93 cycrow 104
	{
160 cycrow 105
		if ( !oDir.create(newDir) )
93 cycrow 106
		{
107
			CLog::logf(CLog::Log_Install, 2, "Unable to create directory to backup original files, %s", newDir.c_str());
108
			AddLogEntry(SPKINSTALL_CREATEDIRECTORY_FAIL, newDir, errors);
109
			return false;
110
		}
111
 
112
		CLog::logf(CLog::Log_Install, 2, "Created new directory, %s", newDir.c_str());
113
		AddLogEntry(SPKINSTALL_CREATEDIRECTORY, newDir, errors);
114
	}
115
 
116
	// now lets copy the file
130 cycrow 117
	CFileIO CopyFile(f->filePointer());
158 cycrow 118
	if(CopyFile.copy(oDir.file(newDir + "/" + f->filename())))
93 cycrow 119
	{
120
		CLog::logf(CLog::Log_Install, 2, "Original file: %s has been backed up", f->GetNameDirectory(NULL).c_str());
121
		AddLogEntry(SPKINSTALL_ORIGINAL_BACKUP, f->GetNameDirectory(NULL), errors);
122
		return true;
123
	}
124
	else
125
	{
126
		CLog::logf(CLog::Log_Install, 2, "Failed to backup the original file: %s", f->GetNameDirectory(NULL).c_str());
127
		AddLogEntry(SPKINSTALL_ORIGINAL_BACKUP_FAIL, f->GetNameDirectory(NULL), errors);
128
		return false;
129
	}
130
}
131
 
132
bool COriginalFiles::doBackup(C_File *f, CyStringList *errors)
133
{
134
	bool backed = false;
135
 
136
	C_File *of = this->_getFile(f);
137
	if ( of ) {
138
		// check if the orignal file is already backed up
139
		if ( !CFileIO::Exists(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString()) )
140
		{
141
			// lets back up the file now
142
			backed = this->backupFile(of, errors);
143
		}
144
	}
145
 
146
	return backed;
147
}
148
 
149
 
150
int COriginalFiles::restoreAll(CProgressInfo *info, int files, int max)
151
{
152
	for ( CListNode<C_File> *oNode = _lFiles.Front(); oNode; oNode = oNode->next() )
153
	{
154
		// update the progress
155
		if ( info ) info->UpdateProgress(files, max);
156
		++files;
157
 
158
		C_File *f = oNode->Data();
159
		CFileIO of(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString());
160
 
161
		if ( of.exists() )
162
			of.Rename(_sDir + "/" + f->GetNameDirectory(NULL).ToString());
163
 
164
		delete oNode->Data();
165
	}
166
 
167
	_lFiles.clear();
168
 
169
	return files;
170
}
171
 
172
bool COriginalFiles::restoreFile(C_File *f, CyStringList *errors)
173
{
174
	bool original = false;
175
 
176
	// check if its an original file and restore
177
	if ( this->isOriginal(f) )
178
	{
179
		CFileIO of(_sDir + "/PluginManager/Original/" + f->GetNameDirectory(NULL).ToString());
180
		if ( of.exists() )
181
		{
182
			original = true;
183
			if ( of.Rename(_sDir + "/" + f->GetNameDirectory(NULL).ToString()) )
184
				AddLogEntry(SPKINSTALL_ORIGINAL_RESTORE, f->GetNameDirectory(NULL), errors);
185
			else
186
				AddLogEntry(SPKINSTALL_ORIGINAL_RESTORE_FAIL, f->GetNameDirectory(NULL), errors);
105 cycrow 187
 
188
			CFileIO backupFile(_sDir + "/PluginManager/Original/Replacements/" + f->GetNameDirectory(NULL).ToString());
189
			if ( backupFile.exists() ) backupFile.remove();
190
 
93 cycrow 191
		}
192
	}
193
 
194
	return original;
195
}
196
 
197
 
198
void COriginalFiles::parse(const Utils::String &data)
199
{
200
	C_File *uf = new C_File();
201
 
127 cycrow 202
	uf->setFileType((FileType)data.token(" ", 1).toLong());
93 cycrow 203
 
204
	// Extra files also contain a directory, so make sure we split that up
127 cycrow 205
	if (uf->fileType() == FILETYPE_EXTRA )
93 cycrow 206
	{
207
		uf->SetDir(data.tokens(" ", 2).tokens(":", 2));
208
		uf->SetFilename(data.tokens(" ", 2).token(":", 1));
209
	}
210
	else
211
		uf->SetFilename(data.tokens(" ", 2));
212
 
213
	// set the complete filename, GetNameDirectory returns the directory based on the file type
214
	uf->SetFilename(_sDir + "/" + uf->GetNameDirectory(NULL).ToString());
215
 
216
	_lFiles.push_back(uf);
217
}
218
 
219
void COriginalFiles::update(bool bForce, const CLinkList<C_File> *pFiles)
220
{
221
	if ( _lFiles.empty() || bForce )
222
	{
223
		_storeFiles(FILETYPE_SCRIPT, "scripts", pFiles);
224
		_storeFiles(FILETYPE_TEXT, "t", pFiles);
225
		_storeFiles(FILETYPE_SOUND, "soundtrack", pFiles);
226
		_storeFiles(FILETYPE_EXTRA, "mov", pFiles);
227
	}
228
}
229
 
160 cycrow 230
bool COriginalFiles::writeData(Utils::CStringList &lines)
93 cycrow 231
{
232
	bool addAny = false;
233
 
234
	if ( !_lFiles.empty() )
235
	{
236
		for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
237
		{
238
			C_File *uf = node->Data();
239
			Utils::String uString = "Original: ";
240
			uString += Utils::String::Number((long)uf->GetFileType()) + " ";
158 cycrow 241
			uString += uf->filename();
93 cycrow 242
 
243
			// add the directory for Extra files
244
			if ( uf->GetFileType() == FILETYPE_EXTRA && !uf->GetDir().Empty())
245
			{
246
				uString += ":";
160 cycrow 247
				uString += uf->dir();
93 cycrow 248
			}
249
 
160 cycrow 250
			lines.pushBack(uString);
93 cycrow 251
			addAny = true;
252
		}
253
	}
254
 
255
	return addAny;
256
}
257
 
258
 
259
void COriginalFiles::reset()
260
{
261
	_lFiles.MemoryClear();
262
}
263
 
264
 
265
/**
266
 * Update original files list
267
 *
268
 * Scan the current directory for any fiels that are already there, ie ones that have not been installed
269
 * Original files should be all the scripts/sounds, etc that are in an unmodified game directory
270
 *
271
 * Save list of files and check if any packages overright these files
272
 * Any file that gets overrighten from this list will automatically be backed up, and restored once the packages are removed
273
 */
127 cycrow 274
void COriginalFiles::_storeFiles(FileType filetype, const Utils::String &searchPath, const CLinkList<C_File> *pFiles)
93 cycrow 275
{
276
	Utils::String ext = "pck";
277
	switch ( filetype )
278
	{
279
		case FILETYPE_SOUND:
280
			ext = "mp3";
281
			break;
282
	}
283
 
284
	CDirIO Dir(_sDir + "/" + searchPath);
285
 
160 cycrow 286
	Utils::CStringList files;
287
	Dir.dirList(files);
288
	if (files.empty())
93 cycrow 289
		return;
290
 
160 cycrow 291
	for(auto itr = files.begin(); itr != files.end(); itr++)
93 cycrow 292
	{
160 cycrow 293
		CFileIO File(Dir.file((*itr)->str));
93 cycrow 294
 
295
		if ( File.extension().Compare(ext) )
296
			_add(filetype, File.filename(), searchPath, pFiles);
297
	}
298
}
299
 
300
/**
301
 * Get original file
302
 *
303
 * Finds a matching original file entry and returns it
304
 */
305
C_File *COriginalFiles::_getFile(C_File *file) const
306
{
307
	if ( !file ) return NULL;
308
 
309
	for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
310
	{
311
		C_File *of = node->Data();
312
 
313
		// not of the same file type
314
		if ( of->GetFileType() != file->GetFileType() )
315
			continue;
316
 
317
		// same file name, must be the same file
158 cycrow 318
		if ( of->filename().Compare(file->filename()) )
93 cycrow 319
			return of;
320
	}
321
 
322
	return NULL;
323
}
324
 
325
 
326
/**
327
 * Adds a file onto the original files list
328
 *
329
 * Checks if it already exists so we dont create multiples
330
 */
127 cycrow 331
void COriginalFiles::_add(FileType filetype, const Utils::String &filename, const Utils::String &searchPath, const CLinkList<C_File> *pFiles)
93 cycrow 332
{
333
	// dont add plugin manager as original files
334
	if ( filetype == FILETYPE_SCRIPT && filename.isin("!init.pmanager") )
335
		return;
336
 
337
	// first check if a matching one exists
338
	for ( CListNode<C_File> *node = _lFiles.Front(); node; node = node->next() )
339
	{
340
		C_File *file = node->Data();
341
		if ( file->GetFileType() != filetype )
342
			continue;
343
 
158 cycrow 344
		if ( file->filename().Compare(filename) )
93 cycrow 345
			return;
346
	}
347
 
348
	// check that no packages are currently using them either, not original if being used already
349
	for ( CListNode<C_File> *node = pFiles->Front(); node; node = node->next() )
350
	{
351
		C_File *file = node->Data();
352
		if ( file->GetFileType() != filetype )
353
			continue;
354
 
158 cycrow 355
		if ( file->filename().Compare(filename) )
93 cycrow 356
			return;
357
	}
358
 
359
	// add the file entry to the list
127 cycrow 360
	C_File *of = new C_File(filename);
361
	of->setFileType(filetype);
362
	if (filetype == FILETYPE_EXTRA)
160 cycrow 363
		of->setDir(searchPath);
364
	of->setFilename(_sDir + "/" + of->getNameDirectory(NULL));
93 cycrow 365
 
366
	_lFiles.push_back(of);
367
}
368
 
105 cycrow 369
void COriginalFiles::_storeOverride(C_File *f)
370
{
371
	CDirIO oDir(_sDir + "/PluginManager/Original/Replacements");
160 cycrow 372
	if ( !oDir.exists() ) oDir.create();
373
	CFileIO file(oDir.file(f->getNameDirectory(NULL)));
374
	if ( !file.GetDirIO().exists() ) file.GetDirIO().create();
375
	CFileIO fromFile(f->filePointer());
105 cycrow 376
	fromFile.copy(file.fullFilename(), true);
93 cycrow 377
}
105 cycrow 378
 
379
}