Subversion Repositories spk

Rev

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