3 #include "nel/misc/types_nl.h"
4 #include "nel/misc/app_context.h"
5 #include "nel/misc/path.h"
6 #include "nel/misc/common.h"
7 #include "nel/misc/sstring.h"
8 #include "nel/misc/algo.h"
11 using namespace NLMISC
;
20 const string
DefaultExt("xml_pack");
21 const uint32 MaxLineSize
= 16*1024;
23 const string
ExcludeFiles(".#*;*.log;*.bin");
24 const string
ExcludeDirs("CVS");
26 bool isExcludedFile(const std::string
&fileName
)
28 static vector
<string
> excludeFileVect
;
29 static bool init
= false;
33 explode(ExcludeFiles
, ";", excludeFileVect
, true);
37 bool excluded
= false;
39 for (uint i
=0; i
<excludeFileVect
.size(); ++i
)
41 if (testWildCard(fileName
, excludeFileVect
[i
]))
51 bool isExcludedDir(const std::string
&dirName
)
53 static vector
<string
> excludeDirVect
;
54 static bool init
= false;
58 explode(ExcludeDirs
, ";", excludeDirVect
, true);
61 bool excluded
= false;
63 for (uint i
=0; i
<excludeDirVect
.size(); ++i
)
65 if (testWildCard(dirName
, excludeDirVect
[i
]))
75 string
getLastDirName(const std::string
&path
)
78 string::size_type pos
= path
.size()-1;
80 // skip any terminal directory separator
81 if (pos
> 0 && (path
[pos
] == '\\' || path
[pos
] == '/'))
84 while(pos
> 0 && path
[pos
] != '\\' && path
[pos
] != '/' )
85 dirName
= path
[pos
--] + dirName
;
90 int main(int argc
, char *argv
[])
92 printf("XML Packer/Unpacker V0.1\n(C) Nevrax 2006\n");
93 CApplicationContext appContext
;
95 TAction action
= undefined
;
96 bool recursive
= false;
98 // compute the current folder name
99 string currentPath
= CPath::getCurrentPath();
100 string dirName
= getLastDirName(currentPath
);;
102 string filename
= dirName
+ "."+DefaultExt
;
104 // check the params to choose action
105 for (uint i
=0; i
<uint(argc
); ++i
)
107 if (strcmp(argv
[i
], "-p") == 0)
109 // pack the current folder
111 printf("Packing files\n");
113 else if (strcmp(argv
[i
], "-u") == 0)
115 // unpack the current folder
117 printf("Unpacking files\n");
119 else if (strcmp(argv
[i
], "-r") == 0)
121 // unpack the current folder
123 printf("Recursive mode\n");
125 // else if (strcmp(argv[i], "-f") == 0)
127 // if (uint(argc) < i+i)
129 // printf("Error : missing file name after -f\n");
132 // // use the specified file archive instead of the directory name
133 // filename = argv[++i];
137 if (action
== undefined
)
139 printf("Usage : %s -u|-p [-r] [-f <filename>]\n", argv
[0]);
140 printf(" -p : pack the current folder\n");
141 printf(" -u : unpack the current folder\n");
142 printf(" -r : pack or unpack subdirectories recursively\n");
143 // printf(" -f <filename> : use the specified filename instead of current directory name\n");
148 vector
<string
> dirStack
;
150 printf("Current patch is '%s'\n", CPath::getCurrentPath().c_str());
152 // push the current directory to start the loop
153 dirStack
.push_back(CPath::getCurrentPath());
156 while(!dirStack
.empty())
158 string dirName
= dirStack
.back();
160 string filename
= dirName
+"/"+getLastDirName(dirName
) + "."+DefaultExt
;
165 printf("Packing directory '%s'...\n", dirName
.c_str());
166 // string packFileName = dirName+"/tmp."+DefaultExt;
167 string packFileName
= filename
;
169 // get the current directory content
170 vector
<string
> files
;
171 CPath::getPathContent(dirName
, false, false, true, files
);
173 vector
<string
> validFiles
;
175 // first loop to build the list of valid file
176 for (uint i
=0; i
<files
.size(); ++i
)
178 if (files
[i
].find(DefaultExt
) != string::npos
)
181 string
&subFileName
= files
[i
];
183 // check exclude filter
184 if (isExcludedFile(subFileName
))
189 // ok, this file is valid
190 validFiles
.push_back(subFileName
);
193 bool needRepack
= true;
195 // if an xml pack already exist in the folder...
196 if (CFile::fileExists(packFileName
))
198 uint32 packDate
= CFile::getFileModificationDate(packFileName
);
199 // loop to check for file time stamp
200 for (uint i
=0; i
<validFiles
.size(); ++i
)
202 uint32 fileDate
= CFile::getFileModificationDate(validFiles
[i
]);
204 if (fileDate
>= packDate
)
209 // all files are older than the pack file ! no repack needed
215 // open the pack file
216 // FILE *fp = nlfopen(filename, "wt");
217 FILE *fp
= nlfopen(packFileName
, "wt");
219 fprintf(fp
, "<packed_xml>\n");
221 for (uint i
=0; i
<validFiles
.size(); ++i
)
223 string
&subFileName
= validFiles
[i
];
225 printf("Adding file '%s'...\n", CFile::getFilename(subFileName
).c_str());
226 fprintf(fp
, " <xml_file name=\"%s\">\n", CFile::getFilename(subFileName
).c_str());
228 FILE *subFp
= nlfopen(subFileName
, "rt");
229 nlassert(subFp
!= NULL
);
230 char buffer
[MaxLineSize
];
232 bool needFinalReturn
= false;
233 result
= fgets(buffer
, MaxLineSize
, subFp
);
234 needFinalReturn
= result
!= NULL
? buffer
[strlen(buffer
)-1] != '\n' : true;
238 result
= fgets(buffer
, MaxLineSize
, subFp
);
239 needFinalReturn
= result
!= NULL
? buffer
[strlen(buffer
)-1] != '\n' : needFinalReturn
;
243 char *finalReturn
= "\n";
244 fputs(finalReturn
, fp
);
249 fprintf(fp
, " </nel:xml_file>\n");
252 fprintf(fp
, "</nel:packed_xml>\n");
258 printf("Directory %s is up to date, no repack\n", dirName
.c_str());
264 printf("Unpacking directory '%s'...\n", dirName
.c_str());
265 // open the pack file
266 // FILE *fp = nlfopen(dirName+"/tmp."+DefaultExt, "rt");
267 FILE *fp
= nlfopen(filename
, "rt");
268 nlassert(fp
!= NULL
);
271 // read the first line
272 char buffer
[MaxLineSize
];
273 fgets(buffer
, MaxLineSize
, fp
);
275 if (strcmp(buffer
, "<nel:packed_xml>\n") != 0)
277 printf ("Error : invalid pack file '%s'\n", filename
.c_str());
285 fgets(buffer
, MaxLineSize
, fp
);
286 CSString
parser(buffer
);
288 if (parser
.find(" <nel:xml_file name=") != 0)
290 if (parser
.find("</nel:packed_xml>") == 0)
296 printf ("Error : invalid pack file '%s' at line %u", filename
.c_str(), linecount
);
300 CSString subFileName
= parser
.leftCrop(sizeof(" <nel:xml_file name=")-1);
301 subFileName
= subFileName
.matchDelimiters(false, false, true, false);
302 subFileName
= subFileName
.unquoteIfQuoted();
303 subFileName
= dirName
+"/"+subFileName
;
305 printf("Extracting file '%s'...\n", CFile::getFilename(subFileName
).c_str());
306 // open the output file
307 FILE *output
= nlfopen(subFileName
, "wt");
310 printf ("Error : can not open output file '%s' from pack file '%s'", subFileName
.c_str(), filename
.c_str());
314 result
= fgets(buffer
, MaxLineSize
, fp
);
316 while (result
!= NULL
&& strcmp(buffer
, " </nel:xml_file>\n") != 0)
318 fputs(result
, output
);
320 result
= fgets(buffer
, MaxLineSize
, fp
);
326 } while(result
!= NULL
);
334 vector
<string
> subDirs
;
335 CPath::getPathContent(dirName
, false, true, false, subDirs
);
337 // filter the directories
338 for (uint i
=subDirs
.size(); i
>0; --i
)
340 if (!isExcludedDir(subDirs
[i
-1]))
341 dirStack
.push_back(subDirs
[i
-1]);