|
a/src/internfile/internfile.cpp |
|
b/src/internfile/internfile.cpp |
|
... |
|
... |
149 |
} else {
|
149 |
} else {
|
150 |
return ipath;
|
150 |
return ipath;
|
151 |
}
|
151 |
}
|
152 |
}
|
152 |
}
|
153 |
|
153 |
|
154 |
// Uncompress input file into a temporary one, by executing the appropriate
|
|
|
155 |
// script.
|
|
|
156 |
static bool uncompressfile(RclConfig *conf, const string& ifn,
|
|
|
157 |
const vector<string>& cmdv, TempDir& tdir,
|
|
|
158 |
string& tfile)
|
|
|
159 |
{
|
|
|
160 |
// Make sure tmp dir is empty. we guarantee this to filters
|
|
|
161 |
if (!tdir.ok() || !tdir.wipe()) {
|
|
|
162 |
LOGERR(("uncompressfile: can't clear temp dir %s\n", tdir.dirname()));
|
|
|
163 |
return false;
|
|
|
164 |
}
|
|
|
165 |
string cmd = cmdv.front();
|
|
|
166 |
|
|
|
167 |
// Substitute file name and temp dir in command elements
|
|
|
168 |
vector<string>::const_iterator it = cmdv.begin();
|
|
|
169 |
++it;
|
|
|
170 |
vector<string> args;
|
|
|
171 |
map<char, string> subs;
|
|
|
172 |
subs['f'] = ifn;
|
|
|
173 |
subs['t'] = tdir.dirname();
|
|
|
174 |
for (; it != cmdv.end(); it++) {
|
|
|
175 |
string ns;
|
|
|
176 |
pcSubst(*it, ns, subs);
|
|
|
177 |
args.push_back(ns);
|
|
|
178 |
}
|
|
|
179 |
|
|
|
180 |
// Execute command and retrieve output file name, check that it exists
|
|
|
181 |
ExecCmd ex;
|
|
|
182 |
int status = ex.doexec(cmd, args, 0, &tfile);
|
|
|
183 |
if (status || tfile.empty()) {
|
|
|
184 |
LOGERR(("uncompressfile: doexec: failed for [%s] status 0x%x\n",
|
|
|
185 |
ifn.c_str(), status));
|
|
|
186 |
if (!tdir.wipe()) {
|
|
|
187 |
LOGERR(("uncompressfile: wipedir failed\n"));
|
|
|
188 |
}
|
|
|
189 |
return false;
|
|
|
190 |
}
|
|
|
191 |
if (tfile[tfile.length() - 1] == '\n')
|
|
|
192 |
tfile.erase(tfile.length() - 1, 1);
|
|
|
193 |
return true;
|
|
|
194 |
}
|
|
|
195 |
|
|
|
196 |
// Delete temporary uncompressed file
|
|
|
197 |
void FileInterner::tmpcleanup()
|
|
|
198 |
{
|
|
|
199 |
if (m_tfile.empty())
|
|
|
200 |
return;
|
|
|
201 |
if (unlink(m_tfile.c_str()) < 0) {
|
|
|
202 |
LOGERR(("FileInterner::tmpcleanup: unlink(%s) errno %d\n",
|
|
|
203 |
m_tfile.c_str(), errno));
|
|
|
204 |
return;
|
|
|
205 |
}
|
|
|
206 |
}
|
|
|
207 |
|
|
|
208 |
// Constructor: identify the input file, possibly create an
|
154 |
// Constructor: identify the input file, possibly create an
|
209 |
// uncompressed temporary copy, and create the top filter for the
|
155 |
// uncompressed temporary copy, and create the top filter for the
|
210 |
// uncompressed file type.
|
156 |
// uncompressed file type.
|
211 |
//
|
157 |
//
|
212 |
// Empty handler on return says that we're in error, this will be
|
158 |
// Empty handler on return says that we're in error, this will be
|
213 |
// processed by the first call to internfile().
|
159 |
// processed by the first call to internfile().
|
214 |
// Split into "constructor calls init()" to allow use from other constructor
|
160 |
// Split into "constructor calls init()" to allow use from other constructor
|
215 |
FileInterner::FileInterner(const string &fn, const struct stat *stp,
|
161 |
FileInterner::FileInterner(const string &fn, const struct stat *stp,
|
216 |
RclConfig *cnf,
|
|
|
217 |
TempDir& td, int flags, const string *imime)
|
162 |
RclConfig *cnf, int flags, const string *imime)
|
218 |
: m_tdir(td), m_ok(false), m_missingdatap(0)
|
163 |
: m_ok(false), m_missingdatap(0), m_uncomp((flags & FIF_forPreview) != 0)
|
219 |
{
|
164 |
{
|
220 |
LOGDEB0(("FileInterner::FileInterner(fn=%s)\n", fn.c_str()));
|
165 |
LOGDEB0(("FileInterner::FileInterner(fn=%s)\n", fn.c_str()));
|
221 |
if (fn.empty()) {
|
166 |
if (fn.empty()) {
|
222 |
LOGERR(("FileInterner::FileInterner: empty file name!\n"));
|
167 |
LOGERR(("FileInterner::FileInterner: empty file name!\n"));
|
223 |
return;
|
168 |
return;
|
|
... |
|
... |
283 |
if (m_cfg->getUncompressor(l_mime, ucmd)) {
|
228 |
if (m_cfg->getUncompressor(l_mime, ucmd)) {
|
284 |
// Check for compressed size limit
|
229 |
// Check for compressed size limit
|
285 |
int maxkbs = -1;
|
230 |
int maxkbs = -1;
|
286 |
if (!m_cfg->getConfParam("compressedfilemaxkbs", &maxkbs) ||
|
231 |
if (!m_cfg->getConfParam("compressedfilemaxkbs", &maxkbs) ||
|
287 |
maxkbs < 0 || !stp || int(stp->st_size / 1024) < maxkbs) {
|
232 |
maxkbs < 0 || !stp || int(stp->st_size / 1024) < maxkbs) {
|
288 |
if (!uncompressfile(m_cfg, m_fn, ucmd, m_tdir, m_tfile)) {
|
233 |
if (!m_uncomp.uncompressfile(m_fn, ucmd, m_tfile)) {
|
289 |
return;
|
234 |
return;
|
290 |
}
|
235 |
}
|
291 |
LOGDEB1(("FileInterner:: after ucomp: m_tdir %s, tfile %s\n",
|
236 |
LOGDEB1(("FileInterner:: after ucomp: tfile %s\n",
|
292 |
m_tdir.dirname(), m_tfile.c_str()));
|
237 |
m_tfile.c_str()));
|
293 |
m_fn = m_tfile;
|
238 |
m_fn = m_tfile;
|
294 |
// Stat the uncompressed file, mainly to get the size
|
239 |
// Stat the uncompressed file, mainly to get the size
|
295 |
struct stat ucstat;
|
240 |
struct stat ucstat;
|
296 |
if (stat(m_fn.c_str(), &ucstat) != 0) {
|
241 |
if (stat(m_fn.c_str(), &ucstat) != 0) {
|
297 |
LOGERR(("FileInterner: can't stat the uncompressed file"
|
242 |
LOGERR(("FileInterner: can't stat the uncompressed file"
|
|
... |
|
... |
350 |
m_ok = true;
|
295 |
m_ok = true;
|
351 |
}
|
296 |
}
|
352 |
|
297 |
|
353 |
// Setup from memory data (ie: out of the web cache). imime needs to be set.
|
298 |
// Setup from memory data (ie: out of the web cache). imime needs to be set.
|
354 |
FileInterner::FileInterner(const string &data, RclConfig *cnf,
|
299 |
FileInterner::FileInterner(const string &data, RclConfig *cnf,
|
355 |
TempDir& td, int flags, const string& imime)
|
300 |
int flags, const string& imime)
|
356 |
: m_tdir(td), m_ok(false), m_missingdatap(0)
|
301 |
: m_ok(false), m_missingdatap(0), m_uncomp((flags & FIF_forPreview) != 0)
|
357 |
{
|
302 |
{
|
358 |
LOGDEB0(("FileInterner::FileInterner(data)\n"));
|
303 |
LOGDEB0(("FileInterner::FileInterner(data)\n"));
|
359 |
initcommon(cnf, flags);
|
304 |
initcommon(cnf, flags);
|
360 |
init(data, cnf, flags, imime);
|
305 |
init(data, cnf, flags, imime);
|
361 |
}
|
306 |
}
|
|
... |
|
... |
414 |
for (unsigned int i = 0; i < MAXHANDLERS; i++)
|
359 |
for (unsigned int i = 0; i < MAXHANDLERS; i++)
|
415 |
m_tmpflgs[i] = false;
|
360 |
m_tmpflgs[i] = false;
|
416 |
m_targetMType = cstr_textplain;
|
361 |
m_targetMType = cstr_textplain;
|
417 |
}
|
362 |
}
|
418 |
|
363 |
|
419 |
FileInterner::FileInterner(const Rcl::Doc& idoc, RclConfig *cnf,
|
364 |
FileInterner::FileInterner(const Rcl::Doc& idoc, RclConfig *cnf, int flags)
|
420 |
TempDir& td, int flags)
|
365 |
: m_ok(false), m_missingdatap(0), m_uncomp(((flags & FIF_forPreview) != 0))
|
421 |
: m_tdir(td), m_ok(false), m_missingdatap(0)
|
|
|
422 |
{
|
366 |
{
|
423 |
LOGDEB0(("FileInterner::FileInterner(idoc)\n"));
|
367 |
LOGDEB0(("FileInterner::FileInterner(idoc)\n"));
|
424 |
initcommon(cnf, flags);
|
368 |
initcommon(cnf, flags);
|
425 |
|
369 |
|
426 |
DocFetcher *fetcher = docFetcherMake(idoc);
|
370 |
DocFetcher *fetcher = docFetcherMake(idoc);
|
|
... |
|
... |
460 |
return ret;
|
404 |
return ret;
|
461 |
}
|
405 |
}
|
462 |
|
406 |
|
463 |
FileInterner::~FileInterner()
|
407 |
FileInterner::~FileInterner()
|
464 |
{
|
408 |
{
|
465 |
tmpcleanup();
|
|
|
466 |
for (vector<Dijon::Filter*>::iterator it = m_handlers.begin();
|
409 |
for (vector<Dijon::Filter*>::iterator it = m_handlers.begin();
|
467 |
it != m_handlers.end(); it++) {
|
410 |
it != m_handlers.end(); it++) {
|
468 |
returnMimeHandler(*it);
|
411 |
returnMimeHandler(*it);
|
469 |
}
|
412 |
}
|
470 |
// m_tempfiles will take care of itself
|
413 |
// m_tempfiles will take care of itself
|
|
... |
|
... |
1010 |
RclConfig *cnf, const Rcl::Doc& idoc)
|
953 |
RclConfig *cnf, const Rcl::Doc& idoc)
|
1011 |
{
|
954 |
{
|
1012 |
LOGDEB(("FileInterner::idocToFile\n"));
|
955 |
LOGDEB(("FileInterner::idocToFile\n"));
|
1013 |
idoc.dump();
|
956 |
idoc.dump();
|
1014 |
|
957 |
|
1015 |
TempDir tmpdir;
|
|
|
1016 |
|
|
|
1017 |
// We set FIF_forPreview for consistency with the previous version
|
958 |
// We set FIF_forPreview for consistency with the previous version
|
1018 |
// which determined this by looking at mtype!=null. Probably
|
959 |
// which determined this by looking at mtype!=null. Probably
|
1019 |
// doesn't change anything in this case.
|
960 |
// doesn't change anything in this case.
|
1020 |
FileInterner interner(idoc, cnf, tmpdir, FIF_forPreview);
|
961 |
FileInterner interner(idoc, cnf, FIF_forPreview);
|
1021 |
interner.setTargetMType(idoc.mimetype);
|
962 |
interner.setTargetMType(idoc.mimetype);
|
1022 |
return interner.interntofile(otemp, tofile, idoc.ipath, idoc.mimetype);
|
963 |
return interner.interntofile(otemp, tofile, idoc.ipath, idoc.mimetype);
|
1023 |
}
|
964 |
}
|
1024 |
|
965 |
|
1025 |
bool FileInterner::interntofile(TempFile& otemp, const string& tofile,
|
966 |
bool FileInterner::interntofile(TempFile& otemp, const string& tofile,
|
|
... |
|
... |
1100 |
return true;
|
1041 |
return true;
|
1101 |
}
|
1042 |
}
|
1102 |
return false;
|
1043 |
return false;
|
1103 |
}
|
1044 |
}
|
1104 |
|
1045 |
|
|
|
1046 |
// Static.
|
1105 |
bool FileInterner::maybeUncompressToTemp(TempFile& temp, const string& fn,
|
1047 |
bool FileInterner::maybeUncompressToTemp(TempFile& temp, const string& fn,
|
1106 |
RclConfig *cnf, const Rcl::Doc& doc)
|
1048 |
RclConfig *cnf, const Rcl::Doc& doc)
|
1107 |
{
|
1049 |
{
|
1108 |
LOGDEB(("FileInterner::maybeUncompressToTemp: [%s]\n", fn.c_str()));
|
1050 |
LOGDEB(("FileInterner::maybeUncompressToTemp: [%s]\n", fn.c_str()));
|
1109 |
struct stat st;
|
1051 |
struct stat st;
|
|
... |
|
... |
1129 |
maxkbs >= 0 && int(st.st_size / 1024) > maxkbs) {
|
1071 |
maxkbs >= 0 && int(st.st_size / 1024) > maxkbs) {
|
1130 |
LOGINFO(("FileInterner:: %s over size limit %d kbs\n",
|
1072 |
LOGINFO(("FileInterner:: %s over size limit %d kbs\n",
|
1131 |
fn.c_str(), maxkbs));
|
1073 |
fn.c_str(), maxkbs));
|
1132 |
return false;
|
1074 |
return false;
|
1133 |
}
|
1075 |
}
|
1134 |
TempDir tmpdir;
|
|
|
1135 |
temp =
|
1076 |
temp =
|
1136 |
TempFile(new TempFileInternal(cnf->getSuffixFromMimeType(doc.mimetype)));
|
1077 |
TempFile(new TempFileInternal(cnf->getSuffixFromMimeType(doc.mimetype)));
|
1137 |
if (!tmpdir.ok() || !temp->ok()) {
|
1078 |
if (!temp->ok()) {
|
1138 |
LOGERR(("FileInterner: cant create temporary file/dir"));
|
1079 |
LOGERR(("FileInterner: cant create temporary file"));
|
1139 |
return false;
|
1080 |
return false;
|
1140 |
}
|
1081 |
}
|
1141 |
|
1082 |
|
|
|
1083 |
Uncomp uncomp;
|
1142 |
string uncomped;
|
1084 |
string uncomped;
|
1143 |
if (!uncompressfile(cnf, fn, ucmd, tmpdir, uncomped)) {
|
1085 |
if (!uncomp.uncompressfile(fn, ucmd, uncomped)) {
|
1144 |
return false;
|
1086 |
return false;
|
1145 |
}
|
1087 |
}
|
1146 |
|
1088 |
|
1147 |
// uncompressfile choses the output file name, there is good
|
1089 |
// uncompressfile choses the output file name, there is good
|
1148 |
// reason for this, but it's not nice here. Have to move, the
|
1090 |
// reason for this, but it's not nice here. Have to move, the
|
|
... |
|
... |
1231 |
struct stat st;
|
1173 |
struct stat st;
|
1232 |
if (stat(fn.c_str(), &st)) {
|
1174 |
if (stat(fn.c_str(), &st)) {
|
1233 |
perror("stat");
|
1175 |
perror("stat");
|
1234 |
exit(1);
|
1176 |
exit(1);
|
1235 |
}
|
1177 |
}
|
1236 |
TempDir tmp;
|
|
|
1237 |
FileInterner interner(fn, &st, config, tmp, 0);
|
1178 |
FileInterner interner(fn, &st, config, 0);
|
1238 |
Rcl::Doc doc;
|
1179 |
Rcl::Doc doc;
|
1239 |
FileInterner::Status status = interner.internfile(doc, ipath);
|
1180 |
FileInterner::Status status = interner.internfile(doc, ipath);
|
1240 |
switch (status) {
|
1181 |
switch (status) {
|
1241 |
case FileInterner::FIDone:
|
1182 |
case FileInterner::FIDone:
|
1242 |
case FileInterner::FIAgain:
|
1183 |
case FileInterner::FIAgain:
|