| 217 | | g_assert(vformat); |
|---|
| 218 | | g_assert(xmlfield); |
|---|
| 219 | | g_assert(name); |
|---|
| 220 | | |
|---|
| 221 | | osync_trace(TRACE_INTERNAL, "Handling \"%s\" xml attribute", name); |
|---|
| 222 | | VFormatAttribute *attr = vformat_attribute_new(NULL, name); |
|---|
| 223 | | add_values(attr, xmlfield, encoding); |
|---|
| 224 | | vformat_add_attribute(vformat, attr); |
|---|
| 225 | | return attr; |
|---|
| 226 | | */ |
|---|
| 227 | | VFormatAttribute *attr = vformat_attribute_new(NULL, name); |
|---|
| | 219 | * Basic Recurrence Rules |
|---|
| | 220 | * |
|---|
| | 221 | * The functions below are necessary for converting a xmlformat-event |
|---|
| | 222 | * to a vCalendar Recurrence Rule. |
|---|
| | 223 | * |
|---|
| | 224 | * Description: |
|---|
| | 225 | * convert_rrule_vcal_frequency get frequency value |
|---|
| | 226 | * convert_rrule_vcal_freqmod get frequency modifier |
|---|
| | 227 | * convert_rrule_vcal_countuntil get count or until value |
|---|
| | 228 | * convert_xml_rrule_to_vcal get interval and call functions above |
|---|
| | 229 | */ |
|---|
| | 230 | |
|---|
| | 231 | static char *convert_rrule_vcal_frequency(OSyncXMLField *xmlfield, int frequency_state_id) |
|---|
| | 232 | { |
|---|
| | 233 | const char *frequency = NULL; |
|---|
| | 234 | char *frequency_id = NULL; |
|---|
| | 235 | |
|---|
| | 236 | /* set Frequency */ |
|---|
| | 237 | frequency = osync_xmlfield_get_key_value(xmlfield, "Frequency"); |
|---|
| | 238 | |
|---|
| | 239 | /* get frequency: only D(1), W(2), MP(3), MD(4), YD(5) and YM(6) are allowed */ |
|---|
| | 240 | if (!strcmp(frequency, "DAILY")) { |
|---|
| | 241 | frequency_id = "D"; |
|---|
| | 242 | } else if (!strcmp(frequency, "WEEKLY")) { |
|---|
| | 243 | frequency_id = "W"; |
|---|
| | 244 | } else if (!strcmp(frequency, "MONTHLY") && frequency_state_id == 3) { |
|---|
| | 245 | frequency_id = "MP"; |
|---|
| | 246 | } else if (!strcmp(frequency, "MONTHLY") && frequency_state_id == 4) { |
|---|
| | 247 | frequency_id = "MD"; |
|---|
| | 248 | } else if (!strcmp(frequency, "YEARLY") && frequency_state_id == 5) { |
|---|
| | 249 | frequency_id = "YD"; |
|---|
| | 250 | } else if (!strcmp(frequency, "YEARLY") && frequency_state_id == 6) { |
|---|
| | 251 | frequency_id = "YM"; |
|---|
| | 252 | } else { |
|---|
| | 253 | osync_trace(TRACE_INTERNAL, "invalid or missing frequency"); |
|---|
| | 254 | return NULL; |
|---|
| | 255 | } |
|---|
| | 256 | |
|---|
| | 257 | return frequency_id; |
|---|
| | 258 | |
|---|
| | 259 | } |
|---|
| | 260 | |
|---|
| | 261 | static char *convert_rrule_vcal_freqmod(OSyncXMLField *xmlfield, gchar **rule, int size, int freqstate) |
|---|
| | 262 | { |
|---|
| | 263 | int i; |
|---|
| | 264 | GString *fm_buffer = g_string_new(""); |
|---|
| | 265 | |
|---|
| | 266 | /* for each modifier do... */ |
|---|
| | 267 | for(i=1; i < size-1; i++) { |
|---|
| | 268 | |
|---|
| | 269 | int count; |
|---|
| | 270 | char sign; |
|---|
| | 271 | |
|---|
| | 272 | if(fm_buffer->len > 0) |
|---|
| | 273 | g_string_append(fm_buffer, ","); |
|---|
| | 274 | |
|---|
| | 275 | /* check frequency modifier */ |
|---|
| | 276 | if (sscanf(rule[i], "%d%c" , &count, &sign) == 2) { |
|---|
| | 277 | |
|---|
| | 278 | /* we need to convert $COUNT- to -$COUNT -> RFC2445 */ |
|---|
| | 279 | if (sign == '-') |
|---|
| | 280 | count = -count; |
|---|
| | 281 | |
|---|
| | 282 | g_string_append_printf(fm_buffer, "%d", count); |
|---|
| | 283 | |
|---|
| | 284 | /* if first freqmod is "(-)2" and second one is "TU" we |
|---|
| | 285 | * have to convert it to 2TU */ |
|---|
| | 286 | if (i < size-2 && !sscanf(rule[i+1], "%d", &count)) { |
|---|
| | 287 | g_string_append_printf(fm_buffer, "%s", rule[i+1]); |
|---|
| | 288 | i++; |
|---|
| | 289 | } |
|---|
| | 290 | |
|---|
| | 291 | } else { |
|---|
| | 292 | /* e.g. Day or 'LD' (Last day) */ |
|---|
| | 293 | g_string_append(fm_buffer, rule[i]); |
|---|
| | 294 | } |
|---|
| | 295 | } |
|---|
| | 296 | |
|---|
| | 297 | return g_string_free(fm_buffer, FALSE); |
|---|
| | 298 | } |
|---|
| | 299 | |
|---|
| | 300 | static char *convert_rrule_vcal_until(const char *until_utc) |
|---|
| | 301 | { |
|---|
| | 302 | int offset = 0; |
|---|
| | 303 | char *until = NULL; |
|---|
| | 304 | |
|---|
| | 305 | |
|---|
| | 306 | /* UNTIL: 20070515T120000 */ |
|---|
| | 307 | /* It is UTC : change the offset from 0 to the system UTC offset.· |
|---|
| | 308 | * vcal doesn't store any TZ information. This means the device have to be |
|---|
| | 309 | * in the same Timezone as the host. |
|---|
| | 310 | */ |
|---|
| | 311 | |
|---|
| | 312 | struct tm *ttm = osync_time_vtime2tm(until_utc); |
|---|
| | 313 | offset = osync_time_timezone_diff(ttm); |
|---|
| | 314 | g_free(ttm); |
|---|
| | 315 | until = osync_time_vtime2localtime(until_utc, offset); |
|---|
| | 316 | |
|---|
| | 317 | return until; |
|---|
| | 318 | |
|---|
| | 319 | } |
|---|
| | 320 | |
|---|
| | 321 | VFormatAttribute *convert_xml_rrule_to_vcal(VFormat *vformat, OSyncXMLField *xmlfield, const char *rulename, const char *encoding) |
|---|
| | 322 | { |
|---|
| | 323 | VFormatAttribute *attr = vformat_attribute_new(NULL, rulename); |
|---|
| | 324 | |
|---|
| | 325 | int frequency_state_id = 0, counter = 0; |
|---|
| | 326 | char *rule = NULL; |
|---|
| | 327 | |
|---|
| | 328 | // Grad the latest key of the field and check if it is a frequency state |
|---|
| | 329 | const char *frequency_state = osync_xmlfield_get_nth_key_name(xmlfield, osync_xmlfield_get_key_count(xmlfield)-1); |
|---|
| | 330 | |
|---|
| | 331 | |
|---|
| | 332 | if (frequency_state) { |
|---|
| | 333 | if ( !strcmp(frequency_state, "ByDay")) |
|---|
| | 334 | frequency_state_id = 3; |
|---|
| | 335 | else if (!strcmp(frequency_state, "ByMonthDay")) |
|---|
| | 336 | frequency_state_id = 4; |
|---|
| | 337 | else if (!strcmp(frequency_state, "ByYearDay")) |
|---|
| | 338 | frequency_state_id = 5; |
|---|
| | 339 | else if (!strcmp(frequency_state, "ByMonth")) |
|---|
| | 340 | frequency_state_id = 6; |
|---|
| | 341 | } |
|---|
| | 342 | |
|---|
| | 343 | /* get Interval */ |
|---|
| | 344 | const char *interval = osync_xmlfield_get_key_value(xmlfield, "Interval"); |
|---|
| | 345 | |
|---|
| | 346 | /* set frequency */ |
|---|
| | 347 | const char *frequency = convert_rrule_vcal_frequency(xmlfield, frequency_state_id); |
|---|
| | 348 | |
|---|
| | 349 | if (frequency && interval ) |
|---|
| | 350 | rule = g_strdup_printf("%s%s", frequency, interval); |
|---|
| | 351 | |
|---|
| | 352 | // FIXME : handle advanced frequency_mod with a convert_rrule_vcal_freqmod |
|---|
| | 353 | // We have a frequency state |
|---|
| | 354 | if (frequency_state_id) { |
|---|
| | 355 | const char *freq_mod = osync_xmlfield_get_key_value(xmlfield, frequency_state); |
|---|
| | 356 | rule = g_strdup_printf("%s %s", rule, freq_mod); |
|---|
| | 357 | } |
|---|
| | 358 | |
|---|
| | 359 | const char *until_utc = osync_xmlfield_get_key_value(xmlfield, "Until"); |
|---|
| | 360 | if (until_utc) { |
|---|
| | 361 | char *until = convert_rrule_vcal_until(until_utc); |
|---|
| | 362 | rule = g_strdup_printf("%s %s", rule, until); |
|---|
| | 363 | } |
|---|
| | 364 | |
|---|
| | 365 | const char *count = osync_xmlfield_get_key_value(xmlfield, "Count"); |
|---|
| | 366 | if (count) { |
|---|
| | 367 | rule = g_strdup_printf("%s #%s", rule, count); |
|---|
| | 368 | } |
|---|
| | 369 | |
|---|
| | 370 | vformat_attribute_add_value(attr, rule); |
|---|
| | 371 | |
|---|