merged branch 1.25 fixes

This commit is contained in:
Jean-Francois Dockes 2019-08-09 11:54:39 +02:00
commit d4c099ab59
31 changed files with 1583 additions and 1145 deletions

View File

@ -112,10 +112,10 @@ overriden in the c++ code by ifdefs _WIN32 anyway */
#define PACKAGE_NAME "Recoll" #define PACKAGE_NAME "Recoll"
/* Define to the full name and version of this package. */ /* Define to the full name and version of this package. */
#define PACKAGE_STRING "Recoll 1.25.19" #define PACKAGE_STRING "Recoll 1.25.21"
/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "1.25.19" #define PACKAGE_VERSION "1.25.21"
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "recoll" #define PACKAGE_TARNAME "recoll"

View File

@ -1559,6 +1559,9 @@ vector<string> RclConfig::getSkippedPaths() const
// don't do this. // don't do this.
skpl.push_back(getDbDir()); skpl.push_back(getDbDir());
skpl.push_back(getConfDir()); skpl.push_back(getConfDir());
#ifdef _WIN32
skpl.push_back(TempFile::rcltmpdir());
#endif
if (getCacheDir().compare(getConfDir())) { if (getCacheDir().compare(getConfDir())) {
skpl.push_back(getCacheDir()); skpl.push_back(getCacheDir());
} }

View File

@ -92,11 +92,11 @@ alink="#0000FF">
"#RCL.INDEXING.INTRODUCTION.CONFIG">Configurations, "#RCL.INDEXING.INTRODUCTION.CONFIG">Configurations,
multiple indexes</a></span></dt> multiple indexes</a></span></dt>
<dt><span class="sect2">2.1.3. <a href= <dt><span class="sect2">2.1.3. <a href=
"#idm218">Document types</a></span></dt> "#idm233">Document types</a></span></dt>
<dt><span class="sect2">2.1.4. <a href= <dt><span class="sect2">2.1.4. <a href=
"#idm259">Indexing failures</a></span></dt> "#idm274">Indexing failures</a></span></dt>
<dt><span class="sect2">2.1.5. <a href= <dt><span class="sect2">2.1.5. <a href=
"#idm271">Recovery</a></span></dt> "#idm286">Recovery</a></span></dt>
</dl> </dl>
</dd> </dd>
<dt><span class="sect1">2.2. <a href= <dt><span class="sect1">2.2. <a href=
@ -851,10 +851,10 @@ alink="#0000FF">
</div> </div>
<p><span class="application">Recoll</span> supports <p><span class="application">Recoll</span> supports
defining multiple indexes, each defined by its own defining multiple indexes, each defined by its own
<a class="link" href="#RCL.INDEXING.CONFIG" title= configuration directory. A configuration directory
"2.3.&nbsp;Index configuration">configuration contains <a class="link" href="#RCL.INDEXING.CONFIG"
directory</a>, in which several configuration files title="2.3.&nbsp;Index configuration">several files</a>
describe what should be indexed and how.</p> which describe what should be indexed and how.</p>
<p>When <span class= <p>When <span class=
"command"><strong>recoll</strong></span> or <span class= "command"><strong>recoll</strong></span> or <span class=
"command"><strong>recollindex</strong></span> is first "command"><strong>recollindex</strong></span> is first
@ -864,14 +864,14 @@ alink="#0000FF">
is located in <code class= is located in <code class=
"filename">$HOME/.recoll/</code> for <span class= "filename">$HOME/.recoll/</code> for <span class=
"application">Unix</span>-like systems and <code class= "application">Unix</span>-like systems and <code class=
"filename">%LOCALAPPDATA%</code> on <span class= "filename">%LOCALAPPDATA%\Recoll</code> on <span class=
"application">Windows</span> (typically <code class= "application">Windows</span> (typically <code class=
"filename">C:\Users\[me]\Appdata\Local</code>).</p> "filename">C:\Users\[me]\Appdata\Local\Recoll</code>).</p>
<p>All configuration parameters have defaults, defined in <p>All configuration parameters have defaults, defined in
system-wide files. Without further customisation, the system-wide files. Without further customisation, the
default configuration will process your complete home default configuration will process your complete home
directory, with a reasonable set of defaults. It can be directory, with a reasonable set of defaults. It can be
changed to process a different area of the file system, adjusted to process a different area of the file system,
select files in different ways, and many other select files in different ways, and many other
things.</p> things.</p>
<p>In some cases, it may be useful to create additional <p>In some cases, it may be useful to create additional
@ -879,6 +879,35 @@ alink="#0000FF">
personal and shared indexes, or to take advantage of the personal and shared indexes, or to take advantage of the
organization of your data to improve search organization of your data to improve search
precision.</p> precision.</p>
<p>In order to do this, you would create an empty
directory in a location of your choice, and then instruct
<span class="command"><strong>recoll</strong></span> or
<span class="command"><strong>recollindex</strong></span>
to use it by setting either a command line option
(<code class="literal">-c</code> <em class=
"replaceable"><code>/some/directory</code></em>), or an
environment variable (<code class=
"envar">RECOLL_CONFDIR</code>=<em class=
"replaceable"><code>/some/directory</code></em>). Any
modification performed by the commands (e.g.
configuration customisation or searches by <span class=
"command"><strong>recoll</strong></span> or index
creation by <span class=
"command"><strong>recollindex</strong></span>) would then
apply to the new directory and not to the default
one.</p>
<p>Once multiple indexes are created, you can use each of
them separately by setting the <code class=
"literal">-c</code> option or the <code class=
"envar">RECOLL_CONFDIR</code> environment variable when
starting a command, to select the desired index.</p>
<p>It is also possible to instruct one configuration to
query one or several other indexes in addition to its
own, by using the <span class="guimenuitem">External
index</span> function in the <span class=
"command"><strong>recoll</strong></span> GUI, or some
other functions in the command line and programming
tools.</p>
<p>A plausible usage scenario for the multiple index <p>A plausible usage scenario for the multiple index
feature would be for a system administrator to set up a feature would be for a system administrator to set up a
central index for shared data, that you choose to search central index for shared data, that you choose to search
@ -904,8 +933,8 @@ alink="#0000FF">
<div class="titlepage"> <div class="titlepage">
<div> <div>
<div> <div>
<h3 class="title"><a name="idm218" id= <h3 class="title"><a name="idm233" id=
"idm218"></a>2.1.3.&nbsp;Document types</h3> "idm233"></a>2.1.3.&nbsp;Document types</h3>
</div> </div>
</div> </div>
</div> </div>
@ -1002,8 +1031,8 @@ alink="#0000FF">
<div class="titlepage"> <div class="titlepage">
<div> <div>
<div> <div>
<h3 class="title"><a name="idm259" id= <h3 class="title"><a name="idm274" id=
"idm259"></a>2.1.4.&nbsp;Indexing failures</h3> "idm274"></a>2.1.4.&nbsp;Indexing failures</h3>
</div> </div>
</div> </div>
</div> </div>
@ -1038,8 +1067,8 @@ alink="#0000FF">
<div class="titlepage"> <div class="titlepage">
<div> <div>
<div> <div>
<h3 class="title"><a name="idm271" id= <h3 class="title"><a name="idm286" id=
"idm271"></a>2.1.5.&nbsp;Recovery</h3> "idm286"></a>2.1.5.&nbsp;Recovery</h3>
</div> </div>
</div> </div>
</div> </div>
@ -1390,8 +1419,8 @@ alink="#0000FF">
<div class="titlepage"> <div class="titlepage">
<div> <div>
<div> <div>
<h4 class="title"><a name="idm392" id= <h4 class="title"><a name="idm407" id=
"idm392"></a>In practise: creating and using an "idm407"></a>In practise: creating and using an
additional index</h4> additional index</h4>
</div> </div>
</div> </div>

View File

@ -377,22 +377,23 @@
<title>Configurations, multiple indexes</title> <title>Configurations, multiple indexes</title>
<para>&RCL; supports defining multiple indexes, each defined by its <para>&RCL; supports defining multiple indexes, each defined by its
own <link linkend="RCL.INDEXING.CONFIG">configuration directory</link>, own configuration directory. A configuration directory contains
in which several configuration files describe <link linkend="RCL.INDEXING.CONFIG">several files</link> which
what should be indexed and how.</para> describe what should be indexed and how.</para>
<para>When <command>recoll</command> or <para>When <command>recoll</command> or
<command>recollindex</command> is first executed, it creates a <command>recollindex</command> is first executed, it creates a
default configuration directory. This configuration is the one used default configuration directory. This configuration is the one used
for indexing and querying when no specific configuration is for indexing and querying when no specific configuration is
specified. It is located in <filename>$HOME/.recoll/</filename> for specified. It is located in <filename>$HOME/.recoll/</filename> for
&LIN; and <filename>%LOCALAPPDATA%</filename> on &WIN; &LIN; and <filename>%LOCALAPPDATA%\Recoll</filename> on &WIN;
(typically <filename>C:\Users\[me]\Appdata\Local</filename>).</para> (typically
<filename>C:\Users\[me]\Appdata\Local\Recoll</filename>).</para>
<para>All configuration parameters have defaults, defined in <para>All configuration parameters have defaults, defined in
system-wide files. Without further customisation, the default system-wide files. Without further customisation, the default
configuration will process your complete home directory, with a configuration will process your complete home directory, with a
reasonable set of defaults. It can be changed to process a reasonable set of defaults. It can be adjusted to process a
different area of the file system, select files in different ways, different area of the file system, select files in different ways,
and many other things.</para> and many other things.</para>
@ -401,6 +402,29 @@
shared indexes, or to take advantage of the organization of your shared indexes, or to take advantage of the organization of your
data to improve search precision.</para> data to improve search precision.</para>
<para>In order to do this, you would create an empty directory in a
location of your choice, and then instruct
<command>recoll</command> or <command>recollindex</command> to use
it by setting either a command line option (<literal>-c</literal>
<replaceable>/some/directory</replaceable>), or an environment
variable
(<envar>RECOLL_CONFDIR</envar>=<replaceable>/some/directory</replaceable>).
Any modification performed by the commands (e.g. configuration
customisation or searches by <command>recoll</command> or index
creation by <command>recollindex</command>) would then apply to the
new directory and not to the default one.</para>
<para>Once multiple indexes are created, you can use each of them
separately by setting the <literal>-c</literal> option or the
<envar>RECOLL_CONFDIR</envar> environment variable when starting a
command, to select the desired index.</para>
<para>It is also possible to instruct one configuration to
query one or several other indexes in addition to its own, by using
the <guimenuitem>External index</guimenuitem> function in the
<command>recoll</command> GUI, or some other functions in the
command line and programming tools.</para>
<para>A plausible usage scenario for the multiple index feature <para>A plausible usage scenario for the multiple index feature
would be for a system administrator to set up a central index for would be for a system administrator to set up a central index for
shared data, that you choose to search or not in addition to your shared data, that you choose to search or not in addition to your

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2005 J.F.Dockes /* Copyright (C) 2005-2019 J.F.Dockes
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
@ -14,302 +14,34 @@
* Free Software Foundation, Inc., * Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifndef TEST_MH_MBOX
#include "autoconfig.h"
#include <stdio.h> #include "autoconfig.h"
#define _FILE_OFFSET_BITS 64
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#include "safesysstat.h"
#include <time.h> #include <time.h>
#include <cstring> #include <cstring>
#include <map> #include <map>
#include <mutex> #include <mutex>
#include <fstream>
#include "cstr.h" #include "cstr.h"
#include "mimehandler.h" #include "mimehandler.h"
#include "log.h" #include "log.h"
#include "readfile.h"
#include "mh_mbox.h" #include "mh_mbox.h"
#include "smallut.h" #include "smallut.h"
#include "rclconfig.h" #include "rclconfig.h"
#include "md5ut.h" #include "md5ut.h"
#include "conftree.h" #include "conftree.h"
#include "pathut.h"
using namespace std; using namespace std;
// Define maximum message size for safety. 100MB would seem reasonable // Define maximum message size for safety. 100MB would seem reasonable
static const unsigned int max_mbox_member_size = 100 * 1024 * 1024; static const unsigned int max_mbox_member_size = 100 * 1024 * 1024;
class FpKeeper {
public:
FpKeeper(FILE **fpp) : m_fpp(fpp) {}
~FpKeeper()
{
if (m_fpp && *m_fpp) {
fclose(*m_fpp);
*m_fpp = 0;
}
}
private: FILE **m_fpp;
};
static std::mutex o_mcache_mutex;
/**
* Handles a cache for message numbers to offset translations. Permits direct
* accesses inside big folders instead of having to scan up to the right place
*
* Message offsets are saved to files stored under cfg(mboxcachedir), default
* confdir/mboxcache. Mbox files smaller than cfg(mboxcacheminmbs) are not
* cached.
* Cache files are named as the md5 of the file UDI, which is kept in
* the first block for possible collision detection. The 64 bits
* offsets for all message "From_" lines follow. The format is purely
* binary, values are not even byte-swapped to be proc-idependant.
*/
#ifdef _WIN32
// vc++ does not let define an array of size o_b1size because non-const??
#define M_o_b1size 1024
#else
#define M_o_b1size o_b1size
#endif
class MboxCache {
public:
typedef MimeHandlerMbox::mbhoff_type mbhoff_type;
MboxCache()
: m_ok(false), m_minfsize(0)
{
// Can't access rclconfig here, we're a static object, would
// have to make sure it's initialized.
}
~MboxCache() {}
mbhoff_type get_offset(RclConfig *config, const string& udi, int msgnum)
{
LOGDEB0("MboxCache::get_offsets: udi [" << (udi) << "] msgnum " << (msgnum) << "\n");
if (!ok(config)) {
LOGDEB0("MboxCache::get_offsets: init failed\n");
return -1;
}
std::unique_lock<std::mutex> locker(o_mcache_mutex);
string fn = makefilename(udi);
FILE *fp = 0;
if ((fp = fopen(fn.c_str(), "r")) == 0) {
LOGDEB("MboxCache::get_offsets: open failed, errno " << (errno) << "\n");
return -1;
}
FpKeeper keeper(&fp);
char blk1[M_o_b1size];
if (fread(blk1, 1, o_b1size, fp) != o_b1size) {
LOGDEB0("MboxCache::get_offsets: read blk1 errno " << (errno) << "\n");
return -1;
}
ConfSimple cf(string(blk1, o_b1size));
string fudi;
if (!cf.get("udi", fudi) || fudi.compare(udi)) {
LOGINFO("MboxCache::get_offset:badudi fn " << (fn) << " udi [" << (udi) << "], fudi [" << (fudi) << "]\n");
return -1;
}
if (fseeko(fp, cacheoffset(msgnum), SEEK_SET) != 0) {
LOGDEB0("MboxCache::get_offsets: seek " << (lltodecstr(cacheoffset(msgnum))) << " errno " << (errno) << "\n");
return -1;
}
mbhoff_type offset = -1;
size_t ret;
if ((ret = fread(&offset, 1, sizeof(mbhoff_type), fp))
!= sizeof(mbhoff_type)) {
LOGDEB0("MboxCache::get_offsets: read ret " << (ret) << " errno " << (errno) << "\n");
return -1;
}
LOGDEB0("MboxCache::get_offsets: ret " << (lltodecstr(offset)) << "\n");
return offset;
}
// Save array of offsets for a given file, designated by Udi
void put_offsets(RclConfig *config, const string& udi, mbhoff_type fsize,
vector<mbhoff_type>& offs)
{
LOGDEB0("MboxCache::put_offsets: " << (offs.size()) << " offsets\n");
if (!ok(config) || !maybemakedir())
return;
if (fsize < m_minfsize)
return;
std::unique_lock<std::mutex> locker(o_mcache_mutex);
string fn = makefilename(udi);
FILE *fp;
if ((fp = fopen(fn.c_str(), "w")) == 0) {
LOGDEB("MboxCache::put_offsets: fopen errno " << (errno) << "\n");
return;
}
FpKeeper keeper(&fp);
string blk1;
blk1.append("udi=");
blk1.append(udi);
blk1.append(cstr_newline);
blk1.resize(o_b1size, 0);
if (fwrite(blk1.c_str(), 1, o_b1size, fp) != o_b1size) {
LOGDEB("MboxCache::put_offsets: fwrite errno " << (errno) << "\n");
return;
}
for (vector<mbhoff_type>::const_iterator it = offs.begin();
it != offs.end(); it++) {
mbhoff_type off = *it;
if (fwrite((char*)&off, 1, sizeof(mbhoff_type), fp) !=
sizeof(mbhoff_type)) {
return;
}
}
}
// Check state, possibly initialize
bool ok(RclConfig *config) {
std::unique_lock<std::mutex> locker(o_mcache_mutex);
if (m_minfsize == -1)
return false;
if (!m_ok) {
int minmbs = 5;
config->getConfParam("mboxcacheminmbs", &minmbs);
if (minmbs < 0) {
// minmbs set to negative to disable cache
m_minfsize = -1;
return false;
}
m_minfsize = minmbs * 1000 * 1000;
m_dir = config->getMboxcacheDir();
m_ok = true;
}
return m_ok;
}
private:
bool m_ok;
// Place where we store things
string m_dir;
// Don't cache smaller files. If -1, don't do anything.
mbhoff_type m_minfsize;
static const size_t o_b1size;
// Create the cache directory if it does not exist
bool maybemakedir()
{
struct stat st;
if (stat(m_dir.c_str(), &st) != 0 && mkdir(m_dir.c_str(), 0700) != 0) {
return false;
}
return true;
}
// Compute file name from udi
string makefilename(const string& udi)
{
string digest, xdigest;
MD5String(udi, digest);
MD5HexPrint(digest, xdigest);
return path_cat(m_dir, xdigest);
}
// Compute offset in cache file for the mbox offset of msgnum
mbhoff_type cacheoffset(int msgnum)
{// Msgnums are from 1
return o_b1size + (msgnum-1) * sizeof(mbhoff_type);
}
};
const size_t MboxCache::o_b1size = 1024;
static class MboxCache o_mcache;
static const string cstr_keyquirks("mhmboxquirks");
MimeHandlerMbox::~MimeHandlerMbox()
{
clear();
}
void MimeHandlerMbox::clear_impl()
{
m_fn.erase();
if (m_vfp) {
fclose((FILE *)m_vfp);
m_vfp = 0;
}
m_msgnum = m_lineno = 0;
m_ipath.erase();
m_offsets.clear();
}
bool MimeHandlerMbox::set_document_file_impl(const string& mt, const string &fn)
{
LOGDEB("MimeHandlerMbox::set_document_file(" << fn << ")\n");
m_fn = fn;
if (m_vfp) {
fclose((FILE *)m_vfp);
m_vfp = 0;
}
m_vfp = fopen(fn.c_str(), "r");
if (m_vfp == 0) {
LOGERR("MimeHandlerMail::set_document_file: error opening " << fn <<
"\n");
return false;
}
#if defined O_NOATIME && O_NOATIME != 0
if (fcntl(fileno((FILE *)m_vfp), F_SETFL, O_NOATIME) < 0) {
// perror("fcntl");
}
#endif
// Used to use ftell() here: no good beyond 2GB
{struct stat st;
if (fstat(fileno((FILE*)m_vfp), &st) < 0) {
LOGERR("MimeHandlerMbox:setdocfile: fstat(" << fn <<
") failed errno " << errno << "\n");
return false;
}
m_fsize = st.st_size;
}
m_havedoc = true;
m_offsets.clear();
m_quirks = 0;
// Check for location-based quirks:
string quirks;
if (m_config && m_config->getConfParam(cstr_keyquirks, quirks)) {
if (quirks == "tbird") {
LOGDEB("MimeHandlerMbox: setting quirks TBIRD\n");
m_quirks |= MBOXQUIRK_TBIRD;
}
}
// And double check for thunderbird
string tbirdmsf = fn + ".msf";
if ((m_quirks&MBOXQUIRK_TBIRD) == 0 && path_exists(tbirdmsf)) {
LOGDEB("MimeHandlerMbox: detected unconfigured tbird mbox in " << (fn) << "\n");
m_quirks |= MBOXQUIRK_TBIRD;
}
return true;
}
#define LL 1024
typedef char line_type[LL+10];
static inline void stripendnl(line_type& line, int& ll)
{
ll = int(strlen(line));
while (ll > 0) {
if (line[ll-1] == '\n' || line[ll-1] == '\r') {
line[ll-1] = 0;
ll--;
} else
break;
}
}
// The mbox format uses lines beginning with 'From ' as separator. // The mbox format uses lines beginning with 'From ' as separator.
// Mailers are supposed to quote any other lines beginning with // Mailers are supposed to quote any other lines beginning with
// 'From ', turning it into '>From '. This should make it easy to detect // 'From ', turning it into '>From '. This should make it easy to detect
@ -353,16 +85,16 @@ static inline void stripendnl(line_type& line, int& ll)
// emacs-vm, Recoll is not alone // emacs-vm, Recoll is not alone
// Update: 2009-11-27: word after From may be quoted string: From "john bull" // Update: 2009-11-27: word after From may be quoted string: From "john bull"
static const string frompat{ static const string frompat{
"^From[ ]+([^ ]+|\"[^\"]+\")[ ]+" // 'From (toto@tutu|"john bull") ' "^From[ ]+([^ ]+|\"[^\"]+\")[ ]+" // 'From (toto@tutu|"john bull") '
"[[:alpha:]]{3}[ ]+[[:alpha:]]{3}[ ]+[0-3 ][0-9][ ]+" // Fri Oct 26 "[[:alpha:]]{3}[ ]+[[:alpha:]]{3}[ ]+[0-3 ][0-9][ ]+" // Fri Oct 26
"[0-2][0-9]:[0-5][0-9](:[0-5][0-9])?[ ]+" // Time, seconds optional "[0-2][0-9]:[0-5][0-9](:[0-5][0-9])?[ ]+" // Time, seconds optional
"([^ ]+[ ]+)?" // Optional tz "([^ ]+[ ]+)?" // Optional tz
"[12][0-9][0-9][0-9]" // Year, unanchored, more data may follow "[12][0-9][0-9][0-9]" // Year, unanchored, more data may follow
"|" // Or standard mail Date: header format "|" // Or standard mail Date: header format
"^From[ ]+[^ ]+[ ]+" // From toto@tutu "^From[ ]+[^ ]+[ ]+" // From toto@tutu
"[[:alpha:]]{3},[ ]+[0-3]?[0-9][ ]+[[:alpha:]]{3}[ ]+" // Mon, 8 May "[[:alpha:]]{3},[ ]+[0-3]?[0-9][ ]+[[:alpha:]]{3}[ ]+" // Mon, 8 May
"[12][0-9][0-9][0-9][ ]+" // Year "[12][0-9][0-9][0-9][ ]+" // Year
"[0-2][0-9]:[0-5][0-9](:[0-5][0-9])?" // Time, secs optional "[0-2][0-9]:[0-5][0-9](:[0-5][0-9])?" // Time, secs optional
}; };
// Extreme thunderbird brokiness. Will sometimes use From lines // Extreme thunderbird brokiness. Will sometimes use From lines
@ -373,84 +105,377 @@ static const string miniTbirdFrom{"^From $"};
static SimpleRegexp fromregex(frompat, SimpleRegexp::SRE_NOSUB); static SimpleRegexp fromregex(frompat, SimpleRegexp::SRE_NOSUB);
static SimpleRegexp minifromregex(miniTbirdFrom, SimpleRegexp::SRE_NOSUB); static SimpleRegexp minifromregex(miniTbirdFrom, SimpleRegexp::SRE_NOSUB);
static std::mutex o_mcache_mutex;
/**
* Handles a cache for message numbers to offset translations. Permits direct
* accesses inside big folders instead of having to scan up to the right place
*
* Message offsets are saved to files stored under cfg(mboxcachedir), default
* confdir/mboxcache. Mbox files smaller than cfg(mboxcacheminmbs) are not
* cached.
* Cache files are named as the md5 of the file UDI, which is kept in
* the first block for possible collision detection. The 64 bits
* offsets for all message "From_" lines follow. The format is purely
* binary, values are not even byte-swapped to be proc-idependant.
*/
#define M_o_b1size 1024
class MboxCache {
public:
MboxCache() {
// Can't access rclconfig here, we're a static object, would
// have to make sure it's initialized.
}
~MboxCache() {}
int64_t get_offset(RclConfig *config, const string& udi, int msgnum) {
LOGDEB0("MboxCache::get_offsets: udi [" << udi << "] msgnum "
<< msgnum << "\n");
if (!ok(config)) {
LOGDEB("MboxCache::get_offsets: init failed\n");
return -1;
}
std::unique_lock<std::mutex> locker(o_mcache_mutex);
string fn = makefilename(udi);
ifstream instream(fn.c_str(), std::ifstream::binary);
if (!instream.good()) {
LOGSYSERR("MboxCache::get_offsets", "open", fn);
return false;
}
char blk1[M_o_b1size];
instream.read(blk1, M_o_b1size);
if (!instream.good()) {
LOGSYSERR("MboxCache::get_offsets", "read blk1", "");
return -1;
}
ConfSimple cf(string(blk1, M_o_b1size));
string fudi;
if (!cf.get("udi", fudi) || fudi.compare(udi)) {
LOGINFO("MboxCache::get_offset:badudi fn " << fn << " udi ["
<< udi << "], fudi [" << fudi << "]\n");
return -1;
}
LOGDEB1("MboxCache::get_offsets: reading offsets file at offs "
<< cacheoffset(msgnum) << "\n");
instream.seekg(cacheoffset(msgnum));
if (!instream.good()) {
LOGSYSERR("MboxCache::get_offsets", "seek",
lltodecstr(cacheoffset(msgnum)));
return -1;
}
int64_t offset = -1;
instream.read((char*)&offset, sizeof(int64_t));
if (!instream.good()) {
LOGSYSERR("MboxCache::get_offsets", "read", "");
return -1;
}
LOGDEB0("MboxCache::get_offsets: ret " << offset << "\n");
return offset;
}
// Save array of offsets for a given file, designated by Udi
void put_offsets(RclConfig *config, const string& udi, int64_t fsize,
vector<int64_t>& offs) {
LOGDEB0("MboxCache::put_offsets: " << offs.size() << " offsets\n");
if (!ok(config) || !maybemakedir())
return;
if (fsize < m_minfsize) {
LOGDEB0("MboxCache::put_offsets: fsize " << fsize << " < minsize "
<< m_minfsize << endl);
return;
}
std::unique_lock<std::mutex> locker(o_mcache_mutex);
string fn = makefilename(udi);
std::ofstream os(fn.c_str(), std::ios::out|std::ios::binary);
if (!os.good()) {
LOGSYSERR("MboxCache::put_offsets", "open", fn);
return;
}
string blk1("udi=");
blk1.append(udi);
blk1.append(cstr_newline);
blk1.resize(M_o_b1size, 0);
os.write(blk1.c_str(), M_o_b1size);
if (!os.good()) {
LOGSYSERR("MboxCache::put_offsets", "write blk1", "");
return;
}
for (const auto& off : offs) {
LOGDEB1("MboxCache::put_offsets: writing value " << off <<
" at offset " << ftello(fp) << endl);
os.write((char*)&off, sizeof(int64_t));
if (!os.good()) {
LOGSYSERR("MboxCache::put_offsets", "write", "");
return;
}
}
os.flush();
if (!os.good()) {
LOGSYSERR("MboxCache::put_offsets", "flush", "");
return;
}
}
// Check state, possibly initialize
bool ok(RclConfig *config) {
std::unique_lock<std::mutex> locker(o_mcache_mutex);
if (m_minfsize == -1)
return false;
if (!m_ok) {
int minmbs = 5;
config->getConfParam("mboxcacheminmbs", &minmbs);
if (minmbs < 0) {
// minmbs set to negative to disable cache
m_minfsize = -1;
return false;
}
m_minfsize = minmbs * 1000 * 1000;
m_dir = config->getMboxcacheDir();
m_ok = true;
}
return m_ok;
}
private:
bool m_ok{false};
// Place where we store things
string m_dir;
// Don't cache smaller files. If -1, don't do anything.
int64_t m_minfsize{0};
// Create the cache directory if it does not exist
bool maybemakedir() {
if (!path_makepath(m_dir, 0700)) {
LOGSYSERR("MboxCache::maybemakedir", "path_makepath", m_dir);
return false;
}
return true;
}
// Compute file name from udi
string makefilename(const string& udi) {
string digest, xdigest;
MD5String(udi, digest);
MD5HexPrint(digest, xdigest);
return path_cat(m_dir, xdigest);
}
// Compute offset in cache file for the mbox offset of msgnum
// Msgnums are from 1
int64_t cacheoffset(int msgnum) {
return M_o_b1size + (msgnum-1) * sizeof(int64_t);
}
};
static class MboxCache o_mcache;
static const string cstr_keyquirks("mhmboxquirks");
enum Quirks {MBOXQUIRK_TBIRD=1};
class MimeHandlerMbox::Internal {
public:
Internal(MimeHandlerMbox *p) : pthis(p) {}
std::string fn; // File name
std::string ipath;
ifstream instream;
int msgnum{0}; // Current message number in folder. Starts at 1
int64_t lineno{0}; // debug
int64_t fsize{0};
std::vector<int64_t> offsets;
int quirks;
MimeHandlerMbox *pthis;
bool tryUseCache(int mtarg);
};
MimeHandlerMbox::MimeHandlerMbox(RclConfig *cnf, const std::string& id)
: RecollFilter(cnf, id)
{
m = new Internal(this);
}
MimeHandlerMbox::~MimeHandlerMbox()
{
if (m) {
clear();
delete m;
}
}
void MimeHandlerMbox::clear_impl()
{
m->fn.erase();
m->ipath.erase();
m->instream = ifstream();
m->msgnum = m->lineno = m->fsize = 0;
m->offsets.clear();
m->quirks = 0;
}
bool MimeHandlerMbox::skip_to_document(const std::string& ipath) {
m->ipath = ipath;
return true;
}
bool MimeHandlerMbox::set_document_file_impl(const string& mt, const string &fn)
{
LOGDEB("MimeHandlerMbox::set_document_file(" << fn << ")\n");
clear_impl();
m->fn = fn;
m->instream = ifstream(fn.c_str(), std::ifstream::binary);
if (!m->instream.good()) {
LOGSYSERR("MimeHandlerMail::set_document_file", "ifstream", fn);
return false;
}
// TBD
#if 0 && defined O_NOATIME && O_NOATIME != 0
if (fcntl(fileno((FILE *)m->vfp), F_SETFL, O_NOATIME) < 0) {
// perror("fcntl");
}
#endif
m->fsize = path_filesize(fn);
m_havedoc = true;
// Check for location-based quirks:
string quirks;
if (m_config && m_config->getConfParam(cstr_keyquirks, quirks)) {
if (quirks == "tbird") {
LOGDEB("MimeHandlerMbox: setting quirks TBIRD\n");
m->quirks |= MBOXQUIRK_TBIRD;
}
}
// And double check for thunderbird
string tbirdmsf = fn + ".msf";
if (!(m->quirks & MBOXQUIRK_TBIRD) && path_exists(tbirdmsf)) {
LOGDEB("MimeHandlerMbox: detected unconf'd tbird mbox in "<< fn <<"\n");
m->quirks |= MBOXQUIRK_TBIRD;
}
return true;
}
bool MimeHandlerMbox::Internal::tryUseCache(int mtarg)
{
bool cachefound = false;
string line;
int64_t off;
LOGDEB0("MimeHandlerMbox::next_doc: mtarg " << mtarg << " m_udi[" <<
pthis->m_udi << "]\n");
if (pthis->m_udi.empty()) {
goto out;
}
if ((off = o_mcache.get_offset(pthis->m_config, pthis->m_udi, mtarg)) < 0) {
goto out;
}
instream.seekg(off);
if (!instream.good()) {
LOGSYSERR("tryUseCache", "seekg", "");
goto out;
}
getline(instream, line, '\n');
if (!instream.good()) {
LOGSYSERR("tryUseCache", "getline", "");
goto out;
}
LOGDEB1("MimeHandlerMbox::tryUseCache:getl ok. line:[" << line << "]\n");
if ((fromregex(line) ||
((quirks & MBOXQUIRK_TBIRD) && minifromregex(line))) ) {
LOGDEB0("MimeHandlerMbox: Cache: From_ Ok\n");
instream.seekg(off);
msgnum = mtarg -1;
cachefound = true;
} else {
LOGDEB0("MimeHandlerMbox: cache: regex failed for [" << line << "]\n");
}
out:
if (!cachefound) {
// No cached result: scan.
instream.seekg(0);
msgnum = 0;
}
return cachefound;
}
bool MimeHandlerMbox::next_document() bool MimeHandlerMbox::next_document()
{ {
if (m_vfp == 0) { if (!m->instream.good()) {
LOGERR("MimeHandlerMbox::next_document: not open\n"); LOGERR("MimeHandlerMbox::next_document: not open\n");
return false; return false;
} }
if (!m_havedoc) { if (!m_havedoc) {
return false; return false;
} }
FILE *fp = (FILE *)m_vfp;
int mtarg = 0; int mtarg = 0;
if (!m_ipath.empty()) { if (!m->ipath.empty()) {
sscanf(m_ipath.c_str(), "%d", &mtarg); sscanf(m->ipath.c_str(), "%d", &mtarg);
} else if (m_forPreview) { } else if (m_forPreview) {
// Can't preview an mbox. // Can't preview an mbox.
LOGDEB("MimeHandlerMbox::next_document: can't preview folders!\n"); LOGDEB("MimeHandlerMbox::next_document: can't preview folders!\n");
return false; return false;
} }
LOGDEB0("MimeHandlerMbox::next_document: fn " << m_fn << ", msgnum " << LOGDEB0("MimeHandlerMbox::next_document: fn " << m->fn << ", msgnum " <<
m_msgnum << " mtarg " << mtarg << " \n"); m->msgnum << " mtarg " << mtarg << " \n");
if (mtarg == 0) if (mtarg == 0)
mtarg = -1; mtarg = -1;
// If we are called to retrieve a specific message, try to use the
// If we are called to retrieve a specific message, seek to bof // offsets cache to try and position to the right header.
// (then scan up to the message). This is for the case where the
// same object is reused to fetch several messages (else the fp is
// just opened no need for a seek). We could also check if the
// current message number is lower than the requested one and
// avoid rereading the whole thing in this case. But I'm not sure
// we're ever used in this way (multiple retrieves on same
// object). So:
bool storeoffsets = true; bool storeoffsets = true;
if (mtarg > 0) { if (mtarg > 0) {
mbhoff_type off; storeoffsets = !m->tryUseCache(mtarg);
line_type line;
LOGDEB0("MimeHandlerMbox::next_doc: mtarg " << mtarg << " m_udi[" <<
m_udi << "]\n");
if (!m_udi.empty() &&
(off = o_mcache.get_offset(m_config, m_udi, mtarg)) >= 0 &&
fseeko(fp, (off_t)off, SEEK_SET) >= 0 &&
fgets(line, LL, fp) &&
(fromregex(line) || ((m_quirks & MBOXQUIRK_TBIRD) &&
minifromregex(line))) ) {
LOGDEB0("MimeHandlerMbox: Cache: From_ Ok\n");
fseeko(fp, (off_t)off, SEEK_SET);
m_msgnum = mtarg -1;
storeoffsets = false;
} else {
fseek(fp, 0, SEEK_SET);
m_msgnum = 0;
}
} }
off_t message_end = 0; int64_t message_end = 0;
bool iseof = false; bool iseof = false;
bool hademptyline = true; bool hademptyline = true;
string& msgtxt = m_metaData[cstr_dj_keycontent]; string& msgtxt = m_metaData[cstr_dj_keycontent];
msgtxt.erase(); msgtxt.erase();
line_type line; string line;
for (;;) { for (;;) {
message_end = ftello(fp); message_end = m->instream.tellg();
if (!fgets(line, LL, fp)) { getline(m->instream, line, '\n');
LOGDEB2("MimeHandlerMbox:next: eof\n"); if (!m->instream.good()) {
ifstream::iostate st = m->instream.rdstate();
if (st & std::ifstream::eofbit) {
LOGDEB0("MimeHandlerMbox:next: eof\n");
}
if (st & std::ifstream::failbit) {
LOGDEB0("MimeHandlerMbox:next: fail\n");
LOGSYSERR("MimeHandlerMbox:next:", "", "");
}
if (st & std::ifstream::badbit) {
LOGDEB0("MimeHandlerMbox:next: bad\n");
LOGSYSERR("MimeHandlerMbox:next:", "", "");
}
if (st & std::ifstream::goodbit) {
LOGDEB0("MimeHandlerMbox:next: good\n");
}
LOGDEB0("MimeHandlerMbox:next: eof at " << message_end << endl);
iseof = true; iseof = true;
m_msgnum++; m->msgnum++;
break; break;
} }
m_lineno++; m->lineno++;
int ll; rtrimstring(line, "\r\n");
stripendnl(line, ll); int ll = line.size();
LOGDEB2("mhmbox:next: hadempty " << hademptyline << " lineno " << LOGDEB2("mhmbox:next: hadempty " << hademptyline << " lineno " <<
m_lineno << " ll " << ll << " Line: [" << line << "]\n"); m->lineno << " ll " << ll << " Line: [" << line << "]\n");
if (hademptyline) { if (hademptyline) {
if (ll > 0) { if (ll > 0) {
// Non-empty line with empty line flag set, reset flag // Non-empty line with empty line flag set, reset flag
// and check regex. // and check regex.
if (!(m_quirks & MBOXQUIRK_TBIRD)) { if (!(m->quirks & MBOXQUIRK_TBIRD)) {
// Tbird sometimes ommits the empty line, so avoid // Tbird sometimes ommits the empty line, so avoid
// resetting state (initially true) and hope for // resetting state (initially true) and hope for
// the best // the best
@ -460,16 +485,18 @@ bool MimeHandlerMbox::next_document()
A LOT */ A LOT */
if (line[0] == 'F' && ( if (line[0] == 'F' && (
fromregex(line) || fromregex(line) ||
((m_quirks & MBOXQUIRK_TBIRD) && minifromregex(line))) ((m->quirks & MBOXQUIRK_TBIRD) && minifromregex(line)))
) { ) {
LOGDEB0("MimeHandlerMbox: msgnum " << m_msgnum << LOGDEB1("MimeHandlerMbox: msgnum " << m->msgnum <<
", From_ at line " << m_lineno << ": [" << line ", From_ at line " << m->lineno << " foffset " <<
<< "]\n"); message_end << " line: [" << line << "]\n");
if (storeoffsets)
m_offsets.push_back(message_end); if (storeoffsets) {
m_msgnum++; m->offsets.push_back(message_end);
if ((mtarg <= 0 && m_msgnum > 1) || }
(mtarg > 0 && m_msgnum > mtarg)) { m->msgnum++;
if ((mtarg <= 0 && m->msgnum > 1) ||
(mtarg > 0 && m->msgnum > mtarg)) {
// Got message, go do something with it // Got message, go do something with it
break; break;
} }
@ -481,15 +508,14 @@ bool MimeHandlerMbox::next_document()
hademptyline = true; hademptyline = true;
} }
if (mtarg <= 0 || m_msgnum == mtarg) { if (mtarg <= 0 || m->msgnum == mtarg) {
// Accumulate message lines // Accumulate message lines
line[ll] = '\n'; line += '\n';
line[ll+1] = 0;
msgtxt += line; msgtxt += line;
if (msgtxt.size() > max_mbox_member_size) { if (msgtxt.size() > max_mbox_member_size) {
LOGERR("mh_mbox: huge message (more than " << LOGERR("mh_mbox: huge message (more than " <<
max_mbox_member_size/(1024*1024) << " MB) inside " << max_mbox_member_size/(1024*1024) << " MB) inside " <<
m_fn << ", giving up\n"); m->fn << ", giving up\n");
return false; return false;
} }
} }
@ -497,135 +523,17 @@ bool MimeHandlerMbox::next_document()
LOGDEB2("Message text length " << msgtxt.size() << "\n"); LOGDEB2("Message text length " << msgtxt.size() << "\n");
LOGDEB2("Message text: [" << msgtxt << "]\n"); LOGDEB2("Message text: [" << msgtxt << "]\n");
char buf[20]; char buf[20];
// m_msgnum was incremented when hitting the next From_ or eof, so the data // m->msgnum was incremented when hitting the next From_ or eof, so the data
// is for m_msgnum - 1 // is for m->msgnum - 1
sprintf(buf, "%d", m_msgnum - 1); sprintf(buf, "%d", m->msgnum - 1);
m_metaData[cstr_dj_keyipath] = buf; m_metaData[cstr_dj_keyipath] = buf;
m_metaData[cstr_dj_keymt] = "message/rfc822"; m_metaData[cstr_dj_keymt] = "message/rfc822";
if (iseof) { if (iseof) {
LOGDEB2("MimeHandlerMbox::next: eof hit\n"); LOGDEB2("MimeHandlerMbox::next: eof hit\n");
m_havedoc = false; m_havedoc = false;
if (!m_udi.empty() && storeoffsets) { if (!m_udi.empty() && storeoffsets) {
o_mcache.put_offsets(m_config, m_udi, m_fsize, m_offsets); o_mcache.put_offsets(m_config, m_udi, m->fsize, m->offsets);
} }
} }
return msgtxt.empty() ? false : true; return msgtxt.empty() ? false : true;
} }
#else // Test driver ->
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <iostream>
#include <string>
using namespace std;
#include "rclconfig.h"
#include "rclinit.h"
#include "cstr.h"
#include "mh_mbox.h"
static char *thisprog;
static char usage [] =
"Test driver for mbox walking function\n"
"mh_mbox [-m num] mboxfile\n"
" \n\n"
;
static void
Usage(void)
{
fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
exit(1);
}
static RclConfig *config;
static int op_flags;
#define OPT_MOINS 0x1
#define OPT_m 0x2
//#define OPT_t 0x4
int main(int argc, char **argv)
{
string msgnum;
thisprog = argv[0];
argc--; argv++;
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
Usage();
while (**argv)
switch (*(*argv)++) {
case 'm': op_flags |= OPT_m; if (argc < 2) Usage();
msgnum = *(++argv);
argc--;
goto b1;
// case 't': op_flags |= OPT_t;break;
default: Usage(); break;
}
b1: argc--; argv++;
}
if (argc != 1)
Usage();
string filename = *argv++;argc--;
string reason;
config = recollinit(RclInitFlags(0), 0, 0, reason, 0);
if (config == 0) {
cerr << "init failed " << reason << endl;
exit(1);
}
config->setKeyDir(path_getfather(filename));
MimeHandlerMbox mh(config, "some_id");
if (!mh.set_document_file("text/x-mail", filename)) {
cerr << "set_document_file failed" << endl;
exit(1);
}
if (!msgnum.empty()) {
mh.skip_to_document(msgnum);
if (!mh.next_document()) {
cerr << "next_document failed after skipping to " << msgnum << endl;
exit(1);
}
map<string, string>::const_iterator it =
mh.get_meta_data().find(cstr_dj_keycontent);
int size;
if (it == mh.get_meta_data().end()) {
size = -1;
cerr << "No content!!" << endl;
exit(1);
}
cout << "Doc " << msgnum << ":" << endl;
cout << it->second << endl;
exit(0);
}
int docnt = 0;
while (mh.has_documents()) {
if (!mh.next_document()) {
cerr << "next_document failed" << endl;
exit(1);
}
docnt++;
map<string, string>::const_iterator it =
mh.get_meta_data().find(cstr_dj_keycontent);
int size;
if (it == mh.get_meta_data().end()) {
size = -1;
} else {
size = it->second.length();
}
cout << "Doc " << docnt << " size " << size << endl;
}
cout << docnt << " documents found in " << filename << endl;
exit(0);
}
#endif // TEST_MH_MBOX

View File

@ -19,6 +19,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <inttypes.h>
#include "mimehandler.h" #include "mimehandler.h"
@ -29,33 +30,19 @@
*/ */
class MimeHandlerMbox : public RecollFilter { class MimeHandlerMbox : public RecollFilter {
public: public:
MimeHandlerMbox(RclConfig *cnf, const std::string& id) MimeHandlerMbox(RclConfig *cnf, const std::string& id);
: RecollFilter(cnf, id), m_vfp(0), m_msgnum(0),
m_lineno(0), m_fsize(0) {
}
virtual ~MimeHandlerMbox(); virtual ~MimeHandlerMbox();
virtual bool next_document() override; virtual bool next_document() override;
virtual bool skip_to_document(const std::string& ipath) override{ virtual bool skip_to_document(const std::string& ipath) override;
m_ipath = ipath;
return true;
}
virtual void clear_impl() override; virtual void clear_impl() override;
typedef long long mbhoff_type;
protected: protected:
virtual bool set_document_file_impl(const std::string&, virtual bool set_document_file_impl(const std::string&,
const std::string&) override; const std::string&) override;
class Internal;
private: private:
std::string m_fn; // File name Internal *m{nullptr};
void *m_vfp; // File pointer for folder
int m_msgnum; // Current message number in folder. Starts at 1
std::string m_ipath;
int m_lineno; // debug
mbhoff_type m_fsize;
std::vector<mbhoff_type> m_offsets;
enum Quirks {MBOXQUIRK_TBIRD=1};
int m_quirks;
}; };
#endif /* _MBOX_H_INCLUDED_ */ #endif /* _MBOX_H_INCLUDED_ */

View File

@ -56,9 +56,12 @@ static const int margin = 2;
void ConfParamW::setValue(const QString& value) void ConfParamW::setValue(const QString& value)
{ {
#ifndef _WIN32
// On Windows all paths are unicode.
if (m_fsencoding) if (m_fsencoding)
m_cflink->set(string((const char *)value.toLocal8Bit())); m_cflink->set(string((const char *)value.toLocal8Bit()));
else else
#endif
m_cflink->set(string((const char *)value.toUtf8())); m_cflink->set(string((const char *)value.toUtf8()));
} }
@ -158,9 +161,12 @@ void ConfParamStrW::loadValue()
{ {
string s; string s;
m_cflink->get(s); m_cflink->get(s);
#ifndef _WIN32
// On Windows all paths are unicode.
if (m_fsencoding) if (m_fsencoding)
m_le->setText(QString::fromLocal8Bit(s.c_str())); m_le->setText(QString::fromLocal8Bit(s.c_str()));
else else
#endif
m_le->setText(QString::fromUtf8(s.c_str())); m_le->setText(QString::fromUtf8(s.c_str()));
} }
@ -191,9 +197,12 @@ void ConfParamCStrW::loadValue()
string s; string s;
m_cflink->get(s); m_cflink->get(s);
QString cs; QString cs;
#ifndef _WIN32
// On Windows all paths are unicode.
if (m_fsencoding) if (m_fsencoding)
cs = QString::fromLocal8Bit(s.c_str()); cs = QString::fromLocal8Bit(s.c_str());
else else
#endif
cs = QString::fromUtf8(s.c_str()); cs = QString::fromUtf8(s.c_str());
for (int i = 0; i < m_cmb->count(); i++) { for (int i = 0; i < m_cmb->count(); i++) {
@ -272,7 +281,12 @@ void ConfParamFNW::loadValue()
{ {
string s; string s;
m_cflink->get(s); m_cflink->get(s);
#ifndef _WIN32
// On Windows all paths are unicode.
m_le->setText(QString::fromLocal8Bit(s.c_str())); m_le->setText(QString::fromLocal8Bit(s.c_str()));
#else
m_le->setText(QString::fromUtf8(s.c_str()));
#endif
} }
void ConfParamFNW::showBrowserDialog() void ConfParamFNW::showBrowserDialog()
@ -346,9 +360,12 @@ void ConfParamSLW::loadValue()
stringToStrings(s, ls); stringToStrings(s, ls);
QStringList qls; QStringList qls;
for (list<string>::const_iterator it = ls.begin(); it != ls.end(); it++) { for (list<string>::const_iterator it = ls.begin(); it != ls.end(); it++) {
// On Windows all paths are unicode.
#ifndef _WIN32
if (m_fsencoding) if (m_fsencoding)
qls.push_back(QString::fromLocal8Bit(it->c_str())); qls.push_back(QString::fromLocal8Bit(it->c_str()));
else else
#endif
qls.push_back(QString::fromUtf8(it->c_str())); qls.push_back(QString::fromUtf8(it->c_str()));
} }
m_lb->clear(); m_lb->clear();
@ -379,7 +396,7 @@ void ConfParamSLW::showInputDialog()
void ConfParamSLW::listToConf() void ConfParamSLW::listToConf()
{ {
list<string> ls; list<string> ls;
LOGDEB2("ConfParamSLW::listToConf. m_fsencoding " << (int(m_fsencoding)) << "\n" ); LOGDEB2("ConfParamSLW::listToConf. m_fsencoding " << m_fsencoding << "\n");
for (int i = 0; i < m_lb->count(); i++) { for (int i = 0; i < m_lb->count(); i++) {
// General parameters are encoded as utf-8. File names as // General parameters are encoded as utf-8. File names as
// local8bit There is no hope for 8bit file names anyway // local8bit There is no hope for 8bit file names anyway
@ -390,8 +407,9 @@ void ConfParamSLW::listToConf()
// paths, and it will come back to haunt us one day. // paths, and it will come back to haunt us one day.
QString text = m_lb->item(i)->text(); QString text = m_lb->item(i)->text();
if (m_fsencoding) { if (m_fsencoding) {
// On Windows all paths are unicode.
#ifdef _WIN32 #ifdef _WIN32
string pth((const char *)(text.toLocal8Bit())); string pth((const char *)(text.toUtf8()));
path_slashize(pth); path_slashize(pth);
ls.push_back(pth); ls.push_back(pth);
#else #else
@ -426,7 +444,7 @@ void ConfParamSLW::deleteSelected()
} }
for (vector<int>::reverse_iterator it = idxes.rbegin(); for (vector<int>::reverse_iterator it = idxes.rbegin();
it != idxes.rend(); it++) { it != idxes.rend(); it++) {
LOGDEB0("deleteSelected: " << (*it) << " was selected\n" ); LOGDEB0("deleteSelected: " << *it << " was selected\n");
QListWidgetItem *item = m_lb->takeItem(*it); QListWidgetItem *item = m_lb->takeItem(*it);
emit entryDeleted(item->text()); emit entryDeleted(item->text());
delete item; delete item;
@ -479,4 +497,3 @@ void ConfParamCSLW::showInputDialog()
} }
} // Namespace confgui } // Namespace confgui

View File

@ -59,12 +59,10 @@ public:
ConfLinkRclRep(ConfNull *conf, const string& nm, ConfLinkRclRep(ConfNull *conf, const string& nm,
string *sk = 0) string *sk = 0)
: m_conf(conf), m_nm(nm), m_sk(sk) /* KEEP THE POINTER, shared data */ : m_conf(conf), m_nm(nm), m_sk(sk) /* KEEP THE POINTER, shared data */
{ { }
}
virtual ~ConfLinkRclRep() {} virtual ~ConfLinkRclRep() {}
virtual bool set(const string& val) virtual bool set(const string& val) {
{
if (!m_conf) if (!m_conf)
return false; return false;
LOGDEB1("Setting [" << m_nm << "] value to [" << val << "]\n"); LOGDEB1("Setting [" << m_nm << "] value to [" << val << "]\n");
@ -73,8 +71,7 @@ public:
LOGERR("Value set failed\n" ); LOGERR("Value set failed\n" );
return ret; return ret;
} }
virtual bool get(string& val) virtual bool get(string& val) {
{
if (!m_conf) if (!m_conf)
return false; return false;
bool ret = m_conf->get(m_nm, val, getSk()); bool ret = m_conf->get(m_nm, val, getSk());
@ -731,4 +728,3 @@ void ConfSubPanelW::restoreEmpty()
} }
} // Namespace confgui } // Namespace confgui

View File

@ -1331,14 +1331,6 @@ Prověřte soubor pracovní plochy</translation>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1368,6 +1360,34 @@ Prověřte soubor pracovní plochy</translation>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2391,7 +2411,7 @@ Použijte odkaz &lt;b&gt;Ukázat hledání&lt;/b&gt;, když máte o výsledku po
</message> </message>
<message> <message>
<source>Start directory (else use regular topdirs):</source> <source>Start directory (else use regular topdirs):</source>
<translation>Začáteční adresář (jinak použít počáteční adresáře):</translation> <translation type="vanished">Začáteční adresář (jinak použít počáteční adresáře):</translation>
</message> </message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
@ -2409,6 +2429,10 @@ Použijte odkaz &lt;b&gt;Ukázat hledání&lt;/b&gt;, když máte o výsledku po
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1239,14 +1239,6 @@ Tjek venligst desktopfilen</translation>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1276,6 +1268,34 @@ Tjek venligst desktopfilen</translation>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2056,7 +2076,7 @@ Brug &lt;b&gt;Vis Forespørgsel&lt;/b&gt; link når i tvivl om resultatet og se
</message> </message>
<message> <message>
<source>Start directory (else use regular topdirs):</source> <source>Start directory (else use regular topdirs):</source>
<translation>Startmappe (ellers brug de regulære øverste mapper):</translation> <translation type="vanished">Startmappe (ellers brug de regulære øverste mapper):</translation>
</message> </message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
@ -2074,6 +2094,10 @@ Brug &lt;b&gt;Vis Forespørgsel&lt;/b&gt; link når i tvivl om resultatet og se
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1299,14 +1299,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1336,6 +1328,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2328,10 +2348,6 @@ Drücken Sie ESC+Leerzeichen für Vervollständigungen des aktuellen Begriffs.</
<source>Browse</source> <source>Browse</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2348,6 +2364,10 @@ Drücken Sie ESC+Leerzeichen für Vervollständigungen des aktuellen Begriffs.</
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1283,14 +1283,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1320,6 +1312,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2239,10 +2259,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished">Περιήγηση</translation> <translation type="unfinished">Περιήγηση</translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2259,6 +2275,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1289,14 +1289,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1326,6 +1318,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2282,10 +2302,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished">Buscar</translation> <translation type="unfinished">Buscar</translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2302,6 +2318,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

Binary file not shown.

View File

@ -1347,11 +1347,11 @@ Merci de vérifier le fichier desktop </translation>
</message> </message>
<message> <message>
<source>(%d documents/%d files/%d errors/%d total files) </source> <source>(%d documents/%d files/%d errors/%d total files) </source>
<translation>(%d documents/%d fichiers/%d erreurs/%d fichiers en tout) </translation> <translation type="vanished">(%d documents/%d fichiers/%d erreurs/%d fichiers en tout) </translation>
</message> </message>
<message> <message>
<source>(%d documents/%d files/%d errors) </source> <source>(%d documents/%d files/%d errors) </source>
<translation>(%d documents/%d fichiers/%d erreurs) </translation> <translation type="vanished">(%d documents/%d fichiers/%d erreurs) </translation>
</message> </message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
@ -1382,6 +1382,34 @@ Merci de vérifier le fichier desktop </translation>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation>Cliquer Annuler pour retourner à la liste.&lt;br&gt;Cliquer Ignorer pour afficher la prévisualisation (et enregister l&apos;option pour cette session). Il y a un risque d&apos;afficher le mauvais document.&lt;br/&gt;</translation> <translation>Cliquer Annuler pour retourner à la liste.&lt;br&gt;Cliquer Ignorer pour afficher la prévisualisation (et enregister l&apos;option pour cette session). Il y a un risque d&apos;afficher le mauvais document.&lt;br/&gt;</translation>
</message> </message>
<message>
<source>documents</source>
<translation>documents</translation>
</message>
<message>
<source>document</source>
<translation>document</translation>
</message>
<message>
<source>files</source>
<translation>fichiers</translation>
</message>
<message>
<source>file</source>
<translation>fichier</translation>
</message>
<message>
<source>errors</source>
<translation>erreurs</translation>
</message>
<message>
<source>error</source>
<translation>erreur</translation>
</message>
<message>
<source>total files)</source>
<translation>fichiers totaux)</translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2421,7 +2449,7 @@ Utiliser le lien &lt;b&gt;Afficher la requête en détail&lt;/b&gt; en cas de do
</message> </message>
<message> <message>
<source>Start directory (else use regular topdirs):</source> <source>Start directory (else use regular topdirs):</source>
<translation>Répertoire de départ (sinon utiliser la variable normale topdirs) :</translation> <translation type="vanished">Répertoire de départ (sinon utiliser la variable normale topdirs) :</translation>
</message> </message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
@ -2443,6 +2471,14 @@ Utiliser le lien &lt;b&gt;Afficher la requête en détail&lt;/b&gt; en cas de do
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation>Ne pas réessayer les fichiers en erreur.</translation> <translation>Ne pas réessayer les fichiers en erreur.</translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. We use topdirs if empty.</source>
<translation type="vanished">Répertoire de départ. Doit faire partie de la zone indexée. topdirs est utilisé si non renseigné.</translation>
</message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation>Répertoire de départ. Doit faire partie de la zone indexée. Traite toute la zone si non renseigné.</translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1203,14 +1203,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1240,6 +1232,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2077,10 +2097,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished">Esplora</translation> <translation type="unfinished">Esplora</translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2097,6 +2113,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1223,14 +1223,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1260,6 +1252,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2161,10 +2181,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished">Naršyti</translation> <translation type="unfinished">Naršyti</translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2181,6 +2197,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -748,7 +748,7 @@ Click Cancel if you want to edit the configuration file before indexing starts,
<context> <context>
<name>QObject</name> <name>QObject</name>
<message> <message>
<location filename="../confgui/confguiindex.cpp" line="+218"/> <location filename="../confgui/confguiindex.cpp" line="+215"/>
<source>Global parameters</source> <source>Global parameters</source>
<translation>Общие параметры</translation> <translation>Общие параметры</translation>
</message> </message>
@ -1064,8 +1064,8 @@ p, li { white-space: pre-wrap; }
<translation>Невозможно извлечь сведения о документе из БД</translation> <translation>Невозможно извлечь сведения о документе из БД</translation>
</message> </message>
<message> <message>
<location filename="../rclm_idx.cpp" line="+261"/> <location filename="../rclm_idx.cpp" line="+263"/>
<location line="+271"/> <location line="+273"/>
<location line="+19"/> <location line="+19"/>
<location filename="../rclm_preview.cpp" line="-138"/> <location filename="../rclm_preview.cpp" line="-138"/>
<location line="+44"/> <location line="+44"/>
@ -1101,7 +1101,7 @@ p, li { white-space: pre-wrap; }
<translation>История</translation> <translation>История</translation>
</message> </message>
<message> <message>
<location filename="../rclm_idx.cpp" line="-507"/> <location filename="../rclm_idx.cpp" line="-511"/>
<source>Indexing in progress: </source> <source>Indexing in progress: </source>
<translation>Идёт индексирование: </translation> <translation>Идёт индексирование: </translation>
</message> </message>
@ -1162,7 +1162,7 @@ Please check the mimeconf file</source>
<translation>ошибка получения списка языков</translation> <translation>ошибка получения списка языков</translation>
</message> </message>
<message> <message>
<location filename="../rclm_idx.cpp" line="+121"/> <location filename="../rclm_idx.cpp" line="+123"/>
<source>Update &amp;Index</source> <source>Update &amp;Index</source>
<translation>Обновить &amp;индекс</translation> <translation>Обновить &amp;индекс</translation>
</message> </message>
@ -1172,7 +1172,42 @@ Please check the mimeconf file</source>
<translation>Индексирование прервано</translation> <translation>Индексирование прервано</translation>
</message> </message>
<message> <message>
<location line="+34"/> <location line="-66"/>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+0"/>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+0"/>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+1"/>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+0"/>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+4"/>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+94"/>
<location line="+27"/> <location line="+27"/>
<source>Stop &amp;Indexing</source> <source>Stop &amp;Indexing</source>
<translation>О&amp;становить индексирование</translation> <translation>О&amp;становить индексирование</translation>
@ -1309,7 +1344,7 @@ Do you want to start the preferences dialog ?</source>
<translation>Поиск не дал результатов</translation> <translation>Поиск не дал результатов</translation>
</message> </message>
<message> <message>
<location filename="../rclm_idx.cpp" line="-136"/> <location filename="../rclm_idx.cpp" line="-138"/>
<source>None</source> <source>None</source>
<translation>Отсутствует</translation> <translation>Отсутствует</translation>
</message> </message>
@ -1329,17 +1364,7 @@ Do you want to start the preferences dialog ?</source>
<translation>Монитор</translation> <translation>Монитор</translation>
</message> </message>
<message> <message>
<location line="+8"/> <location line="+74"/>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+6"/>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+58"/>
<source>Indexing failed</source> <source>Indexing failed</source>
<translation>Не удалось выполнить индексирование</translation> <translation>Не удалось выполнить индексирование</translation>
</message> </message>
@ -1370,7 +1395,7 @@ Do you want to start the preferences dialog ?</source>
<translation>Сбросить индекс и начать заново?</translation> <translation>Сбросить индекс и начать заново?</translation>
</message> </message>
<message> <message>
<location line="+193"/> <location line="+195"/>
<source>Can&apos;t update index: internal error</source> <source>Can&apos;t update index: internal error</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
@ -1501,7 +1526,7 @@ Please check the desktop file</source>
<translation type="vanished">Для запуска текущего процесса индексирования был использован другой интерфейс. Прекратить выполнение процесса невозможно</translation> <translation type="vanished">Для запуска текущего процесса индексирования был использован другой интерфейс. Прекратить выполнение процесса невозможно</translation>
</message> </message>
<message> <message>
<location filename="../rclm_idx.cpp" line="-303"/> <location filename="../rclm_idx.cpp" line="-305"/>
<source>Bad paths</source> <source>Bad paths</source>
<translation>Неверные пути</translation> <translation>Неверные пути</translation>
</message> </message>
@ -1512,7 +1537,7 @@ Please check the desktop file</source>
</translation> </translation>
</message> </message>
<message> <message>
<location line="+279"/> <location line="+281"/>
<source>Selection patterns need topdir</source> <source>Selection patterns need topdir</source>
<translation>Для шаблонов отбора требуется topdir</translation> <translation>Для шаблонов отбора требуется topdir</translation>
</message> </message>
@ -1622,7 +1647,7 @@ Please check the desktop file</source>
<translation>Больше не показывать (для восстановления значений используйте окно настройки интерфейса).</translation> <translation>Больше не показывать (для восстановления значений используйте окно настройки интерфейса).</translation>
</message> </message>
<message> <message>
<location filename="../rclm_idx.cpp" line="-342"/> <location filename="../rclm_idx.cpp" line="-344"/>
<source>Index locked</source> <source>Index locked</source>
<translation>Индекс заблокирован</translation> <translation>Индекс заблокирован</translation>
</message> </message>
@ -2138,12 +2163,12 @@ Please check the desktop file</source>
<translation>Дата и время</translation> <translation>Дата и время</translation>
</message> </message>
<message> <message>
<location line="+193"/> <location line="+189"/>
<source>Can&apos;t sort by inverse relevance</source> <source>Can&apos;t sort by inverse relevance</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location line="-202"/> <location line="-198"/>
<source>Ipath</source> <source>Ipath</source>
<translation>Ipath</translation> <translation>Ipath</translation>
</message> </message>
@ -2293,7 +2318,7 @@ Please check the desktop file</source>
<context> <context>
<name>ResTable</name> <name>ResTable</name>
<message> <message>
<location filename="../restable.cpp" line="+787"/> <location filename="../restable.cpp" line="+783"/>
<source>&amp;Reset sort</source> <source>&amp;Reset sort</source>
<translation>&amp;Сбросить сортировку</translation> <translation>&amp;Сбросить сортировку</translation>
</message> </message>
@ -2311,7 +2336,7 @@ Please check the desktop file</source>
<translation type="obsolete">&quot;</translation> <translation type="obsolete">&quot;</translation>
</message> </message>
<message> <message>
<location line="-313"/> <location line="-312"/>
<source>Save table to CSV file</source> <source>Save table to CSV file</source>
<translation>Сохранить таблицу в CSV-файл</translation> <translation>Сохранить таблицу в CSV-файл</translation>
</message> </message>
@ -2353,7 +2378,7 @@ Please check the desktop file</source>
<translation type="obsolete">&amp;Открыть родительский документ/каталог</translation> <translation type="obsolete">&amp;Открыть родительский документ/каталог</translation>
</message> </message>
<message> <message>
<location line="+301"/> <location line="+300"/>
<source>&amp;Save as CSV</source> <source>&amp;Save as CSV</source>
<translation>&amp;Сохранить как CSV</translation> <translation>&amp;Сохранить как CSV</translation>
</message> </message>
@ -2843,8 +2868,12 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
</message> </message>
<message> <message>
<location line="+10"/> <location line="+10"/>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Start directory (else use regular topdirs):</source> <source>Start directory (else use regular topdirs):</source>
<translation>Корневой каталог (или использовать стандартный topdirs):</translation> <translation type="vanished">Корневой каталог (или использовать стандартный topdirs):</translation>
</message> </message>
<message> <message>
<location line="+14"/> <location line="+14"/>
@ -3609,7 +3638,7 @@ This should give higher precedence to the results where the search terms appear
<translation type="obsolete">Просмотр</translation> <translation type="obsolete">Просмотр</translation>
</message> </message>
<message> <message>
<location filename="../confgui/confgui.cpp" line="+258"/> <location filename="../confgui/confgui.cpp" line="+267"/>
<source>Choose</source> <source>Choose</source>
<translation>Выбрать</translation> <translation>Выбрать</translation>
</message> </message>
@ -3617,7 +3646,7 @@ This should give higher precedence to the results where the search terms appear
<context> <context>
<name>confgui::ConfParamSLW</name> <name>confgui::ConfParamSLW</name>
<message> <message>
<location line="+54"/> <location line="+59"/>
<source>+</source> <source>+</source>
<translation>+</translation> <translation>+</translation>
</message> </message>

View File

@ -1204,14 +1204,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1241,6 +1233,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2078,10 +2098,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished">Gözat</translation> <translation type="unfinished">Gözat</translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2098,6 +2114,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1221,14 +1221,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1258,6 +1250,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2107,10 +2127,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished">Перегляд</translation> <translation type="unfinished">Перегляд</translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2127,6 +2143,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1144,14 +1144,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1181,6 +1173,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -1842,10 +1862,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -1862,6 +1878,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1317,14 +1317,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1354,6 +1346,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2250,10 +2270,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2270,6 +2286,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -1330,14 +1330,6 @@ Please check the desktop file</source>
<source>Content has been indexed for these MIME types:</source> <source>Content has been indexed for these MIME types:</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>(%d documents/%d files/%d errors/%d total files) </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>(%d documents/%d files/%d errors) </source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index): <source>Empty or non-existant paths in configuration file. Click Ok to start indexing anyway (absent data will not be purged from the index):
</source> </source>
@ -1367,6 +1359,34 @@ Please check the desktop file</source>
<source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source> <source>Click Cancel to return to the list.&lt;br&gt;Click Ignore to show the preview anyway (and remember for this session). There is a risk of showing the wrong entry.&lt;br/&gt;</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>documents</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>document</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>errors</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>total files)</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>RclMainBase</name> <name>RclMainBase</name>
@ -2283,10 +2303,6 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Browse</source> <source>Browse</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory (else use regular topdirs):</source>
<translation type="unfinished"></translation>
</message>
<message> <message>
<source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source> <source>Leave empty to select all files. You can use multiple space-separated shell-type patterns.&lt;br&gt;Patterns with embedded spaces should be quoted with double quotes.&lt;br&gt;Can only be used if the start target is set.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
@ -2303,6 +2319,10 @@ Use &lt;b&gt;Show Query&lt;/b&gt; link when in doubt about result and see manual
<source>Retry previously failed files.</source> <source>Retry previously failed files.</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SpellBase</name> <name>SpellBase</name>

View File

@ -55,20 +55,22 @@ void RclMain::updateIdxStatus()
} }
msg += phs + " "; msg += phs + " ";
if (status.phase == DbIxStatus::DBIXS_FILES) { if (status.phase == DbIxStatus::DBIXS_FILES) {
char cnts[100]; QString sdocs = status.docsdone > 1 ?tr("documents") : tr("document");
QString sfiles = status.filesdone > 1 ? tr("files") : tr("file");
QString serrors = status.fileerrors > 1 ? tr("errors") : tr("error");
QString stats;
if (status.dbtotdocs > 0) { if (status.dbtotdocs > 0) {
string format = stats = QString("(%1 ") + sdocs + "/%2 " + sfiles +
qs2utf8s(tr("(%d documents/%d files/%d errors/%d total files) ")); "/%3 " + serrors + "/%4 " + tr("total files)");
sprintf(cnts, format.c_str(), stats = stats.arg(status.docsdone).arg(status.filesdone).
status.docsdone, status.filesdone, status.fileerrors, arg(status.fileerrors).arg(status.totfiles);
status.totfiles);
} else { } else {
string format = stats = QString("(%1 ") + sdocs + "/%2 " + sfiles +
qs2utf8s(tr("(%d documents/%d files/%d errors) ")); "/%3 " + serrors + ") ";
sprintf(cnts, format.c_str(), stats = stats.arg(status.docsdone).arg(status.filesdone).
status.docsdone, status.filesdone, status.fileerrors); arg(status.fileerrors);
} }
msg += QString::fromUtf8(cnts) + " "; msg += stats + " ";
} }
string mf;int ecnt = 0; string mf;int ecnt = 0;
string fcharset = theconfig->getDefCharset(true); string fcharset = theconfig->getDefCharset(true);
@ -495,6 +497,8 @@ void RclMain::specialIndex()
args.push_back("-Z"); args.push_back("-Z");
} else { } else {
args.push_back("-e"); args.push_back("-e");
// -e also needs -i, else we don't reindex, just erase
args.push_back("-i");
} }
} }

View File

@ -9,8 +9,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>413</width> <width>610</width>
<height>191</height> <height>192</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -70,7 +70,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="textLabel1"> <widget class="QLabel" name="textLabel1">
<property name="text"> <property name="text">
<string>Start directory (else use regular topdirs):</string> <string>Start directory. Must be part of the indexed tree. Use full indexed area if empty.</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>false</bool> <bool>false</bool>

View File

@ -90,9 +90,6 @@
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>Enter search terms here.</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>

130
src/testmains/trmbox.cpp Normal file
View File

@ -0,0 +1,130 @@
/* Copyright (C) 2017-2019 J.F.Dockes
*
* License: GPL 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <iostream>
#include <string>
using namespace std;
#include "rclconfig.h"
#include "rclinit.h"
#include "cstr.h"
#include "mh_mbox.h"
static char *thisprog;
static char usage [] =
"Test driver for mbox walking function\n"
"mh_mbox [-m num] mboxfile\n"
" \n\n"
;
static void
Usage(void)
{
fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
exit(1);
}
static RclConfig *config;
static int op_flags;
#define OPT_MOINS 0x1
#define OPT_m 0x2
//#define OPT_t 0x4
int main(int argc, char **argv)
{
string msgnum;
thisprog = argv[0];
argc--; argv++;
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
Usage();
while (**argv)
switch (*(*argv)++) {
case 'm': op_flags |= OPT_m; if (argc < 2) Usage();
msgnum = *(++argv);
argc--;
goto b1;
// case 't': op_flags |= OPT_t;break;
default: Usage(); break;
}
b1: argc--; argv++;
}
if (argc != 1)
Usage();
string filename = *argv++;argc--;
string reason;
config = recollinit(RclInitFlags(0), 0, 0, reason, 0);
if (config == 0) {
cerr << "init failed " << reason << endl;
exit(1);
}
config->setKeyDir(path_getfather(filename));
MimeHandlerMbox mh(config, "some_id");
if (!mh.set_document_file("text/x-mail", filename)) {
cerr << "set_document_file failed" << endl;
exit(1);
}
if (!msgnum.empty()) {
mh.skip_to_document(msgnum);
if (!mh.next_document()) {
cerr << "next_document failed after skipping to " << msgnum << endl;
exit(1);
}
map<string, string>::const_iterator it =
mh.get_meta_data().find(cstr_dj_keycontent);
int size;
if (it == mh.get_meta_data().end()) {
size = -1;
cerr << "No content!!" << endl;
exit(1);
}
cout << "Doc " << msgnum << ":" << endl;
cout << it->second << endl;
exit(0);
}
int docnt = 0;
while (mh.has_documents()) {
if (!mh.next_document()) {
cerr << "next_document failed" << endl;
exit(1);
}
docnt++;
map<string, string>::const_iterator it =
mh.get_meta_data().find(cstr_dj_keycontent);
int size;
if (it == mh.get_meta_data().end()) {
size = -1;
} else {
size = it->second.length();
}
cout << "Doc " << docnt << " size " << size << endl;
}
cout << docnt << " documents found in " << filename << endl;
exit(0);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2004 J.F.Dockes /* Copyright (C) 2004-2019 J.F.Dockes
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or * the Free Software Foundation; either version 2.1 of the License, or
@ -57,9 +57,9 @@
#include "safesysstat.h" #include "safesysstat.h"
#include "transcode.h" #include "transcode.h"
#define STAT _wstat #define STAT _wstati64
#define LSTAT _wstat #define LSTAT _wstati64
#define STATBUF _stat #define STATBUF _stati64
#define ACCESS _waccess #define ACCESS _waccess
#else // Not windows -> #else // Not windows ->
@ -654,18 +654,18 @@ bool path_makepath(const string& ipath, int mode)
vector<string> elems; vector<string> elems;
stringToTokens(path, elems, "/"); stringToTokens(path, elems, "/");
path = "/"; path = "/";
for (vector<string>::const_iterator it = elems.begin(); for (const auto& elem : elems) {
it != elems.end(); it++) {
#ifdef _WIN32 #ifdef _WIN32
if (it == elems.begin() && path_strlookslikedrive(*it)) { if (path == "/" && path_strlookslikedrive(elem)) {
path = ""; path = "";
} }
#endif #endif
path += *it; path += elem;
// Not using path_isdir() here, because this cant grok symlinks // Not using path_isdir() here, because this cant grok symlinks
// If we hit an existing file, no worry, mkdir will just fail. // If we hit an existing file, no worry, mkdir will just fail.
if (access(path.c_str(), 0) != 0) { if (access(path.c_str(), 0) != 0) {
if (mkdir(path.c_str(), mode) != 0) { if (mkdir(path.c_str(), mode) != 0) {
//cerr << "mkdir " << path << " failed, errno " << errno << endl;
return false; return false;
} }
} }

View File

@ -83,7 +83,7 @@ static bool path_isdriveabs(const string& s)
#include <Shlwapi.h> #include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib") #pragma comment(lib, "shlwapi.lib")
string path_thisexecpath() static string path_thisexecpath()
{ {
wchar_t text[MAX_PATH]; wchar_t text[MAX_PATH];
GetModuleFileNameW(NULL, text, MAX_PATH); GetModuleFileNameW(NULL, text, MAX_PATH);
@ -100,13 +100,16 @@ string path_thisexecpath()
return path; return path;
} }
string path_wingettempfilename(wchar_t *pref)
// On Windows, we ese a subdirectory named "rcltmp" inside the windows
// temp location to create the temporary files in.
static const string& path_wingetrcltmpdir()
{ {
// Use a subdirectory named "rcltmp" inside the windows temp // Constant: only need to compute once
// location. static string tdir;
if (tdir.empty()) {
wchar_t dbuf[MAX_PATH + 1]; wchar_t dbuf[MAX_PATH + 1];
GetTempPathW(MAX_PATH + 1, dbuf); GetTempPathW(MAX_PATH + 1, dbuf);
string tdir;
wchartoutf8(dbuf, tdir); wchartoutf8(dbuf, tdir);
tdir = path_cat(tdir, "rcltmp");; tdir = path_cat(tdir, "rcltmp");;
if (!path_exists(tdir)) { if (!path_exists(tdir)) {
@ -114,11 +117,21 @@ string path_wingettempfilename(wchar_t *pref)
LOGSYSERR("path_wingettempfilename", "path_makepath", tdir); LOGSYSERR("path_wingettempfilename", "path_makepath", tdir);
} }
} }
}
return tdir;
}
static bool path_gettempfilename(string& filename, string& reason)
{
string tdir = path_wingetrcltmpdir();
wchar_t dbuf[MAX_PATH + 1];
utf8towchar(tdir, dbuf, MAX_PATH); utf8towchar(tdir, dbuf, MAX_PATH);
wchar_t buf[MAX_PATH + 1]; wchar_t buf[MAX_PATH + 1];
GetTempFileNameW(dbuf, pref, 0, buf); static wchar_t prefix[]{L"rcl"};
string filename; GetTempFileNameW(dbuf, prefix, 0, buf);
wchartoutf8(buf, filename); wchartoutf8(buf, filename);
// Windows will have created a temp file, we delete it. // Windows will have created a temp file, we delete it.
if (!DeleteFileW(buf)) { if (!DeleteFileW(buf)) {
LOGSYSERR("path_wingettempfilename", "DeleteFileW", filename); LOGSYSERR("path_wingettempfilename", "DeleteFileW", filename);
@ -126,10 +139,35 @@ string path_wingettempfilename(wchar_t *pref)
LOGDEB1("path_wingettempfilename: DeleteFile " << filename << " Ok\n"); LOGDEB1("path_wingettempfilename: DeleteFile " << filename << " Ok\n");
} }
path_slashize(filename); path_slashize(filename);
return filename; return true;
} }
#endif // _WIN32 #else // _WIN32 above
static bool path_gettempfilename(string& filename, string& reason)
{
filename = path_cat(tmplocation(), "rcltmpfXXXXXX");
char *cp = strdup(filename.c_str());
if (!cp) {
reason = "Out of memory (for file name !)\n";
return false;
}
// Using mkstemp this way is awful (bot the suffix adding and
// using mkstemp() instead of mktemp just to avoid the warnings)
int fd;
if ((fd = mkstemp(cp)) < 0) {
free(cp);
reason = "TempFileInternal: mkstemp failed\n";
return false;
}
close(fd);
unlink(cp);
filename = cp;
free(cp);
return true;
}
#endif // posix
// Check if path is either non-existing or an empty directory. // Check if path is either non-existing or an empty directory.
bool path_empty(const string& path) bool path_empty(const string& path)
@ -259,7 +297,7 @@ bool maketmpdir(string& tdir, string& reason)
// There is a race condition between name computation and // There is a race condition between name computation and
// mkdir. try to make sure that we at least don't shoot ourselves // mkdir. try to make sure that we at least don't shoot ourselves
// in the foot // in the foot
#if !defined(HAVE_MKDTEMP) || defined(_WIN32) #if !defined(HAVE_MKDTEMP)
static std::mutex mmutex; static std::mutex mmutex;
std::unique_lock<std::mutex> lock(mmutex); std::unique_lock<std::mutex> lock(mmutex);
#endif #endif
@ -285,8 +323,9 @@ bool maketmpdir(string& tdir, string& reason)
// in the foot // in the foot
static std::mutex mmutex; static std::mutex mmutex;
std::unique_lock<std::mutex> lock(mmutex); std::unique_lock<std::mutex> lock(mmutex);
static wchar_t tmpbasename[]{L"rcltmp"}; if (!path_gettempfilename(tdir, reason)) {
tdir = path_wingettempfilename(tmpbasename); return false;
}
#endif #endif
// At this point the directory does not exist yet except if we used // At this point the directory does not exist yet except if we used
@ -356,32 +395,10 @@ TempFile::Internal::Internal(const string& suffix)
static std::mutex mmutex; static std::mutex mmutex;
std::unique_lock<std::mutex> lock(mmutex); std::unique_lock<std::mutex> lock(mmutex);
#ifndef _WIN32 if (!path_gettempfilename(m_filename, m_reason)) {
string filename = path_cat(tmplocation(), "rcltmpfXXXXXX");
char *cp = strdup(filename.c_str());
if (!cp) {
m_reason = "Out of memory (for file name !)\n";
return; return;
} }
m_filename += suffix;
// Using mkstemp this way is awful (bot the suffix adding and
// using mkstemp() instead of mktemp just to avoid the warnings)
int fd;
if ((fd = mkstemp(cp)) < 0) {
free(cp);
m_reason = "TempFileInternal: mkstemp failed\n";
return;
}
close(fd);
unlink(cp);
filename = cp;
free(cp);
#else
static wchar_t tmpbasename[]{L"rcl"};
string filename = path_wingettempfilename(tmpbasename);
#endif
m_filename = filename + suffix;
LOGDEB1("TempFile: filename: " << m_filename << endl); LOGDEB1("TempFile: filename: " << m_filename << endl);
int fd1 = open(m_filename.c_str(), O_CREAT | O_EXCL, 0600); int fd1 = open(m_filename.c_str(), O_CREAT | O_EXCL, 0600);
if (fd1 < 0) { if (fd1 < 0) {
@ -393,6 +410,15 @@ TempFile::Internal::Internal(const string& suffix)
} }
} }
const std::string& TempFile::rcltmpdir()
{
#ifdef _WIN32
return path_wingetrcltmpdir();
#else
return tmplocation();
#endif
}
#ifdef _WIN32 #ifdef _WIN32
static list<string> remainingTempFileNames; static list<string> remainingTempFileNames;
static std::mutex remTmpFNMutex; static std::mutex remTmpFNMutex;

View File

@ -63,6 +63,10 @@ public:
// process). Called after clearing the mimeHandler cache. Does // process). Called after clearing the mimeHandler cache. Does
// nothing if not _WIN32 // nothing if not _WIN32
static void tryRemoveAgain(); static void tryRemoveAgain();
// Also for Windows: for adding the temp files path to the default
// skippedPaths
static const std::string& rcltmpdir();
class Internal; class Internal;
private: private:
std::shared_ptr<Internal> m; std::shared_ptr<Internal> m;

View File

@ -1283,7 +1283,7 @@ bool SimpleRegexp::simpleMatch(const string& val) const
{ {
if (!ok()) if (!ok())
return false; return false;
return regex_match(val, m->res, m->expr); return regex_search(val, m->res, m->expr);
} }
string SimpleRegexp::getMatch(const string& val, int i) const string SimpleRegexp::getMatch(const string& val, int i) const