Skip to content

Commit 51b745f

Browse files
committed
oxcical: let oxcical_parse_rrule emit more error code detail
What once was reported as E-2718 is now reported as E-2801..E-2823. As such, be wary about E-2817 (because it looks so much like E-2718); it is a new error code. References: GXL-475, GXL-598, DESK-3399, DESK-3426
1 parent b72ece2 commit 51b745f

File tree

4 files changed

+96
-69
lines changed

4 files changed

+96
-69
lines changed

include/gromox/ical.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,6 @@ extern GX_EXPORT bool ical_parse_duration(const char *str_duration, long *psecon
162162
extern GX_EXPORT bool ical_itime_to_utc(const ical_component *, ical_time, time_t *);
163163
extern GX_EXPORT bool ical_datetime_to_utc(const ical_component *, const char *datetime, time_t *);
164164
extern GX_EXPORT bool ical_utc_to_datetime(const ical_component *, time_t utc_time, ical_time *);
165-
extern GX_EXPORT bool ical_parse_rrule(const ical_component *, time_t start, const std::vector<ical_value> *, ical_rrule *);
165+
extern GX_EXPORT const char *ical_parse_rrule(const ical_component *, time_t start, const std::vector<ical_value> *, ical_rrule *);
166166
extern GX_EXPORT int weekday_to_int(const char *);
167167
extern GX_EXPORT const char *weekday_to_str(unsigned int);

lib/email/ical.cpp

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,15 +1771,19 @@ static void ical_next_rrule_base_itime(ical_rrule *pirrule)
17711771
}
17721772
}
17731773

1774-
/* ptz_component can be NULL, represents UTC */
1775-
bool ical_parse_rrule(const ical_component *ptz_component,
1774+
/*
1775+
* @ptz_component: if NULL, represents UTC
1776+
*
1777+
* On success, returns %nullptr. On error, the error indicator string is returned.
1778+
*/
1779+
const char *ical_parse_rrule(const ical_component *ptz_component,
17761780
time_t start_time, const std::vector<ical_value> *pvalue_list,
17771781
ical_rrule *pirrule)
17781782
{
17791783
*pirrule = {};
17801784
auto pvalue = ical_get_first_subvalue_by_name_internal(pvalue_list, "FREQ");
17811785
if (pvalue == nullptr)
1782-
return false;
1786+
return "E-2824: RRULE has no FREQ";
17831787
if (strcasecmp(pvalue, "SECONDLY") == 0)
17841788
pirrule->frequency = ical_frequency::second;
17851789
else if (strcasecmp(pvalue, "MINUTELY") == 0)
@@ -1795,33 +1799,33 @@ bool ical_parse_rrule(const ical_component *ptz_component,
17951799
else if (strcasecmp(pvalue, "YEARLY") == 0)
17961800
pirrule->frequency = ical_frequency::year;
17971801
else
1798-
return false;
1802+
return "E-2825: RRULE has invalid FREQ";
17991803
pirrule->real_frequency = pirrule->frequency;
18001804
pvalue = ical_get_first_subvalue_by_name_internal(pvalue_list, "INTERVAL");
18011805
if (NULL == pvalue) {
18021806
pirrule->interval = 1;
18031807
} else {
18041808
pirrule->interval = strtol(pvalue, nullptr, 0);
18051809
if (pirrule->interval <= 0)
1806-
return false;
1810+
return "E-2826: RRULE has invalid INTERVAL";
18071811
}
18081812
pvalue = ical_get_first_subvalue_by_name_internal(pvalue_list, "COUNT");
18091813
if (NULL == pvalue) {
18101814
pirrule->total_count = 0;
18111815
} else {
18121816
pirrule->total_count = strtol(pvalue, nullptr, 0);
18131817
if (pirrule->total_count <= 0)
1814-
return false;
1818+
return "E-2827: RRULE has invalid COUNT";
18151819
}
18161820
pvalue = ical_get_first_subvalue_by_name_internal(pvalue_list, "UNTIL");
18171821
if (NULL != pvalue) {
18181822
if (pirrule->total_count != 0)
1819-
return false;
1823+
return "E-2828: Cannot combine COUNT with UNTIL in RRULE";
18201824
time_t until_time;
18211825
if (!ical_parse_until(ptz_component, pvalue, &until_time))
1822-
return false;
1826+
return "E-2829: RRULE has invalid UNTIL";
18231827
if (until_time < start_time)
1824-
return false;
1828+
return "E-2830: RRULE has UNTIL < DTSTART";
18251829
/* until==start can happen with a recurrent series with one occurrence */
18261830
pirrule->b_until = true;
18271831
ical_utc_to_datetime(ptz_component,
@@ -1910,14 +1914,14 @@ bool ical_parse_rrule(const ical_component *ptz_component,
19101914
if (pirrule->frequency != ical_frequency::week &&
19111915
pirrule->frequency != ical_frequency::month &&
19121916
pirrule->frequency != ical_frequency::year)
1913-
return false;
1917+
return "E-2841: RRULE has BYDAY but is not of frequency WEEK/MONTH/YEAR";
19141918
for (const auto &pnv2 : *pbywday_list) {
19151919
int dayofweek = -1, weekorder = -1;
19161920
if (!ical_parse_byday(pnv2.c_str(), &dayofweek, &weekorder))
19171921
continue;
19181922
if (ical_frequency::month == pirrule->frequency) {
19191923
if (weekorder > 5 || weekorder < -5)
1920-
return false;
1924+
return "E-2844: RRULE.FREQ=MONTHLY with invalid weekorder";
19211925
else if (weekorder > 0)
19221926
ical_set_bitmap(pirrule->wday_bitmap,
19231927
7*(weekorder - 1) + dayofweek);
@@ -1939,7 +1943,7 @@ bool ical_parse_rrule(const ical_component *ptz_component,
19391943
ical_set_bitmap(pirrule->wday_bitmap, 7*i + dayofweek);
19401944
} else {
19411945
if (weekorder != 0)
1942-
return false;
1946+
return "E-2845: RRULE with invalid weekorder";
19431947
ical_set_bitmap(pirrule->wday_bitmap, dayofweek);
19441948
}
19451949
}
@@ -1982,57 +1986,57 @@ bool ical_parse_rrule(const ical_component *ptz_component,
19821986
if (NULL != psetpos_list) {
19831987
switch (pirrule->frequency) {
19841988
case ical_frequency::second:
1985-
return false;
1989+
return "E-2850: RRULE has both BYSECOND and BYSETPOS";
19861990
case ical_frequency::minute:
19871991
if (pirrule->real_frequency != ical_frequency::second)
1988-
return false;
1992+
return "E-2851";
19891993
if (60 * pirrule->interval > 366)
1990-
return false;
1994+
return "E-2852";
19911995
break;
19921996
case ical_frequency::hour:
19931997
if (pirrule->real_frequency != ical_frequency::minute)
1994-
return false;
1998+
return "E-2853";
19951999
if (60 * pirrule->interval > 366)
1996-
return false;
2000+
return "E-2854";
19972001
break;
19982002
case ical_frequency::day:
19992003
if (pirrule->real_frequency != ical_frequency::hour)
2000-
return false;
2004+
return "E-2855";
20012005
if (24 * pirrule->interval > 366)
2002-
return false;
2006+
return "E-2856";
20032007
break;
20042008
case ical_frequency::week:
20052009
if (pirrule->real_frequency == ical_frequency::day) {
20062010
break;
20072011
} else if (pirrule->real_frequency == ical_frequency::hour) {
20082012
if (7 * 24 * pirrule->interval > 366)
2009-
return false;
2013+
return "E-2857";
20102014
break;
20112015
}
2012-
return false;
2016+
return "E-2858";
20132017
case ical_frequency::month:
20142018
if (pirrule->real_frequency == ical_frequency::day) {
20152019
if (31 * pirrule->interval > 366)
2016-
return false;
2020+
return "E-2859";
20172021
} else if (pirrule->real_frequency == ical_frequency::week) {
20182022
if (5 * pirrule->interval > 366)
2019-
return false;
2023+
return "E-2860";
20202024
} else {
2021-
return false;
2025+
return "E-2861";
20222026
}
20232027
break;
20242028
case ical_frequency::year:
20252029
if (pirrule->real_frequency == ical_frequency::day) {
20262030
if (pirrule->interval > 1)
2027-
return false;
2031+
return "E-2862";
20282032
} else if (pirrule->real_frequency == ical_frequency::week) {
20292033
if (pirrule->interval > 8)
2030-
return false;
2034+
return "E-2863";
20312035
} else if (pirrule->real_frequency == ical_frequency::month) {
20322036
if (pirrule->interval > 30)
2033-
return false;
2037+
return "E-2864";
20342038
} else {
2035-
return false;
2039+
return "E-2865";
20362040
}
20372041
break;
20382042
}
@@ -2053,7 +2057,7 @@ bool ical_parse_rrule(const ical_component *ptz_component,
20532057
if (NULL != pvalue) {
20542058
auto dow = weekday_to_int(pvalue);
20552059
if (dow < 0)
2056-
return false;
2060+
return "E-2868";
20572061
pirrule->weekstart = dow;
20582062
} else {
20592063
pirrule->weekstart = pbywnum_list != nullptr;
@@ -2129,7 +2133,7 @@ bool ical_parse_rrule(const ical_component *ptz_component,
21292133
itime < pirrule->next_base_itime;
21302134
itime = ical_next_rrule_itime(pirrule, hint_result, itime)) {
21312135
if (pirrule->b_until && itime > pirrule->until_itime)
2132-
return false;
2136+
return "E-2869";
21332137
hint_result = ical_test_rrule(pirrule, itime);
21342138
if (hint_result != rrule_by::setpos)
21352139
continue;
@@ -2146,10 +2150,10 @@ bool ical_parse_rrule(const ical_component *ptz_component,
21462150
pirrule->real_start_itime = itime;
21472151
pirrule->current_instance = 1;
21482152
pirrule->next_base_itime = pirrule->base_itime;
2149-
return true;
2153+
return nullptr;
21502154
}
21512155
pirrule->current_instance = 1;
2152-
return true;
2156+
return nullptr;
21532157
}
21542158
auto base_itime = pirrule->base_itime;
21552159
itime = pirrule->instance_itime;
@@ -2166,7 +2170,7 @@ bool ical_parse_rrule(const ical_component *ptz_component,
21662170
}
21672171
pirrule->current_instance = 1;
21682172
pirrule->b_start_exceptional = true;
2169-
return true;
2173+
return nullptr;
21702174
}
21712175

21722176
bool ical_rrule::iterate()

lib/freebusy.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,11 @@ static bool recurrencepattern_to_rrule(const ical_component *tzcom,
212212
return false;
213213
line.append_value("WKST", wd);
214214
}
215-
return ical_parse_rrule(tzcom, start_whole, &line.value_list, irrule);
215+
auto err = ical_parse_rrule(tzcom, start_whole, &line.value_list, irrule);
216+
if (err == nullptr)
217+
return true;
218+
mlog(LV_ERR, "%s: RRULE parse: %s", __func__, err);
219+
return false;
216220
}
217221

218222
static bool find_recur_times(const ical_component *tzcom,

0 commit comments

Comments
 (0)