Back to index

lightning-sunbird  0.9+nobinonly
icalfileset.c
Go to the documentation of this file.
00001 /* -*- Mode: C -*-
00002   ======================================================================
00003   FILE: icalfileset.c
00004   CREATOR: eric 23 December 1999
00005   
00006   $Id: icalfileset.c,v 1.32 2004/09/22 07:26:18 acampi Exp $
00007   $Locker:  $
00008     
00009  (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
00010 
00011  This program is free software; you can redistribute it and/or modify
00012  it under the terms of either: 
00013 
00014     The LGPL as published by the Free Software Foundation, version
00015     2.1, available at: http://www.fsf.org/copyleft/lesser.html
00016 
00017   Or:
00018 
00019     The Mozilla Public License Version 1.0. You may obtain a copy of
00020     the License at http://www.mozilla.org/MPL/
00021 
00022  The Original Code is eric. The Initial Developer of the Original
00023  Code is Eric Busboom
00024 
00025 
00026  ======================================================================*/
00027 
00028 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032 
00033 #include "icalfileset.h"
00034 #include "icalgauge.h"
00035 #include <errno.h>
00036 #include <sys/stat.h> /* for stat */
00037 #ifndef WIN32
00038 #include <unistd.h> /* for stat, getpid */
00039 #else
00040 #include <io.h>
00041 #include <share.h>
00042 #endif
00043 #include <stdlib.h>
00044 #include <string.h>
00045 #include <fcntl.h> /* for fcntl */
00046 #include "icalfilesetimpl.h"
00047 #include "icalclusterimpl.h"
00048 
00049 #ifdef WIN32
00050 #define snprintf     _snprintf
00051 #define strcasecmp   stricmp
00052 
00053 #define _S_ISTYPE(mode, mask)  (((mode) & _S_IFMT) == (mask))
00054 
00055 #define S_ISDIR(mode)    _S_ISTYPE((mode), _S_IFDIR)
00056 #define S_ISREG(mode)    _S_ISTYPE((mode), _S_IFREG)
00057 #endif
00058 
00059 extern int errno;
00060 
00062 icalfileset_options icalfileset_options_default = {O_RDWR|O_CREAT, 0644, 0};
00063 
00064 int icalfileset_lock(icalfileset *set);
00065 int icalfileset_unlock(icalfileset *set);
00066 icalerrorenum icalfileset_read_file(icalfileset* set, mode_t mode);
00067 int icalfileset_filesize(icalfileset* set);
00068 
00069 icalerrorenum icalfileset_create_cluster(const char *path);
00070 
00071 icalset* icalfileset_new(const char* path)
00072 {
00073   return icalset_new(ICAL_FILE_SET, path, &icalfileset_options_default);
00074 }
00075 
00076 icalset* icalfileset_new_reader(const char* path)
00077 {
00078   icalfileset_options reader_options = icalfileset_options_default;
00079   reader_options.flags = O_RDONLY;
00080 
00081   return icalset_new(ICAL_FILE_SET, path, &reader_options);
00082 }
00083 
00084 icalset* icalfileset_new_writer(const char* path)
00085 {
00086   icalfileset_options writer_options = icalfileset_options_default;
00087   writer_options.flags = O_RDONLY;
00088 
00089   return icalset_new(ICAL_FILE_SET, path, &writer_options);
00090 }
00091 
00092 icalset* icalfileset_init(icalset *set, const char* path, void* options_in)
00093 {
00094   icalfileset_options *options = (options_in) ? options_in : &icalfileset_options_default;
00095   icalfileset *fset = (icalfileset*) set;
00096   int flags;
00097   mode_t mode;
00098   off_t cluster_file_size;
00099 
00100   icalerror_clear_errno();
00101   icalerror_check_arg_rz( (path!=0), "path");
00102   icalerror_check_arg_rz( (fset!=0), "fset");
00103 
00104   fset->path = strdup(path);
00105   fset->options = *options;
00106 
00107   flags = options->flags;
00108   mode  = options->mode;
00109 
00110   cluster_file_size = icalfileset_filesize(fset);
00111   
00112   if(cluster_file_size < 0){
00113     icalfileset_free(set);
00114     return 0;
00115   }
00116 
00117 #ifndef WIN32
00118   fset->fd = open(fset->path, flags, mode);
00119 #else
00120   fset->fd = open(fset->path, flags | O_BINARY, mode);
00121   /* fset->fd = sopen(fset->path,flags, _SH_DENYWR, _S_IREAD | _S_IWRITE); */
00122 #endif
00123     
00124   if (fset->fd < 0){
00125     icalerror_set_errno(ICAL_FILE_ERROR);
00126     icalfileset_free(set);
00127     return 0;
00128   }
00129 
00130 #ifndef WIN32
00131     icalfileset_lock(fset);
00132 #endif
00133     
00134     if(cluster_file_size > 0 ){
00135        icalerrorenum error;
00136        if((error = icalfileset_read_file(fset,mode))!= ICAL_NO_ERROR){
00137          icalfileset_free(set);
00138          return 0;
00139        }
00140     }
00141  
00142     if (options->cluster) {
00143        fset->cluster = icalcomponent_new_clone(icalcluster_get_component(options->cluster));
00144        fset->changed = 1;
00145     }
00146 
00147     if (fset->cluster == 0) {
00148       fset->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
00149     }
00150 
00151     return set;
00152 }
00153 
00154 
00155 icalcluster* icalfileset_produce_icalcluster(const char *path) {
00156   icalset *fileset;
00157   icalcluster *ret;
00158 
00159   int errstate = icalerror_errors_are_fatal;
00160   icalerror_errors_are_fatal = 0;
00161     
00162   fileset = icalfileset_new_reader(path);
00163   
00164 
00165   if (fileset == 0 && icalerrno == ICAL_FILE_ERROR) {
00166     /* file does not exist */
00167     ret = icalcluster_new(path, NULL);
00168   } else {
00169     ret = icalcluster_new(path, ((icalfileset*)fileset)->cluster);
00170     icalfileset_free(fileset);
00171   }
00172   
00173   icalerror_errors_are_fatal = errstate;
00174   icalerror_set_errno(ICAL_NO_ERROR);
00175   return ret;
00176 }
00177 
00178 
00179 
00180 char* icalfileset_read_from_file(char *s, size_t size, void *d)
00181 {
00182     char* p = s;
00183     int fd = (int)d;
00184 
00185     /* Simulate fgets -- read single characters and stop at '\n' */
00186 
00187     for(p=s; p<s+size-1;p++){
00188        
00189        if(read(fd,p,1) != 1 || *p=='\n'){
00190            p++;
00191            break;
00192        } 
00193     }
00194 
00195     *p = '\0';
00196     
00197     if(*s == 0){
00198        return 0;
00199     } else {
00200        return s;
00201     }
00202 
00203 }
00204 
00205 
00206 icalerrorenum icalfileset_read_file(icalfileset* set,mode_t mode)
00207 {
00208     icalparser *parser;
00209   
00210     parser = icalparser_new();
00211 
00212     icalparser_set_gen_data(parser,(void*)set->fd);
00213     set->cluster = icalparser_parse(parser,icalfileset_read_from_file);
00214     icalparser_free(parser);
00215 
00216     if (set->cluster == 0 || icalerrno != ICAL_NO_ERROR){
00217        icalerror_set_errno(ICAL_PARSE_ERROR);
00218        /*return ICAL_PARSE_ERROR;*/
00219     }
00220   
00221     if (icalcomponent_isa(set->cluster) != ICAL_XROOT_COMPONENT){
00222        /* The parser got a single component, so it did not put it in
00223           an XROOT. */
00224        icalcomponent *cl = set->cluster;
00225        set->cluster = icalcomponent_new(ICAL_XROOT_COMPONENT);
00226        icalcomponent_add_component(set->cluster,cl);
00227     }
00228 
00229     return ICAL_NO_ERROR;
00230 }
00231 
00232 int icalfileset_filesize(icalfileset* fset)
00233 {
00234     int cluster_file_size;
00235     struct stat sbuf;
00236     
00237     if (stat(fset->path,&sbuf) != 0){
00238        
00239        /* A file by the given name does not exist, or there was
00240           another error */
00241        cluster_file_size = 0;
00242        if (errno == ENOENT) {
00243            /* It was because the file does not exist */
00244            return 0;
00245        } else {
00246            /* It was because of another error */
00247            icalerror_set_errno(ICAL_FILE_ERROR);
00248            return -1;
00249        }
00250     } else {
00251        /* A file by the given name exists, but is it a regular file? */
00252        
00253        if (!S_ISREG(sbuf.st_mode)){ 
00254            /* Nope, not a regular file */
00255            icalerror_set_errno(ICAL_FILE_ERROR);
00256            return -1;
00257        } else {
00258            /* Lets assume that it is a file of the right type */
00259            return sbuf.st_size;
00260        }      
00261     }
00262 
00263     /*return -1; not reached*/
00264 }
00265 
00266 void icalfileset_free(icalset* set)
00267 {
00268     icalfileset *fset = (icalfileset*) set;
00269 
00270     icalerror_check_arg_rv((set!=0),"set");
00271 
00272     if (fset->cluster != 0){
00273        icalfileset_commit(set);
00274        icalcomponent_free(fset->cluster);
00275        fset->cluster=0;
00276     }
00277 
00278     if (fset->gauge != 0){
00279        icalgauge_free(fset->gauge);
00280        fset->gauge=0;
00281     }
00282 
00283     if(fset->fd > 0){
00284        icalfileset_unlock(fset);
00285        close(fset->fd);
00286        fset->fd = -1;
00287     }
00288 
00289     if(fset->path != 0){
00290        free(fset->path);
00291        fset->path = 0;
00292     }
00293 }
00294 
00295 const char* icalfileset_path(icalset* set) {
00296     icalerror_check_arg_rz((set!=0),"set");
00297 
00298     return ((icalfileset*)set)->path;
00299 }
00300 
00301 
00302 int icalfileset_lock(icalfileset *set)
00303 {
00304 #ifndef WIN32
00305     struct flock lock;
00306     int rtrn;
00307 
00308     icalerror_check_arg_rz((set->fd>0),"set->fd");
00309     errno = 0;
00310     lock.l_type = F_WRLCK;     /* F_RDLCK, F_WRLCK, F_UNLCK */
00311     lock.l_start = 0;  /* byte offset relative to l_whence */
00312     lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
00313     lock.l_len = 0;       /* #bytes (0 means to EOF) */
00314 
00315     rtrn = fcntl(set->fd, F_SETLKW, &lock);
00316 
00317     return rtrn;
00318 #else
00319        return 0;
00320 #endif
00321 }
00322 
00323 int icalfileset_unlock(icalfileset *set)
00324 {
00325 #ifndef WIN32
00326     struct flock lock;
00327     icalerror_check_arg_rz((set->fd>0),"set->fd");
00328 
00329     lock.l_type = F_WRLCK;     /* F_RDLCK, F_WRLCK, F_UNLCK */
00330     lock.l_start = 0;  /* byte offset relative to l_whence */
00331     lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
00332     lock.l_len = 0;       /* #bytes (0 means to EOF) */
00333 
00334     return (fcntl(set->fd, F_UNLCK, &lock)); 
00335 #else
00336        return 0;
00337 #endif
00338 }
00339 
00340 icalerrorenum icalfileset_commit(icalset* set)
00341 {
00342     char tmp[ICAL_PATH_MAX]; 
00343     char *str;
00344     icalcomponent *c;
00345     off_t write_size=0;
00346     icalfileset *fset = (icalfileset*) set;
00347 
00348     icalerror_check_arg_re((fset!=0),"set",ICAL_BADARG_ERROR);  
00349     
00350     icalerror_check_arg_re((fset->fd>0),"set->fd is invalid",
00351                         ICAL_INTERNAL_ERROR) ;
00352 
00353     if (fset->changed == 0 ){
00354        return ICAL_NO_ERROR;
00355     }
00356     
00357     if(lseek(fset->fd, 0, SEEK_SET) < 0){
00358        icalerror_set_errno(ICAL_FILE_ERROR);
00359        return ICAL_FILE_ERROR;
00360     }
00361     
00362     for(c = icalcomponent_get_first_component(fset->cluster,ICAL_ANY_COMPONENT);
00363        c != 0;
00364        c = icalcomponent_get_next_component(fset->cluster,ICAL_ANY_COMPONENT)){
00365        int sz;
00366 
00367        str = icalcomponent_as_ical_string(c);
00368     
00369        sz=write(fset->fd,str,strlen(str));
00370 
00371        if ( sz != strlen(str)){
00372            perror("write");
00373            icalerror_set_errno(ICAL_FILE_ERROR);
00374            return ICAL_FILE_ERROR;
00375        }
00376 
00377        write_size += sz;
00378     }
00379     
00380     fset->changed = 0;    
00381 
00382 #ifndef WIN32
00383     if(ftruncate(fset->fd,write_size) < 0){
00384        return ICAL_FILE_ERROR;
00385     }
00386 #else
00387        chsize( fset->fd, tell( fset->fd ) );
00388 #endif
00389     
00390     return ICAL_NO_ERROR;
00391 } 
00392 
00393 void icalfileset_mark(icalset* set) {
00394     icalerror_check_arg_rv((set!=0),"set");
00395 
00396     ((icalfileset*)set)->changed = 1;
00397 }
00398 
00399 icalcomponent* icalfileset_get_component(icalset* set){
00400     icalfileset *fset = (icalfileset*) set;
00401     icalerror_check_arg_rz((set!=0),"set");
00402 
00403     return fset->cluster;
00404 }
00405 
00406 
00407 /* manipulate the components in the set */
00408 
00409 icalerrorenum icalfileset_add_component(icalset *set,
00410                                    icalcomponent* child)
00411 {
00412     icalfileset *fset = (icalfileset*) set;
00413 
00414     icalerror_check_arg_re((set!=0),"set", ICAL_BADARG_ERROR);
00415     icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
00416 
00417     icalcomponent_add_component(fset->cluster,child);
00418 
00419     icalfileset_mark(set);
00420 
00421     return ICAL_NO_ERROR;
00422 }
00423 
00424 icalerrorenum icalfileset_remove_component(icalset *set,
00425                                       icalcomponent* child)
00426 {
00427     icalfileset *fset = (icalfileset*) set;
00428 
00429     icalerror_check_arg_re((set!=0),"set",ICAL_BADARG_ERROR);
00430     icalerror_check_arg_re((child!=0),"child",ICAL_BADARG_ERROR);
00431 
00432     icalcomponent_remove_component(fset->cluster,child);
00433 
00434     icalfileset_mark(set);
00435 
00436     return ICAL_NO_ERROR;
00437 }
00438 
00439 int icalfileset_count_components(icalset *set,
00440                              icalcomponent_kind kind)
00441 {
00442     icalfileset *fset = (icalfileset*) set;
00443 
00444     if (set == 0){
00445        icalerror_set_errno(ICAL_BADARG_ERROR);
00446        return -1;
00447     }
00448 
00449     return icalcomponent_count_components(fset->cluster,kind);
00450 }
00451 
00452 icalerrorenum icalfileset_select(icalset* set, icalgauge* gauge)
00453 {
00454     icalfileset *fset = (icalfileset*) set;
00455 
00456     icalerror_check_arg_re(gauge!=0,"gauge",ICAL_BADARG_ERROR);
00457 
00458     fset->gauge = gauge;
00459 
00460     return ICAL_NO_ERROR;
00461 }
00462 
00463 void icalfileset_clear(icalset* set)
00464 {
00465     icalfileset *fset = (icalfileset*) set;
00466 
00467     icalerror_check_arg_rv(set!=0,"set");
00468 
00469     fset->gauge = 0;
00470 }
00471 
00472 icalcomponent* icalfileset_fetch(icalset* set,const char* uid)
00473 {
00474     icalfileset *fset = (icalfileset*) set;
00475     icalcompiter i;    
00476 
00477     icalerror_check_arg_rz(set!=0,"set");
00478     
00479     for(i = icalcomponent_begin_component(fset->cluster,ICAL_ANY_COMPONENT);
00480        icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
00481        
00482               icalcomponent *this = icalcompiter_deref(&i);
00483               icalcomponent *inner;
00484               icalproperty *p;
00485               const char *this_uid;
00486 
00487               for(inner = icalcomponent_get_first_component(this,ICAL_ANY_COMPONENT);
00488                      inner != 0;
00489                      inner = icalcomponent_get_next_component(this,ICAL_ANY_COMPONENT)){
00490 
00491                      p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY);
00492                      if ( p )
00493                      {
00494                             this_uid = icalproperty_get_uid(p);
00495 
00496                             if(this_uid==0){
00497                             icalerror_warn("icalfileset_fetch found a component with no UID");
00498                             continue;
00499                             }
00500 
00501                             if (strcmp(uid,this_uid)==0){
00502                                    return this;
00503                             }
00504                      }
00505               }
00506        }
00507 
00508     return 0;
00509 }
00510 
00511 int icalfileset_has_uid(icalset* set,const char* uid)
00512 {
00513     assert(0); /* HACK, not implemented */
00514     return 0;
00515 }
00516 
00517 /******* support routines for icalfileset_fetch_match *********/
00518 
00519 struct icalfileset_id{
00520     char* uid;
00521     char* recurrence_id;
00522     int sequence;
00523 };
00524 
00525 void icalfileset_id_free(struct icalfileset_id *id)
00526 {
00527     if(id->recurrence_id != 0){
00528        free(id->recurrence_id);
00529     }
00530 
00531     if(id->uid != 0){
00532        free(id->uid);
00533     }
00534 }
00535 
00536 
00537 struct icalfileset_id icalfileset_get_id(icalcomponent* comp)
00538 {
00539     icalcomponent *inner;
00540     struct icalfileset_id id;
00541     icalproperty *p;
00542 
00543     inner = icalcomponent_get_first_real_component(comp);
00544     
00545     p = icalcomponent_get_first_property(inner, ICAL_UID_PROPERTY);
00546 
00547     assert(p!= 0);
00548 
00549     id.uid = strdup(icalproperty_get_uid(p));
00550 
00551     p = icalcomponent_get_first_property(inner, ICAL_SEQUENCE_PROPERTY);
00552 
00553     if(p == 0) {
00554        id.sequence = 0;
00555     } else { 
00556        id.sequence = icalproperty_get_sequence(p);
00557     }
00558 
00559     p = icalcomponent_get_first_property(inner, ICAL_RECURRENCEID_PROPERTY);
00560 
00561     if (p == 0){
00562        id.recurrence_id = 0;
00563     } else {
00564        icalvalue *v;
00565        v = icalproperty_get_value(p);
00566        id.recurrence_id = strdup(icalvalue_as_ical_string(v));
00567 
00568        assert(id.recurrence_id != 0);
00569     }
00570 
00571     return id;
00572 }
00573 
00574 
00575 /* Find the component that is related to the given
00576    component. Currently, it just matches based on UID and
00577    RECURRENCE-ID */
00578 icalcomponent* icalfileset_fetch_match(icalset* set, icalcomponent *comp)
00579 {
00580     icalfileset *fset = (icalfileset*) set;
00581     icalcompiter i;    
00582 
00583     struct icalfileset_id comp_id, match_id;
00584     
00585     comp_id = icalfileset_get_id(comp);
00586 
00587     for(i = icalcomponent_begin_component(fset->cluster,ICAL_ANY_COMPONENT);
00588        icalcompiter_deref(&i)!= 0; icalcompiter_next(&i)){
00589        
00590        icalcomponent *match = icalcompiter_deref(&i);
00591 
00592        match_id = icalfileset_get_id(match);
00593 
00594        if(strcmp(comp_id.uid, match_id.uid) == 0 &&
00595           ( comp_id.recurrence_id ==0 || 
00596             strcmp(comp_id.recurrence_id, match_id.recurrence_id) ==0 )){
00597 
00598            /* HACK. What to do with SEQUENCE? */
00599 
00600            icalfileset_id_free(&match_id);
00601            icalfileset_id_free(&comp_id);
00602            return match;
00603            
00604        }
00605        
00606        icalfileset_id_free(&match_id);
00607     }
00608 
00609     icalfileset_id_free(&comp_id);
00610     return 0;
00611 
00612 }
00613 
00614 
00615 icalerrorenum icalfileset_modify(icalset* set, icalcomponent *old,
00616                              icalcomponent *new)
00617 {
00618     icalfileset *fset = (icalfileset*) set;
00619 
00620     assert(0); /* HACK, not implemented */
00621     return ICAL_NO_ERROR;
00622 }
00623 
00624 
00625 /* Iterate through components */
00626 icalcomponent* icalfileset_get_current_component (icalset* set)
00627 {
00628     icalfileset *fset = (icalfileset*) set;
00629 
00630     icalerror_check_arg_rz((set!=0),"set");
00631 
00632     return icalcomponent_get_current_component(fset->cluster);
00633 }
00634 
00635 
00636 icalcomponent* icalfileset_get_first_component(icalset* set)
00637 {
00638     icalcomponent *c=0;
00639     icalfileset *fset = (icalfileset*) set;
00640 
00641     icalerror_check_arg_rz((set!=0),"set");
00642 
00643     do {
00644        if (c == 0){
00645            c = icalcomponent_get_first_component(fset->cluster,
00646                                             ICAL_ANY_COMPONENT);
00647        } else {
00648            c = icalcomponent_get_next_component(fset->cluster,
00649                                            ICAL_ANY_COMPONENT);
00650        }
00651 
00652        if(c != 0 && (fset->gauge == 0 ||
00653                     icalgauge_compare(fset->gauge, c) == 1)){
00654            return c;
00655        }
00656 
00657     } while(c != 0);
00658 
00659 
00660     return 0;
00661 }
00662 
00663 icalcomponent* icalfileset_get_next_component(icalset* set)
00664 {
00665     icalfileset *fset = (icalfileset*) set;
00666     icalcomponent *c;
00667 
00668     icalerror_check_arg_rz((set!=0),"set");
00669     
00670     do {
00671        c = icalcomponent_get_next_component(fset->cluster,
00672                                         ICAL_ANY_COMPONENT);
00673 
00674        if(c != 0 && (fset->gauge == 0 ||
00675                     icalgauge_compare(fset->gauge,c) == 1)){
00676            return c;
00677        }
00678        
00679     } while(c != 0);
00680     
00681     
00682     return 0;
00683 }
00684 /*
00685 icalsetiter icalfileset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge)
00686 {
00687     icalsetiter itr = icalsetiter_null;
00688     icalcomponent* comp = NULL;
00689     icalcompiter citr;
00690     icalfileset *fset = (icalfileset*) set;
00691 
00692     icalerror_check_arg_re((set!=0), "set", icalsetiter_null);
00693 
00694     itr.gauge = gauge;
00695 
00696     citr = icalcomponent_begin_component(fset->cluster, kind);
00697     comp = icalcompiter_deref(&citr);
00698 
00699     while (comp != 0) {
00700        comp = icalcompiter_deref(&citr);
00701        if (gauge == 0 || icalgauge_compare(itr.gauge, comp) == 1) {
00702            itr.iter = citr;
00703            return itr;
00704        }
00705        comp =  icalcompiter_next(&citr);
00706     }
00707 
00708     return icalsetiter_null;
00709 }
00710 */
00711 
00712 icalsetiter icalfileset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge)
00713 {
00714     icalsetiter itr = icalsetiter_null;
00715     icalcomponent* comp = NULL;
00716     icalcompiter citr;
00717     icalfileset *fset = (icalfileset*) set;
00718     struct icaltimetype start, next;
00719     icalproperty *dtstart, *rrule, *prop, *due;
00720     struct icalrecurrencetype recur;
00721     int g = 0;
00722 
00723     icalerror_check_arg_re((set!=0), "set", icalsetiter_null);
00724 
00725     itr.gauge = gauge;
00726 
00727     citr = icalcomponent_begin_component(fset->cluster, kind);
00728     comp = icalcompiter_deref(&citr);
00729 
00730     if (gauge == 0) {
00731         itr.iter = citr;
00732         return itr;
00733     }
00734 
00735     while (comp != 0) {
00736 
00737         /* check if it is a recurring component and with guage expand, if so
00738            we need to add recurrence-id property to the given component */
00739         rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY);
00740         g = icalgauge_get_expand(gauge);
00741 
00742         if (rrule != 0
00743             && g == 1) {
00744 
00745             recur = icalproperty_get_rrule(rrule);
00746             if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) {
00747                 dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
00748                 if (dtstart)
00749                     start = icalproperty_get_dtstart(dtstart);
00750             } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
00751                     due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
00752                     if (due)
00753                         start = icalproperty_get_due(due);
00754             }
00755 
00756             if (itr.last_component == NULL) {
00757                 itr.ritr = icalrecur_iterator_new(recur, start);
00758                 next = icalrecur_iterator_next(itr.ritr);
00759                 itr.last_component = comp;
00760             }
00761             else {
00762                 next = icalrecur_iterator_next(itr.ritr);
00763                 if (icaltime_is_null_time(next)){
00764                     itr.last_component = NULL;
00765                     icalrecur_iterator_free(itr.ritr);
00766                     itr.ritr = NULL;
00767                     return icalsetiter_null;
00768                 } else {
00769                     itr.last_component = comp;
00770                 }
00771             }
00772 
00773             /* add recurrence-id to the component
00774                if there is a recurrence-id already, remove it, then add the new one */
00775             if (prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY))
00776                 icalcomponent_remove_property(comp, prop);
00777             icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next));
00778 
00779         }
00780 
00781         if (gauge == 0 || icalgauge_compare(itr.gauge, comp) == 1) {
00782             /* matches and returns */
00783             itr.iter = citr;
00784             return itr;
00785         }
00786 
00787         /* if there is no previous component pending, then get the next component */
00788         if (itr.last_component == NULL)
00789             comp =  icalcompiter_next(&citr);
00790     }
00791 
00792     return icalsetiter_null;
00793 }
00794 icalcomponent* icalfileset_form_a_matched_recurrence_component(icalsetiter* itr)
00795 {
00796     icalcomponent* comp = NULL;
00797     struct icaltimetype start, next;
00798     icalproperty *dtstart, *rrule, *prop, *due;
00799     struct icalrecurrencetype recur;
00800 
00801     comp = itr->last_component;
00802 
00803     if (comp == NULL || itr->gauge == NULL) {
00804         return NULL;
00805     }
00806 
00807     rrule = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY);
00808 
00809     recur = icalproperty_get_rrule(rrule);
00810 
00811     if (icalcomponent_isa(comp) == ICAL_VEVENT_COMPONENT) {
00812         dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
00813         if (dtstart)
00814             start = icalproperty_get_dtstart(dtstart);
00815     } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
00816         due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
00817         if (due)
00818             start = icalproperty_get_due(due);
00819     }
00820 
00821     if (itr->ritr == NULL) {
00822         itr->ritr = icalrecur_iterator_new(recur, start);
00823         next = icalrecur_iterator_next(itr->ritr);
00824         itr->last_component = comp;
00825     } else {
00826         next = icalrecur_iterator_next(itr->ritr);
00827         if (icaltime_is_null_time(next)){
00828             /* no more recurrence, returns */
00829             itr->last_component = NULL;
00830             icalrecur_iterator_free(itr->ritr);
00831             itr->ritr = NULL;
00832             return NULL;
00833         } else {
00834             itr->last_component = comp;
00835         }
00836     }
00837 
00838     /* add recurrence-id to the component
00839      * if there is a recurrence-id already, remove it, then add the new one */
00840     if (prop = icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY))
00841         icalcomponent_remove_property(comp, prop);
00842         icalcomponent_add_property(comp, icalproperty_new_recurrenceid(next));
00843 
00844      if (itr->gauge == 0 || icalgauge_compare(itr->gauge, comp) == 1) {
00845          /* matches and returns */
00846          return comp;
00847      }
00848      /* not matched */
00849      return NULL;
00850 
00851 }
00852 icalcomponent* icalfilesetiter_to_next(icalset* set, icalsetiter* i)
00853 {
00854 
00855     icalcomponent* c = NULL;
00856     icalfileset *fset = (icalfileset*) set;
00857     struct icaltimetype start, next;
00858     icalproperty *dtstart, *rrule, *prop, *due;
00859     struct icalrecurrencetype recur;
00860     int g = 0;
00861 
00862 
00863     do {
00864         c = icalcompiter_next(&(i->iter));
00865 
00866         if (c == 0) continue;
00867         if (i->gauge == 0) return c;
00868 
00869 
00870         rrule = icalcomponent_get_first_property(c, ICAL_RRULE_PROPERTY);
00871         g = icalgauge_get_expand(i->gauge);
00872 
00873         /* a recurring component with expand query */
00874         if (rrule != 0
00875             && g == 1) {
00876 
00877             recur = icalproperty_get_rrule(rrule);
00878 
00879             if (icalcomponent_isa(c) == ICAL_VEVENT_COMPONENT) {
00880                 dtstart = icalcomponent_get_first_property(c, ICAL_DTSTART_PROPERTY);
00881                 if (dtstart)
00882                     start = icalproperty_get_dtstart(dtstart);
00883             } else if (icalcomponent_isa(c) == ICAL_VTODO_COMPONENT) {
00884                 due = icalcomponent_get_first_property(c, ICAL_DUE_PROPERTY);
00885                 if (due)
00886                     start = icalproperty_get_due(due);
00887             }
00888 
00889             if (i->ritr == NULL) {
00890                 i->ritr = icalrecur_iterator_new(recur, start);
00891                 next = icalrecur_iterator_next(i->ritr);
00892                 i->last_component = c;
00893             } else {
00894                 next = icalrecur_iterator_next(i->ritr);
00895                 if (icaltime_is_null_time(next)) {
00896                     /* no more recurrence, returns */
00897                     i->last_component = NULL;
00898                     icalrecur_iterator_free(i->ritr);
00899                     i->ritr = NULL;
00900                     return NULL;
00901                 } else {
00902                     i->last_component = c;
00903                 }
00904             }
00905         }
00906 
00907         /* add recurrence-id to the component
00908          * if there is a recurrence-id already, remove it, then add the new one */
00909         if (prop = icalcomponent_get_first_property(c, ICAL_RECURRENCEID_PROPERTY))
00910             icalcomponent_remove_property(c, prop);
00911         icalcomponent_add_property(c, icalproperty_new_recurrenceid(next));
00912 
00913         if(c != 0 && (i->gauge == 0 ||
00914                         icalgauge_compare(i->gauge, c) == 1)){
00915             return c;
00916         }
00917     } while (c != 0);
00918 
00919     return 0;
00920 
00921 }