Subversion Repositories spk

Rev

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

Rev Author Line No. Line
1 cycrow 1
#include <spk.h>
305 cycrow 2
#include "Utils/CommandLine.h"
3
 
1 cycrow 4
void PrintError ( int err )
5
{
6
	switch ( err )
7
	{
8
		case CATERR_NODATFILE:
9
			printf ( "No dat file found\n" );
10
			break;
11
		case CATERR_NOCATFILE:
12
			printf ( "Unable to open cat file\n" );
13
			break;
14
		case CATERR_FILEEMPTY:
15
			printf ( "Cat file is empty\n" );
16
			break;
17
		case CATERR_READCAT:
18
			printf ( "Unable to read cat file\n" );
19
			break;
20
		case CATERR_DECRYPT:
21
			printf ( "Unable to decrypt cat file\n" );
22
			break;
23
		case CATERR_MISMATCH:
317 cycrow 24
			printf("Dat file size mismatch\n");
1 cycrow 25
			break;
317 cycrow 26
		case CATERR_CREATED:
27
			printf("Cat file does not exist\n");
28
			break;
322 cycrow 29
		default:
30
			printf("Unknown error code: %d\n", err);
31
			break;
1 cycrow 32
	}
33
}
34
 
316 cycrow 35
void ListFiles(const Utils::CommandLine &cmd)
1 cycrow 36
{
316 cycrow 37
	const Utils::WString& filename = cmd.arg(1);
38
	const Utils::WString& searchmask = cmd.arg(2);
39
 
320 cycrow 40
	CFileIO File(!filename.contains(L":") ? CDirIO(cmd.cmdDir()).file(filename) : filename);
316 cycrow 41
	if(!File.exists())
42
		File.open(filename);
43
	if (!File.exists())
44
	{
322 cycrow 45
		wprintf(L"Error: Cat file: %s, does not exist\n", filename.c_str());
316 cycrow 46
		return;
47
	}
48
 
49
	wprintf(L"Listing files in %s...", filename.c_str());
197 cycrow 50
	if (!searchmask.empty())
51
		wprintf(L"(%s)", searchmask.c_str() );
52
	printf("\n");
1 cycrow 53
 
54
	CCatFile catfile;
316 cycrow 55
	int err = catfile.open(File.fullFilename(), L"", CATREAD_CATDECRYPT);
1 cycrow 56
 
316 cycrow 57
	int listed = 0;
1 cycrow 58
	if ( err == CATERR_NONE )
59
	{
322 cycrow 60
		wprintf(L"Opened file\n" );
61
		for (size_t i = 0; i < catfile.GetNumFiles(); i++)
1 cycrow 62
		{
63
			SInCatFile *file = catfile.GetFile ( i );
322 cycrow 64
			if (file)
65
			{
66
				if (!searchmask.empty())
67
				{
68
					if (!file->sFile.match(searchmask))
69
						continue;
70
				}
1 cycrow 71
 
322 cycrow 72
				wprintf(L"[%9s] %s\n", SPK::GetSizeString(static_cast<unsigned long>(file->lSize)).c_str(), file->sFile.c_str());
73
				++listed;
1 cycrow 74
			}
75
		}
316 cycrow 76
 
77
		if (!searchmask.empty())
78
			wprintf(L"\nListed Files: [%d/%d]", listed, static_cast<int>(catfile.GetNumFiles()));
1 cycrow 79
	}
80
	else
81
		PrintError ( err );
82
}
83
 
314 cycrow 84
void findAllFiles(const CDirIO &dirIO, const Utils::WString& dir, const Utils::WString& filepattern, Utils::WStringList& list)
85
{
86
	Utils::WStringList dirList;
87
	if (dirIO.dirList(dirList, dir, filepattern, true))
88
	{
322 cycrow 89
		for (const auto& entry : dirList)
314 cycrow 90
		{
322 cycrow 91
			if (dirIO.isDir(entry->str))
92
				findAllFiles(dirIO, entry->str, filepattern, list);
314 cycrow 93
			else
322 cycrow 94
				list.pushBack(entry->str);
314 cycrow 95
		}
96
	}
97
}
98
 
320 cycrow 99
bool findFiles(Utils::WStringList &files, const Utils::WString &filepattern, const Utils::CommandLine &cmd)
127 cycrow 100
{
320 cycrow 101
	CFileIO File((filepattern.contains(L":")) ? filepattern : cmd.cmdDir() + L"/" + filepattern);
305 cycrow 102
	return File.GetDirIO().dirList(files, Utils::WString::Null(), File.filename(), true);
127 cycrow 103
}
1 cycrow 104
 
127 cycrow 105
 
317 cycrow 106
void ExtractFile (const Utils::CommandLine& cmd, const Utils::WString& fileMask, bool preserve)
1 cycrow 107
{
317 cycrow 108
	Utils::WString filename = cmd.arg(1) + fileMask;
109
	Utils::WString to = cmd.argCount() < 2 ? cmd.cmdDir() : cmd.arg(2);
110
	if (!to.contains(L":")) to = cmd.file()->dirIO().file(to);
111
	CDirIO destination(to);
112
 
113
	if (cmd.hasSwitch("preserve"))
114
		preserve = true;
115
 
222 cycrow 116
	if ( !filename.contains(L"::") ) return;
41 cycrow 117
 
222 cycrow 118
	Utils::WString catfile = filename.token(L"::", 1);
320 cycrow 119
	CFileIO File((catfile.contains(L":")) ? catfile : cmd.cmdDir() + L"/" + catfile);
222 cycrow 120
	Utils::WString filemask = filename.token(L"::", 2);
1 cycrow 121
 
122
	CCatFile cat;
317 cycrow 123
	int err = cat.open(File.fullFilename(), L"", CATREAD_DAT);
1 cycrow 124
	if ( err )
125
	{
126
		PrintError ( err );
127
		return;
128
	}
129
 
317 cycrow 130
	Utils::WStringList fileList;
131
	if (filemask.containsAny(L"*?"))
1 cycrow 132
	{
322 cycrow 133
		for (size_t i = 0; i < cat.GetNumFiles(); i++)
1 cycrow 134
		{
317 cycrow 135
			SInCatFile* f = cat.GetFile(i);
322 cycrow 136
			if(f && f->sFile.match(filemask))
317 cycrow 137
				fileList.pushBack(f->sFile);
1 cycrow 138
		}
139
	}
317 cycrow 140
	else
141
		fileList.pushBack(filemask);
1 cycrow 142
 
222 cycrow 143
	if (fileList.empty())
1 cycrow 144
	{
222 cycrow 145
		wprintf(L"Error: unable to find any files matching: %s\n", filemask.c_str() );
1 cycrow 146
		return;
147
	}
148
 
222 cycrow 149
	for (auto itr = fileList.begin(); itr != fileList.end(); itr++)
1 cycrow 150
	{
222 cycrow 151
		Utils::WString file = (*itr)->str;
152
		if (!cat.extractFile(file, to, preserve))
197 cycrow 153
			wprintf(L"Error: %s\n", cat.getErrorString().c_str() );
1 cycrow 154
		else
317 cycrow 155
			wprintf(L"File has been written: %s\n", preserve ? file.c_str() : CFileIO(file).filename().c_str());
1 cycrow 156
	}
157
}
158
 
314 cycrow 159
void AppendFile (const Utils::CommandLine& cmd)
1 cycrow 160
{
314 cycrow 161
	Utils::WString sFile = cmd.arg(2);
162
	Utils::WString filepattern = cmd.arg(1);
197 cycrow 163
	Utils::WString catfile;
164
	Utils::WString file;
1 cycrow 165
 
314 cycrow 166
	bool recursive = cmd.hasSwitch(L"recursive");
167
 
276 cycrow 168
	Utils::WString C_File = sFile.findReplace(L"\\", L"/");
1 cycrow 169
	bool doFile = false;
276 cycrow 170
	if ( !C_File.contains(L"::"))
1 cycrow 171
	{
276 cycrow 172
		catfile = C_File;
1 cycrow 173
		doFile = true;
174
	}
175
	else
176
	{
276 cycrow 177
		catfile = C_File.token(L"::", 1);
305 cycrow 178
		file = C_File.token(L"::", 2);
1 cycrow 179
	}
180
 
305 cycrow 181
	if (!catfile.contains(":"))
320 cycrow 182
		catfile = cmd.cmdDir() + L"/" + catfile;
305 cycrow 183
 
197 cycrow 184
	Utils::WStringList list;
314 cycrow 185
 
320 cycrow 186
	CFileIO File((filepattern.contains(L":")) ? filepattern : cmd.cmdDir() + L"/" + filepattern);
314 cycrow 187
	if (recursive)
188
		findAllFiles(File.dirIO(), L"", File.filename(), list);
189
	else
320 cycrow 190
		findFiles(list, filepattern, cmd);
158 cycrow 191
	if (!list.size())
1 cycrow 192
	{
197 cycrow 193
		wprintf(L"Error: no files found to add: %s\n", filepattern.c_str());
1 cycrow 194
		return;
195
	}
196
 
197
	CCatFile cat;
197 cycrow 198
	int err = cat.open(catfile, L"", CATREAD_CATDECRYPT);
305 cycrow 199
	if ( err && err != CATERR_CREATED)
1 cycrow 200
	{
201
		PrintError ( err );
202
		return;
203
	}
204
 
314 cycrow 205
 
206
	int added = 0;
158 cycrow 207
	for (auto itr = list.begin(); itr != list.end(); itr++)
1 cycrow 208
	{
314 cycrow 209
		if (File.dirIO().isDir((*itr)->str))
210
			continue;
211
 
197 cycrow 212
		Utils::WString filename = (*itr)->str;
305 cycrow 213
		Utils::WString toFile = file;
314 cycrow 214
		if (doFile)			
215
			toFile = File.dirIO().relativePath(filename);;
1 cycrow 216
 
305 cycrow 217
		if (!toFile.contains(L"."))
1 cycrow 218
		{
316 cycrow 219
			if (toFile[static_cast<unsigned long>(toFile.length() - 1)] != L'/')
305 cycrow 220
				toFile += L"/";
221
			toFile += CFileIO(filename).filename();
1 cycrow 222
		}
223
 
314 cycrow 224
		++added;
305 cycrow 225
		if (cat.appendFile(filename, toFile))
226
			wprintf(L"File %s has beed added to: %s::%s\n", filename.c_str(), catfile.c_str(), toFile.c_str());
1 cycrow 227
		else
197 cycrow 228
			wprintf(L"Error: Unable to add file: %s\n", filename.c_str());
1 cycrow 229
	}
314 cycrow 230
 
231
	if(!added)
232
		wprintf(L"Warning: Nothing to add: %s\n", filepattern.c_str());
1 cycrow 233
}
234
 
320 cycrow 235
void RemoveFile (const Utils::CommandLine &cmd)
1 cycrow 236
{
320 cycrow 237
	Utils::WString C_File = cmd.arg(1);
238
	Utils::WString remfile = cmd.arg(2);
239
 
240
	CFileIO File((C_File.contains(L":")) ? C_File : cmd.cmdDir() + L"/" + C_File);
1 cycrow 241
	// first open the cat file
242
	CCatFile cat;
320 cycrow 243
	int err = cat.open(File.fullFilename(), L"", CATREAD_CATDECRYPT);
1 cycrow 244
	if ( err )
245
	{
246
		PrintError ( err );
247
		return;
248
	}
249
 
320 cycrow 250
	std::vector<Utils::WString> files;
251
	if (remfile.containsAny(L"*?"))
1 cycrow 252
	{
322 cycrow 253
		for (size_t i = 0; i < cat.GetNumFiles(); i++)
320 cycrow 254
		{
255
			SInCatFile* f = cat.GetFile(i);
322 cycrow 256
			if (f && f->sFile.match(remfile))
320 cycrow 257
				files.push_back(f->sFile);
258
		}
1 cycrow 259
	}
320 cycrow 260
	else
261
		files.push_back(remfile);
1 cycrow 262
 
320 cycrow 263
	for (auto itr = files.begin(); itr != files.end(); itr++)
264
	{
265
		if (!cat.removeFile(*itr))
266
			wprintf(L"Unable to find %s in cat file\n", itr->c_str());
267
		else
268
			wprintf(L"%s: has been removed from archive\n", itr->c_str());
269
	}
1 cycrow 270
}
271
 
320 cycrow 272
void UnpackFile(const Utils::CommandLine &cmd)
1 cycrow 273
{
320 cycrow 274
	const Utils::WString& file = cmd.arg(1);
275
	const Utils::WString & tofile = cmd.arg(2);
276
	const Utils::WString& ext = cmd.switchData(L"ext");
277
 
197 cycrow 278
	Utils::WStringList list;
320 cycrow 279
	if(!findFiles(list, file, cmd) || !list.size())
1 cycrow 280
	{
226 cycrow 281
		wprintf(L"Error: no files found to unpack: %s\n", file.c_str());
1 cycrow 282
		return;
283
	}
284
 
276 cycrow 285
	for(auto itr = list.first(); itr; itr = list.next())
1 cycrow 286
	{
312 cycrow 287
		Utils::WString filename = itr->str;
1 cycrow 288
 
289
		C_File f(filename);
276 cycrow 290
		if (!f.CheckValidFilePointer())
291
		{
320 cycrow 292
			CFileIO File((file.contains(L":")) ? file : cmd.cmdDir() + L"/" + file);
276 cycrow 293
			filename = File.GetDirIO().file(itr->str);
294
			f.setFilename(filename);
295
		}
296
 
297
		Utils::WString oldFilename = f.filename();
298
 
1 cycrow 299
		if ( !f.CheckValidFilePointer() )
197 cycrow 300
			wprintf(L"Error: %s doesn't exists\n", filename.c_str() );
1 cycrow 301
		else if ( !f.ReadFromFile() )
197 cycrow 302
			wprintf(L"Error: unable to open file: %s\n", filename.c_str() );
1 cycrow 303
		else
304
		{
312 cycrow 305
			if(!f.UnPCKFile())
306
				wprintf(L"Error: unable to unpack file: %s\n", filename.c_str());
1 cycrow 307
			else
312 cycrow 308
			{
309
				if (tofile.empty())
310
					f.changeFileExt(ext.empty() ? L"xml" : ext);
311
				else if (tofile.left(2) == L"*.")
312
					f.changeFileExt(CFileIO(tofile).extension().toString());
313
				else
314
					f.setFilename(tofile);
1 cycrow 315
 
312 cycrow 316
				if (!f.writeFilePointer())
317
					wprintf(L"Error: unable to write file: %s\n", tofile.c_str());
318
				else
319
					wprintf(L"%s has been unpacked to %s\n", oldFilename.c_str(), f.filename().c_str());
320
			}
1 cycrow 321
		}
322
	}
323
}
324
 
320 cycrow 325
void PackFile(const Utils::CommandLine &cmd)
1 cycrow 326
{
320 cycrow 327
	const Utils::WString& file = cmd.arg(1);
328
	const Utils::WString& tofile = cmd.arg(2);
329
 
197 cycrow 330
	Utils::WStringList list;
320 cycrow 331
	if(!findFiles(list, file, cmd) || !list.size())
1 cycrow 332
	{
276 cycrow 333
		wprintf(L"Error: no files found to pack: %s\n", file.c_str());
1 cycrow 334
		return;
335
	}
336
 
127 cycrow 337
	for(auto itr = list.first(); itr; itr = list.next())
1 cycrow 338
	{
312 cycrow 339
		Utils::WString filename = itr->str;
1 cycrow 340
 
341
		C_File f(filename);
342
		if ( !f.CheckValidFilePointer() )
197 cycrow 343
			wprintf(L"Error: %s doesn't exists\n", filename.c_str() );
1 cycrow 344
		else if ( !f.ReadFromFile() )
197 cycrow 345
			wprintf(L"Error: unable to open file: %s\n", filename.c_str() );
1 cycrow 346
		else if ( !f.PCKFile() )
197 cycrow 347
			wprintf(L"Error: unable to pack file: %s\n", filename.c_str() );
1 cycrow 348
		else
349
		{
185 cycrow 350
			if ( tofile.empty() )
1 cycrow 351
			{
197 cycrow 352
				if ( f.checkFileExt(L"bob") )
353
					f.changeFileExt(L"pbb");
354
				else if ( f.checkFileExt(L"bod") )
355
					f.changeFileExt(L"pbd");
1 cycrow 356
				else
197 cycrow 357
					f.changeFileExt(L"pck");
1 cycrow 358
			}
197 cycrow 359
			else if ( tofile.left(2) == L"*." )
185 cycrow 360
				f.changeFileExt(tofile.right(3));
1 cycrow 361
			else
185 cycrow 362
				f.setFilename(tofile);
1 cycrow 363
 
129 cycrow 364
			if ( !f.writeFilePointer() )
276 cycrow 365
				wprintf(L"Error: unable to write file: %s\n", tofile.c_str() );
1 cycrow 366
			else
320 cycrow 367
				wprintf(L"%s has been packed to %s\n", CFileIO(filename).filename().c_str(), f.filename().c_str());
1 cycrow 368
		}
369
	}
370
}
371
 
298 cycrow 372
void PrintSyntax(const Utils::WString &cmd)
1 cycrow 373
{
298 cycrow 374
	wprintf(L"Syntax: %s <flags> [arguments]\n", cmd.c_str() );
375
	wprintf(L"Flags:\n");
376
	wprintf(L"\t-l <filename> [filemask]\n");
377
	wprintf(L"\t\tLists the contents of a cat file, with optional search mask\n");
317 cycrow 378
	wprintf(L"\t-x [--preserve] <catfile::filemask> [dir]\n");
322 cycrow 379
	wprintf(L"\t\textracts a file from a cat file to the optional directory\n\t--preserve: Preserves directory structure");
298 cycrow 380
	wprintf(L"\t-xa <catfile> [dir]\n");
381
	wprintf(L"\t\textracts all files to optional directory\n");
382
	wprintf(L"\t-a <filename> <catfile::tofile>\n");
383
	wprintf(L"\t\tAdds the file into a cat archive, saves it as <tofile>\n");
384
	wprintf(L"\t-r <catfile> <file>\n");
385
	wprintf(L"\t\tRemoves a file from an archive\n");
386
	wprintf(L"\t[--ext:EXTENSION] -u <filename> [tofile]\n");
387
	wprintf(L"\t\tUnpacks a file, ie from pck to xml/txt\n");
388
	wprintf(L"\t-p <filename> <tofile>\n");
389
	wprintf(L"\t\tPacks a file, ie from xml/txt to pck\n");
1 cycrow 390
}
391
 
392
int main ( int argc, char **argv )
393
{
316 cycrow 394
	printf ( "\nCATPCK Tool V1.22 17/05/2025 (SPK: %.2f) Created by Cycrow\n\n", GetLibraryVersion() );
1 cycrow 395
 
396
	// parse the cmd name
305 cycrow 397
	Utils::CommandLine cmd(argc, argv);
276 cycrow 398
 
1 cycrow 399
	if ( argc < 2 )
305 cycrow 400
		PrintSyntax(cmd.cmdName());
1 cycrow 401
	else
402
	{
305 cycrow 403
		Utils::WString command(cmd.arg(0).lower());
1 cycrow 404
 
305 cycrow 405
		auto& args = cmd.args();
276 cycrow 406
 
407
		if ( (command == L"-l") || (command == L"-list") )
408
		{
316 cycrow 409
			if (cmd.argCount() < 2)
305 cycrow 410
				wprintf(L"Syntax: %s -l <filename> [filemask]\n\tLists the contents of the cat file\n", cmd.cmdName().c_str());
1 cycrow 411
			else
316 cycrow 412
				ListFiles(cmd);
1 cycrow 413
		}
317 cycrow 414
		else if ((command == L"-x") || (command == L"-extract"))
1 cycrow 415
		{
317 cycrow 416
			if (cmd.argCount() < 2 )
417
				wprintf(L"Syntax: %s %s [--preserve] <catfile::filemask> [dir]\n\tExtracts a file from the cat archive\n", cmd.cmdName().c_str(), command.c_str() );
1 cycrow 418
			else
317 cycrow 419
				ExtractFile (cmd, L"", false);
1 cycrow 420
		}
276 cycrow 421
		else if ( (command == L"-xa") || (command == L"-extractall") )
1 cycrow 422
		{
317 cycrow 423
			if (cmd.argCount() < 2)
305 cycrow 424
				wprintf(L"Syntax: %s %s <catfile> [dir]\n\tExtracts all files from the cat archive\n", cmd.cmdName().c_str(), command.c_str() );
1 cycrow 425
			else
317 cycrow 426
				ExtractFile(cmd, L"::*", true);
1 cycrow 427
		}
276 cycrow 428
		else if ( (command == L"-a") || (command == L"-append") )
1 cycrow 429
		{
320 cycrow 430
			if (cmd.argCount() < 3 )
305 cycrow 431
				wprintf(L"Syntax: %s -a <filename> <catfile::tofile>\n\tAppends a file into the archive\n", cmd.cmdName().c_str() );
1 cycrow 432
			else
314 cycrow 433
				AppendFile(cmd);
1 cycrow 434
		}
276 cycrow 435
		else if ( (command == L"-r") || (command == L"-remove") )
1 cycrow 436
		{
320 cycrow 437
			if (cmd.argCount() < 3 )
305 cycrow 438
				wprintf(L"Syntax: %s -r <catfile> <filename>\n\tRemoves a file from the archive\n", cmd.cmdName().c_str() );
1 cycrow 439
			else
320 cycrow 440
				RemoveFile(cmd);
1 cycrow 441
		}
276 cycrow 442
		else if ( (command == L"-u") || (command == L"-unpack") )
1 cycrow 443
		{
320 cycrow 444
			if (cmd.argCount() < 2 )
305 cycrow 445
				wprintf(L"Syntax: %s [--ext:EXTENSION] -u <filename> [to]\n\tUnpacks a file", cmd.cmdName().c_str() );
1 cycrow 446
			else
320 cycrow 447
				UnpackFile(cmd);
1 cycrow 448
		}
276 cycrow 449
		else if ( (command == L"-p") || (command == L"-pack") )
1 cycrow 450
		{
320 cycrow 451
			if (cmd.argCount() < 2 )
305 cycrow 452
				wprintf(L"Syntax: %s -p <filename> [to]\n\tPacks a file to .pck", cmd.cmdName().c_str() );
1 cycrow 453
			else
320 cycrow 454
				PackFile(cmd);
1 cycrow 455
		}
456
		else
457
		{
322 cycrow 458
			wprintf(L"Invalid flag: %s\n\n", command.c_str());
305 cycrow 459
			PrintSyntax(cmd.cmdName());
1 cycrow 460
		}
461
	}
462
 
463
#ifdef _DEBUG
464
	char pause;
465
	printf ( "\n\nPress a key to end\n" );
466
	scanf ( "%c", &pause );
467
#endif
468
 
469
	return 0;
470
}
471