* make time & size checking a bit stricter, report errors to user

This commit is contained in:
Dirk-Jan C. Binnema 2011-07-16 12:50:17 +03:00
parent 199c6c9bd9
commit 6c62a066c8
5 changed files with 45 additions and 58 deletions

View File

@ -45,32 +45,18 @@ public:
if (!clear_prefix (begin))
return Xapian::BAD_VALUENO;
// now and begin should only appear at the end, so
// correct them...
if (begin == "today" || begin == "now")
std::swap (begin, end);
substitute_date (begin);
substitute_date (end);
substitute_date (begin, true);
substitute_date (end, false);
normalize_date (begin);
normalize_date (end);
// note, we'll have to compare the *completed*
// versions of begin and end to if the were specified
// in the opposite order; however, if that is true, we
// have to complete begin, end 'for real', as the
// begin date is completed to the begin of the
// interval, and the to the end of the interval
// ie. begin: 2008 -> 200801010000 end: 2008 ->
// 200812312359
if (complete_date12(begin,true) >
complete_date12(end, false))
std::swap (begin, end);
begin = complete_date12(begin,true);
begin = complete_date12(begin, true);
end = complete_date12(end, false);
if (begin > end)
throw Xapian::QueryParserError ("end time is before begin");
return (Xapian::valueno)MU_MSG_PSEUDO_FIELD_ID_DATESTR;
}
@ -93,13 +79,15 @@ private:
} else
return false;
}
void substitute_date (std::string& date) {
void substitute_date (std::string& date, bool is_begin) {
char datebuf[13];
time_t now = time(NULL);
if (date == "today") {
strftime(datebuf, sizeof(datebuf), "%Y%m%d0000",
strftime(datebuf, sizeof(datebuf),
is_begin ? "%Y%m%d0000" : "%Y%m%d2359",
localtime(&now));
date = datebuf;
} else if (date == "now") {
@ -189,9 +177,9 @@ private:
bool substitute_size (std::string& size) {
gchar str[16];
guint64 num = mu_str_size_parse_kmg (size.c_str());
if (num == G_MAXUINT64)
return false;
gint64 num = mu_str_size_parse_bkm(size.c_str());
if (num < 0)
throw Xapian::QueryParserError ("invalid size");
snprintf (str, sizeof(str), "%" G_GUINT64_FORMAT, num);
size = str;
return true;
@ -243,8 +231,8 @@ get_query (MuQuery *mqx, const char* searchexpr, GError **err)
} catch (...) {
/* some error occured */
g_set_error (err, 0, MU_ERROR_QUERY, "parse error in query '%s'",
searchexpr);
g_set_error (err, 0, MU_ERROR_QUERY,
"parse error in query");
g_free (preprocessed);
throw;
}

View File

@ -314,7 +314,7 @@ static void
add_terms_values_date (Xapian::Document& doc, MuMsg *msg,
MuMsgFieldId mfid)
{
char datebuf[13]; /* YYYYMMDDHHMMSS */
char datebuf[13]; /* YYYYMMDDHHMM\0 */
static const std::string pfx (1, mu_msg_field_xapian_prefix(mfid));
gint64 num = mu_msg_get_field_numeric (msg, mfid);

View File

@ -345,30 +345,28 @@ mu_str_date_parse_hdwmy (const char *nptr)
return delta <= now ? now - delta : never;
}
guint64
mu_str_size_parse_kmg (const char* str)
gint64
mu_str_size_parse_bkm (const char* str)
{
gint64 num;
char *end;
g_return_val_if_fail (str, G_MAXUINT64);
num = strtol (str, &end, 10);
if (num < 0)
return G_MAXUINT64;
if (!end || end[1] != '\0')
return G_MAXUINT64;
switch (tolower(end[0])) {
case 'b': return num; /* bytes */
case 'k': return num * 1000; /* kilobyte */
case 'm': return num * 1000 * 1000; /* megabyte */
/* case 'g': return num * 1000 * 1000 * 1000; /\* gigabyte *\/ */
default:
return G_MAXUINT64;
}
const char *cur;
g_return_val_if_fail (str, -1);
if (!isdigit(str[0]))
return -1;
num = atoi(str);
for (++str; isdigit(*str); ++str);
switch (tolower(*str)) {
case '\0':
case 'b' : return num; /* bytes */
case 'k': return num * 1000; /* kilobyte */
case 'm': return num * 1000 * 1000; /* megabyte */
default:
return -1;
}
}

View File

@ -215,10 +215,11 @@ time_t mu_str_date_parse_hdwmy (const char* str);
/**
* parse a byte size; a size is a number, with optionally a
* unit. Units recognized are K (1000) and M (1000*1000). Only the
* first letter is checked and the function is not case-sensitive, so
* 1000Kb, 3M will work equally well. Note, for kB, MB etc., we then
* follow the SI standards, not 2^10 etc.
* unit. Units recognized are b/B (bytes) k/K (1000) and m/M
* (1000*1000). Only the first letter is checked and the function is
* not case-sensitive, so 1000Kb, 3M will work equally well. Note,
* for kB, MB etc., we then follow the SI standards, not 2^10 etc. The
* 'b' may be omitted.
*
* practical sizes for email messages are in terms of Mb; even in
* extreme cases it should be under 100 Mb. Function return
@ -226,9 +227,9 @@ time_t mu_str_date_parse_hdwmy (const char* str);
*
* @param str a string with a size, such a "100", "100Kb", "1Mb"
*
* @return the corresponding time_t value (as a guint64)
* @return the corresponding size in bytes, or -1 in case of error
*/
guint64 mu_str_size_parse_kmg (const char* str);
gint64 mu_str_size_parse_bkm (const char* str);
/**
* create a full path from a path + a filename. function is _not_

View File

@ -347,13 +347,13 @@ test_mu_query_dates (void)
QResults queries[] = {
{ "date:20080731..20080804", 5},
{ "date:20080804..20080731", 5},
/* { "date:20080804..20080731", 5}, */
{ "date:2008-07/31..2008@08:04", 5},
{ "date:2008-0731..20080804 s:gcc", 1},
{ "date:2008-08-11-08-03..now", 1},
{ "date:2008-08-11-08-03..today", 1},
{ "date:now..2008-08-11-08-03", 1},
{ "date:today..2008-08-11-08-03", 1},
/* { "date:now..2008-08-11-08-03", 1}, */
/* { "date:today..2008-08-11-08-03", 1}, */
{ "date:2008-08-11-08-05..now", 0},
};