File: icalfilter.c

package info (click to toggle)
ical2html 2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 440 kB
  • ctags: 104
  • sloc: sh: 1,048; ansic: 670; makefile: 32
file content (187 lines) | stat: -rw-r--r-- 5,577 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 * icalfilter -- filter an iCalendar file
 *
 * Author: Bert Bos <bert@w3.org>
 * Created: 30 Sep 2002
 */

#include "config.h"
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <getopt.h>
#include <ctype.h>
/*
#include <icaltime.h>
#include <icalcomponent.h>
#include <icalerror.h>
#include <icaltimezone.h>
*/
#include <libical/ical.h>
#include <libical/icalss.h>
/*
#include <icalset.h>
#include <icalfileset.h>
*/

#define PRODID "-//W3C//NONSGML icalfilter 0.1//EN"

#define ERR_OUT_OF_MEM 1	/* Program exit codes */
#define ERR_USAGE 2
#define ERR_DATE 3
#define ERR_PARSE 4
#define ERR_FILEIO 5
#define ERR_ICAL_ERR 6		/* Other error */

#define USAGE "Usage: ical2html [options] input output\n\
  -p, --class=CLASS            only (PUBLIC, CONFIDENTIAL, PRIVATE, NONE)\n\
  -P, --not-class=CLASS        exclude (PUBLIC, CONFIDENTIAL, PRIVATE, NONE)\n\
  -c, --category=CATEGORY      only events of this category\n\
  -C, --not-category=CATEGORY  exclude events of this category\n\
  input and output are iCalendar files\n"

/* Long command line options */
static struct option options[] = {
  {"class", 1, 0, 'p'},
  {"not-class", 1, 0, 'P'},
  {"category", 1, 0, 'c'},
  {"not-category", 1, 0, 'C'},
  {0, 0, 0, 0}
};

#define OPTIONS "p:P:c:C:"

/* Structure for storing applicable events */
typedef struct _event_item {
  struct icaltimetype start;
  struct icaltimetype end;
  icalcomponent *event;
} event_item;



/* fatal -- print error message and exit with errcode */
static void fatal(int errcode, const char *message,...)
{
  va_list args;
  va_start(args, message);
  vfprintf(stderr, message, args);
  va_end(args);
  exit(errcode);
}


/* read_stream -- read size bytes into s from stream d */
static char* read_stream(char *s, size_t size, void *d)  
{  
  return fgets(s, size, (FILE*)d); 
} 


/* main */
int main(int argc, char *argv[])
{
  FILE* stream;
  icalcomponent *comp;
  icalparser *parser;
  char *classmask = NULL, *categorymask = NULL;
  char *notclassmask = NULL, *notcategorymask = NULL;
  char c;
  const char *class;
  icalset *out;
  icalcomponent *h, *next, *newset;
  icalproperty *p;

  /* We handle errors ourselves */
  icalerror_errors_are_fatal = 0;
  icalerrno = 0;

  /* Read commandline */
  while ((c = getopt_long(argc, argv, OPTIONS, options, NULL)) != -1) {
    switch (c) {
    case 'p': classmask = strdup(optarg); break;
    case 'P': notclassmask = strdup(optarg); break;
    case 'c': categorymask = strdup(optarg); break;
    case 'C': notcategorymask = strdup(optarg); break;
    default: fatal(ERR_USAGE, USAGE);
    }
  }
  /* Get input file name */
  if (optind == argc) fatal(ERR_USAGE, USAGE);
  stream = optind == argc ? stdin : fopen(argv[optind], "r");
  if (!stream) fatal(ERR_FILEIO, "%s: %s\n", argv[optind], strerror(errno));
  optind++;

  /* Get output file name */
  if (optind == argc) fatal(ERR_USAGE, USAGE);
  (void) unlink(argv[optind]);	/* Remove output file if it already exists */
  out = icalfileset_new(argv[optind]);
  if (!out) fatal(ERR_FILEIO, "%s: %s\n", argv[optind], strerror(errno));

  /* Should have no more arguments */
  if (optind + 1 != argc) fatal(ERR_USAGE, USAGE);

  /* Create a new parser object */
  parser = icalparser_new();

  /* Tell the parser what input stream it should use */
  icalparser_set_gen_data(parser, stream);

  /* Let the parser read the file and return all components */
  if (! (comp = icalparser_parse(parser, read_stream)))
    fatal(ERR_PARSE, "Parse error: %s\n", icalerror_strerror(icalerrno));
  icalparser_free(parser);

  /* Initialize a new VCALENDAR */
  newset = icalcomponent_vanew(ICAL_VCALENDAR_COMPONENT,
			       icalproperty_new_version("2.0"),
			       icalproperty_new_prodid(PRODID),
			       0);

  /* Iterate over VEVENTs */
  for (h = icalcomponent_get_first_component(comp, ICAL_VEVENT_COMPONENT);
       h; h = next) {

    next = icalcomponent_get_next_component(comp, ICAL_VEVENT_COMPONENT);

    /* Check if the event is of the right class (unless we accept all) */
    if (classmask || notclassmask) {
      p = icalcomponent_get_first_property(h, ICAL_CLASS_PROPERTY);
      class = p ? icalvalue_as_ical_string(icalproperty_get_value(p))
	: "NONE";
      if (classmask && strcasecmp(classmask, class) != 0) continue;
      if (notclassmask && strcasecmp(notclassmask, class) == 0) continue;
    }

    /* Check if the event is of the right category (unless we accept all) */
    if (categorymask) {
      p = icalcomponent_get_first_property(h, ICAL_CATEGORIES_PROPERTY);
      while (p && strcasecmp(categorymask, icalproperty_get_categories(p)))
	p = icalcomponent_get_next_property(h, ICAL_CATEGORIES_PROPERTY);
      if (!p) continue;		/* No category was equal to categorymask */
    }
    if (notcategorymask) {
      p = icalcomponent_get_first_property(h, ICAL_CATEGORIES_PROPERTY);
      while (p && strcasecmp(notcategorymask, icalproperty_get_categories(p)))
	p = icalcomponent_get_next_property(h, ICAL_CATEGORIES_PROPERTY);
      if (p) continue;		/* Some category equal to notcategorymask */
    }

    /* The event passed our filters, so add it to the output set */
    icalcomponent_remove_component(comp, h); /* Move from comp... */
    icalcomponent_add_component(newset, h); /* ... to out */
  }

  /* Put new vcalendar in output file, flush to disk and close file */
  icalfileset_add_component(out, newset);
  icalfileset_free(out);

  /* Clean up */
  icalcomponent_free(comp);

  return 0;
}