Subversion Repositories spk

Rev

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