diff options
Diffstat (limited to 'libkcal/libical/vzic-1.3')
-rw-r--r-- | libkcal/libical/vzic-1.3/ChangeLog | 57 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/Makefile | 83 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/Makefile.org | 89 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/README | 202 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/test-vzic.c | 422 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic-dump.c | 409 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic-dump.h | 58 | ||||
-rwxr-xr-x | libkcal/libical/vzic-1.3/vzic-dump.pl | 222 | ||||
-rwxr-xr-x | libkcal/libical/vzic-1.3/vzic-merge.pl | 127 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic-output.c | 2325 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic-output.h | 38 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic-parse.c | 901 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic-parse.h | 38 | ||||
-rwxr-xr-x | libkcal/libical/vzic-1.3/vzic-test.pl | 164 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic.c | 320 | ||||
-rw-r--r-- | libkcal/libical/vzic-1.3/vzic.h | 196 |
16 files changed, 0 insertions, 5651 deletions
diff --git a/libkcal/libical/vzic-1.3/ChangeLog b/libkcal/libical/vzic-1.3/ChangeLog deleted file mode 100644 index f2d9569e5..000000000 --- a/libkcal/libical/vzic-1.3/ChangeLog +++ /dev/null @@ -1,57 +0,0 @@ -2006-03-18 Damon Chaplin <damon@gnome.org> - - * Released Vzic 1.3 - -2006-03-18 Damon Chaplin <damon@gnome.org> - - * vzic-output.c (expand_tzname): added special case for America/Nome. - (output_rrule): made hacks a bit more general, to handle Asia/Gaza - which now has a day=4 rule. At some point we should check what newer - versions of Outlook can handle so we can be more accurate. - - * vzic-dump.c (dump_time_zone_names): try looking for timezone info - using original and linked name. - - * README, *.c: fixed spelling 'compatable' -> 'compatible'. - - * vzic.c: patch from Jonathan Guthrie to support a --olson-dir option. - -2003-10-25 Damon Chaplin <damon@gnome.org> - - * Released Vzic 1.2 - -2003-10-25 Damon Chaplin <damon@gnome.org> - - * vzic-output.c: - * Makefile: moved the PRODUCT_ID and TZID_PREFIX settings to the - Makefile and changed the default so people don't accidentally use - the same IDs as Evolution. - - * vzic-parse.c (parse_time): substitute 23:59:59 when we read a time - of 24:00:00. This is a bit of a kludge to avoid problems, since - 24:00:00 is not a valid iCalendar time. Since 24:00:00 is only used - for a few timezones in the 1930s it doesn't matter too much. - - To write a correct fix we'd need to review all the code that deals - with times to see if it would be affected, e.g. a time of 24:00 on - one day should be considered equal to 0:00 the next day. - - We'd also need to adjust the output times to use 0:00 the next day - rather than 24:00. If we need to output recurrence rules that would - be a problem, since 'last saturday at 24:00' can't be easily - converted to another rule that uses 0:00 instead. - -2003-10-22 Damon Chaplin <damon@gnome.org> - - * Released Vzic 1.1 - -2003-10-22 Damon Chaplin <damon@gnome.org> - - * vzic-parse.c (parse_time): allow a time of 24:00, as used in - the America/Montreal and America/Toronto rules in the 1930s! - I'm not 100% sure the rest of the code will handle this OK, but - it only affects the 'pure' output. - -2003-09-01 Damon Chaplin <damon@gnome.org> - - * Released Vzic 1.0 diff --git a/libkcal/libical/vzic-1.3/Makefile b/libkcal/libical/vzic-1.3/Makefile deleted file mode 100644 index 7196c1529..000000000 --- a/libkcal/libical/vzic-1.3/Makefile +++ /dev/null @@ -1,83 +0,0 @@ - -# -# You will need to set this to the directory that the Olson timezone data -# files are in. -# -OLSON_DIR = ../tzdata - - -# This is used as the PRODID property on the iCalendar files output. -# It identifies the product which created the iCalendar objects. -# So you need to substitute your own organization name and product. -PRODUCT_ID = -//KDE//NONSGML KCal Olson-VTIMEZONE Converter//EN - - -# This is used to create unique IDs for each VTIMEZONE component. -# The prefix is put before each timezone city name. It should start and end -# with a '/'. The first part, i.e. 'myorganization.org' below, should be -# a unique vendor ID, e.g. use a hostname. The part after that can be -# anything you want. We use a date and version number for libical. The %D -# gets expanded to today's date. There is also a vzic-merge.pl which can be -# used to merge changes into a master set of VTIMEZONEs. If a VTIMEZONE has -# changed, it bumps the version number on the end of this prefix. */ -TZID_PREFIX = /kde.org/Olson_%D_1/ - - -# Set any -I include directories to find the libical header files, and the -# libical library to link with. You only need these if you want to run the -# tests. You may need to change the '#include <ical.h>' line at the top of -# test-vzic.c as well. -LIBICAL_CFLAGS = -LIBICAL_LDADD = -lical-evolution - - -# -# You shouldn't need to change the rest of the file. -# - -GLIB_CFLAGS = `pkg-config --cflags glib-2.0` -GLIB_LDADD = `pkg-config --libs glib-2.0` - -CFLAGS = -g -DOLSON_DIR=\"$(OLSON_DIR)\" -DPRODUCT_ID='"$(PRODUCT_ID)"' -DTZID_PREFIX='"$(TZID_PREFIX)"' $(GLIB_CFLAGS) $(LIBICAL_CFLAGS) - -OBJECTS = vzic.o vzic-parse.o vzic-dump.o vzic-output.o - -all: vzic - -vzic: $(OBJECTS) - $(CC) $(OBJECTS) $(GLIB_LDADD) -o vzic - -test-vzic: test-vzic.o - $(CC) test-vzic.o $(LIBICAL_LDADD) -o test-vzic - -# Dependencies. -$(OBJECTS): vzic.h -vzic.o vzic-parse.o: vzic-parse.h -vzic.o vzic-dump.o: vzic-dump.h -vzic.o vzic-output.o: vzic-output.h - -test-parse: vzic - ./vzic-dump.pl $(OLSON_DIR) - ./vzic --dump --pure - @echo - @echo "#" - @echo "# If either of these diff commands outputs anything there may be a problem." - @echo "#" - diff -ru zoneinfo/ZonesPerl zoneinfo/ZonesVzic - diff -ru zoneinfo/RulesPerl zoneinfo/RulesVzic - -test-changes: vzic test-vzic - ./test-vzic --dump-changes - ./vzic --dump-changes --pure - @echo - @echo "#" - @echo "# If this diff command outputs anything there may be a problem." - @echo "#" - diff -ru zoneinfo/ChangesVzic test-output - -clean: - -rm -rf vzic $(OBJECTS) *~ ChangesVzic RulesVzic ZonesVzic RulesPerl ZonesPerl test-vzic test-vzic.o - -.PHONY: clean perl-dump test-parse - - diff --git a/libkcal/libical/vzic-1.3/Makefile.org b/libkcal/libical/vzic-1.3/Makefile.org deleted file mode 100644 index 4b5917c24..000000000 --- a/libkcal/libical/vzic-1.3/Makefile.org +++ /dev/null @@ -1,89 +0,0 @@ - -# -# You will need to set this to the directory that the Olson timezone data -# files are in. -# -OLSON_DIR = /home/damon/src/olson/tzdata2006b - - -# This is used as the PRODID property on the iCalendar files output. -# It identifies the product which created the iCalendar objects. -# So you need to substitute your own organization name and product. -PRODUCT_ID = -//My Organization//NONSGML My Product//EN - -# This is what libical-evolution uses. -#PRODUCT_ID = -//Ximian//NONSGML Evolution Olson-VTIMEZONE Converter//EN - - -# This is used to create unique IDs for each VTIMEZONE component. -# The prefix is put before each timezone city name. It should start and end -# with a '/'. The first part, i.e. 'myorganization.org' below, should be -# a unique vendor ID, e.g. use a hostname. The part after that can be -# anything you want. We use a date and version number for libical. The %D -# gets expanded to today's date. There is also a vzic-merge.pl which can be -# used to merge changes into a master set of VTIMEZONEs. If a VTIMEZONE has -# changed, it bumps the version number on the end of this prefix. */ -TZID_PREFIX = /myorganization.org/%D_1/ - -# This is what libical-evolution uses. -#TZID_PREFIX = /softwarestudio.org/Olson_%D_1/ - - -# Set any -I include directories to find the libical header files, and the -# libical library to link with. You only need these if you want to run the -# tests. You may need to change the '#include <ical.h>' line at the top of -# test-vzic.c as well. -LIBICAL_CFLAGS = -LIBICAL_LDADD = -lical-evolution - - -# -# You shouldn't need to change the rest of the file. -# - -GLIB_CFLAGS = `pkg-config --cflags glib-2.0` -GLIB_LDADD = `pkg-config --libs glib-2.0` - -CFLAGS = -g -DOLSON_DIR=\"$(OLSON_DIR)\" -DPRODUCT_ID='"$(PRODUCT_ID)"' -DTZID_PREFIX='"$(TZID_PREFIX)"' $(GLIB_CFLAGS) $(LIBICAL_CFLAGS) - -OBJECTS = vzic.o vzic-parse.o vzic-dump.o vzic-output.o - -all: vzic - -vzic: $(OBJECTS) - $(CC) $(OBJECTS) $(GLIB_LDADD) -o vzic - -test-vzic: test-vzic.o - $(CC) test-vzic.o $(LIBICAL_LDADD) -o test-vzic - -# Dependencies. -$(OBJECTS): vzic.h -vzic.o vzic-parse.o: vzic-parse.h -vzic.o vzic-dump.o: vzic-dump.h -vzic.o vzic-output.o: vzic-output.h - -test-parse: vzic - ./vzic-dump.pl $(OLSON_DIR) - ./vzic --dump --pure - @echo - @echo "#" - @echo "# If either of these diff commands outputs anything there may be a problem." - @echo "#" - diff -ru zoneinfo/ZonesPerl zoneinfo/ZonesVzic - diff -ru zoneinfo/RulesPerl zoneinfo/RulesVzic - -test-changes: vzic test-vzic - ./test-vzic --dump-changes - ./vzic --dump-changes --pure - @echo - @echo "#" - @echo "# If this diff command outputs anything there may be a problem." - @echo "#" - diff -ru zoneinfo/ChangesVzic test-output - -clean: - -rm -rf vzic $(OBJECTS) *~ ChangesVzic RulesVzic ZonesVzic RulesPerl ZonesPerl test-vzic test-vzic.o - -.PHONY: clean perl-dump test-parse - - diff --git a/libkcal/libical/vzic-1.3/README b/libkcal/libical/vzic-1.3/README deleted file mode 100644 index 962ff2e67..000000000 --- a/libkcal/libical/vzic-1.3/README +++ /dev/null @@ -1,202 +0,0 @@ - - -VZIC README -=========== - -This is 'vzic', a program to convert the Olson timezone database files into -VTIMEZONE files compatible with the iCalendar specification (RFC2445). - -(The name is based on the 'zic' program which converts the Olson files into -time zone information files used by several Unix C libraries, including -glibc. See zic(8) and tzfile(5).) - - - -REQUIREMENTS -============ - -You need the Olson timezone database files, which can be found at: - - ftp://elsie.nci.nih.gov/pub/ - - (Old versions can be found at ftp://munnari.oz.au/pub/oldtz/) - - -Vzic also uses the GLib library (for hash tables, dynamic arrays, and date -calculations). You need version 2.0 or higher. You can get this from: - - http://www.gtk.org - - - -BUILDING -======== - -Edit the Makefile to set the OLSON_DIR, PRODUCT_ID and TZID_PREFIX variables. - -Then run 'make'. - - - -RUNNING -======= - -Run 'vzic'. - -The output is placed in the zoneinfo subdirectory by default, -but you can use the --output-dir options to set another toplevel output -directory. - -By default it outputs VTIMEZONEs that try to be compatible with Outlook -(2000, at least). Outlook can't handle certain iCalendar constructs in -VTIMEZONEs, such as RRULEs using BYMONTHDAY, so it has to adjust the RRULEs -slightly to get Outlook to parse them. Unfortunately this means they are -slightly wrong. If given the --pure option, vzic outputs the exact data, -without worrying about compatability. - -NOTE: We don't convert all the Olson files. We skip 'backward', 'etcetera', -'leapseconds', 'pacificnew', 'solar87', 'solar88' and 'solar89', 'factory' -and 'systemv', since these don't really provide any useful timezones. -See vzic.c. - - - -MERGING CHANGES INTO A MASTER SET OF VTIMEZONES -=============================================== - -The Olson timezone files are updated fairly often, so we need to build new -sets of VTIMEZONE files. Though we have to be careful to ensure that the TZID -of updated timezones is also updated, since it must remain unique. - -We use a version number on the end of the TZID prefix (see the TZIDPrefix -variable in vzic-output.c) to ensure this uniqueness. - -But we don't want to update the version numbers of VTIMEZONEs which have not -changed. So we use the vzic-merge.pl Perl script. This merges in the new set -of VTIMEZONEs with a 'master' set. It compares each new VTIMEZONE file with -the one in the master set (ignoring changes to the TZID). If the new -VTIMEZONE file is different, it copies it to the master set and sets the -version number to the old VTIMEZONE's version number + 1. - -To use vzic-merge.pl you must change the $MASTER_ZONEINFO_DIR and -$NEW_ZONEINFO_DIR variables at the top of the file to point to your 2 sets of -VTIMEZONEs. You then just run the script. (I recommend you keep a backup of -the old master VTIMEZONE files, and use diff to compare the new master set -with the old one, in case anything goes wrong.) - -You must merge in changes to the zones.tab file by hand. - -Note that some timezones are renamed or removed occasionally, so applications -should be able to cope with this. - - - -COMPATABILITY NOTES -=================== - -It seems that Microsoft Outlook is very picky about the iCalendar files it -will accept. (I've been testing with Outlook 2000. I hope the other versions -are no worse.) Here's a few problems we've had with the VTIMEZONEs: - - o Outlook doesn't like any years before 1600. We were using '1st Jan 0001' - in all VTIMEZONEs to specify the first UTC offset known for the timezone. - (The Olson data does not give a start date for this.) - - Now we just skip this first component for most timezones. The UTC offset - can still be found from the TZOFFSETFROM property of the first component. - - Though some timezones only specify one UTC offset that applies forever, - so in these cases we output '1st Jan 1970' (Indian/Cocos, - Pacific/Johnston). - - o Outlook doesn't like the BYMONTHDAY specifier in RRULEs. - - We have changed most of the VTIMEZONEs to use things like 'BYDAY=2SU' - rather than 'BYMONTHDAY=8,9,10,11,12,13,14;BYDAY=SU', though some of - them were impossible to convert correctly so they are not always correct. - - o Outlook doesn't like TZOFFSETFROM/TZOFFSETTO properties which include a - seconds component, e.g. 'TZOFFSETFROM:+110628'. - Quite a lot of the Olson timezones include seconds in their UTC offsets, - though no timezones currently have a UTC offset that uses the seconds - value. - - We've rounded all UTC offsets to the nearest minute. Since all timezone - offsets currently used have '00' as the seconds offset, this doesn't lose - us much. - - o Outlook doesn't like lines being split in certain places, even though - the iCalendar spec says they can be split anywhere. - - o Outlook can only handle one RDATE or a pair of RRULEs. So we had to remove - all historical data. - - -TESTING -======= - -Do a 'make test-vic', then run ./test-vic. - -The test-vzic program compares our libical code and VTIMEZONE data against -the Unix functions like mktime(). It steps over a period of time (1970-2037) -converting from UTC to a given timezone and back again every 15 minutes. -Any differences are output into the test-output directory. - -The output matches for all of the timezones, except in a few places where the -result can't be determined. So I think we can be fairly confident that the -VTIMEZONEs are correct. - -Note that you must use the same Olson data in libical that the OS is using -for mktime() etc. For example, I am using RedHat 9 which uses tzdata2002d, -so I converted this to VTIMEZONE files and installed it into the libical -timezone data directory before testing. (You need to use '--pure' when -creating the VTIMEZONE files as well.) - - -Testing the Parsing Code ------------------------- - -Run 'make test-parse'. - -This runs 'vzic --dump' and 'perl-dump' and compares the output. The diff -commands should not produce any output. - -'vzic --dump' dumps all the parsed data out in the original Olson format, -but without comments. The files are written into the ZonesVzic and RulesVzic -subdirectories of the zoneinfo directory. - -'make perl-dump' runs the vzic-dump.pl perl script which outputs the files -in the same format as 'vzic --dump' in the ZonesPerl and RulesPerl -subdirectories. The perl script doesn't actually parse the fields; it only -strips comments and massages the fields so we have the same output format. - -Currently they both produce exactly the same output so we know the parsing -code is OK. - - -Testing the VTIMEZONE Files ---------------------------- - -Run 'make test-changes'. - -This runs 'vzic --dump-changes' and 'test-vzic --dump-changes' and compares -the output. The diff command should not produce any output. - -Both commands output timezone changes for each zone up to a specific year -(2030) into files for each timezone. It outputs the timezone changes in a -list in this format: - - Timezone Name Date and Time of Change in UTC New Offset from UTC - - America/Dawson 26 Oct 1986 2:00:00 -0800 - -Unfortunately there are some differences here, but they all happen before -1970 so it doesn't matter too much. It looks like the libical code has -problems determining things like 'last Sunday of the month' before 1970. -This is because it uses mktime() etc. which can't really handle dates -before 1970. - - - -Damon Chaplin <damon@gnome.org>, 25 Oct 2003. - diff --git a/libkcal/libical/vzic-1.3/test-vzic.c b/libkcal/libical/vzic-1.3/test-vzic.c deleted file mode 100644 index c06f27384..000000000 --- a/libkcal/libical/vzic-1.3/test-vzic.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * test-vzic.c - test vzic + libical against mktime() and friends. - * - * Note that when we output VCALENDAR data compatible with Outlook the - * results aren't all correct. - * - * We have to modify some RRULEs which makes these timezones incorrect: - * - * Africa/Cairo - * America/Godthab - * America/Santiago - * Antarctica/Palmer - * Asia/Baghdad - * Asia/Damascus - * Asia/Jerusalem - * - * Also, we can only output one RDATE or a pair of RRULEs which may make some - * other timezones incorrect sometimes (e.g. if they change). - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <errno.h> - -#include <ical.h> -/*#include <evolution/ical.h>*/ - -#define CHANGES_MAX_YEAR 2030 - -/* These are the years between which we test against the Unix timezone - functions, inclusive. When using 'vzic --pure' you can test the full - range from 1970 to 2037 and it should match against mktime() etc. - (assuming you are using the same Olson timezone data for both). - - But when using VTIMEZONE's that are compatible with Outlook, it is only - worth testing times in the future. There will be lots of differences in - the past, since we can't include any historical changes in the files. */ -#if 1 -#define DUMP_START_YEAR 2003 -#define DUMP_END_YEAR 2037 -#else -#define DUMP_START_YEAR 1970 -#define DUMP_END_YEAR 2037 -#endif - -/* The maximum size of any complete pathname. */ -#define PATHNAME_BUFFER_SIZE 1024 - -#ifndef FALSE -#define FALSE (0) -#endif - -#ifndef TRUE -#define TRUE (!FALSE) -#endif - -int VzicDumpChanges = FALSE; - -/* We output beneath the current directory for now. */ -char *directory = "test-output"; - -static void usage (void); -static int parse_zone_name (char *name, - char **directory, - char **subdirectory, - char **filename); -static void ensure_directory_exists (char *directory); -static void dump_local_times (icaltimezone *zone, - FILE *fp); - - -int main(int argc, char* argv[]) -{ - icalarray *zones; - icaltimezone *zone; - char *zone_directory, *zone_subdirectory, *zone_filename, *location; - char output_directory[PATHNAME_BUFFER_SIZE]; - char filename[PATHNAME_BUFFER_SIZE]; - FILE *fp; - int i; - int skipping = TRUE; - - /* - * Command-Line Option Parsing. - */ - for (i = 1; i < argc; i++) { - /* --dump-changes: Dumps a list of times when each timezone changed, - and the new local time offset from UTC. */ - if (!strcmp (argv[i], "--dump-changes")) - VzicDumpChanges = TRUE; - - else - usage (); - } - - - zones = icaltimezone_get_builtin_timezones (); - - ensure_directory_exists (directory); - - for (i = 0; i < zones->num_elements; i++) { - zone = icalarray_element_at (zones, i); - - location = icaltimezone_get_location (zone); - -#if 0 - /* Use this to start at a certain zone. */ - if (skipping && strcmp (location, "America/Boise")) - continue; -#endif - - skipping = FALSE; - - /* Use this to only output data for certain timezones. */ -#if 0 - if (strcmp (location, "America/Cancun") - && strcmp (location, "Asia/Baku") - && strcmp (location, "Asia/Nicosia") - && strcmp (location, "Asia/Novosibirsk") - && strcmp (location, "Asia/Samarkand") - && strcmp (location, "Asia/Tashkent") - && strcmp (location, "Asia/Tbilisi") - && strcmp (location, "Asia/Yerevan") - && strcmp (location, "Australia/Broken_Hill") - && strcmp (location, "Europe/Simferopol") - && strcmp (location, "Europe/Tallinn") - && strcmp (location, "Europe/Zaporozhye") - ) - continue; -#endif - -#if 0 - printf ("%s\n", location); -#endif - - parse_zone_name (location, &zone_directory, &zone_subdirectory, - &zone_filename); - - sprintf (output_directory, "%s/%s", directory, zone_directory); - ensure_directory_exists (output_directory); - sprintf (filename, "%s/%s", output_directory, zone_filename); - - if (zone_subdirectory) { - sprintf (output_directory, "%s/%s/%s", directory, zone_directory, - zone_subdirectory); - ensure_directory_exists (output_directory); - sprintf (filename, "%s/%s", output_directory, zone_filename); - } - - fp = fopen (filename, "w"); - if (!fp) { - fprintf (stderr, "Couldn't create file: %s\n", filename); - exit (1); - } - - /* We can run 2 different tests - output all changes for each zone, or - test against mktime()/localtime(). Should have a command-line option - or something. */ - if (VzicDumpChanges) - icaltimezone_dump_changes (zone, CHANGES_MAX_YEAR, fp); - else - dump_local_times (zone, fp); - - if (ferror (fp)) { - fprintf (stderr, "Error writing file: %s\n", filename); - exit (1); - } - - fclose (fp); - } - - return 0; -} - - -static void -usage (void) -{ - fprintf (stderr, "Usage: test-vzic [--dump-changes]\n"); - - exit (1); -} - - -/* This checks that the Zone name only uses the characters in [-+_/a-zA-Z0-9], - and outputs a warning if it isn't. */ -static int -parse_zone_name (char *name, - char **directory, - char **subdirectory, - char **filename) -{ - static int invalid_zone_num = 1; - - char *p, ch, *first_slash_pos = NULL, *second_slash_pos = NULL; - int invalid = FALSE; - - for (p = name; (ch = *p) != 0; p++) { - if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') - && (ch < '0' || ch > '9') && ch != '/' && ch != '_' - && ch != '-' && ch != '+') { - fprintf (stderr, "Warning: Unusual Zone name: %s\n", name); - invalid = TRUE; - break; - } - - if (ch == '/') { - if (!first_slash_pos) { - first_slash_pos = p; - } else if (!second_slash_pos) { - second_slash_pos = p; - } else { - fprintf (stderr, "Warning: More than 2 '/' characters in Zone name: %s\n", name); - invalid = TRUE; - break; - } - } - } - - if (!first_slash_pos) { - fprintf (stderr, "No '/' character in Zone name: %s. Skipping.\n", name); - return FALSE; - } - - if (invalid) { - fprintf (stderr, "Invalid zone name: %s\n", name); - exit (0); - } else { - *first_slash_pos = '\0'; - *directory = icalmemory_strdup (name); - *first_slash_pos = '/'; - - if (second_slash_pos) { - *second_slash_pos = '\0'; - *subdirectory = icalmemory_strdup (first_slash_pos + 1); - *second_slash_pos = '/'; - - *filename = icalmemory_strdup (second_slash_pos + 1); - } else { - *subdirectory = NULL; - *filename = icalmemory_strdup (first_slash_pos + 1); - } - } -} - - -static void -ensure_directory_exists (char *directory) -{ - struct stat filestat; - - if (stat (directory, &filestat) != 0) { - /* If the directory doesn't exist, try to create it. */ - if (errno == ENOENT) { - if (mkdir (directory, 0777) != 0) { - fprintf (stderr, "Can't create directory: %s\n", directory); - exit (1); - } - } else { - fprintf (stderr, "Error calling stat() on directory: %s\n", directory); - exit (1); - } - } else if (!S_ISDIR (filestat.st_mode)) { - fprintf (stderr, "Can't create directory, already exists: %s\n", - directory); - exit (1); - } -} - - -static void -dump_local_times (icaltimezone *zone, FILE *fp) -{ - static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - icaltimezone *utc_timezone; - struct icaltimetype tt, tt_copy; - struct tm tm, local_tm; - time_t t; - char tzstring[256], *location; - int last_year_output = 0; - int total_error = 0, total_error2 = 0; - - utc_timezone = icaltimezone_get_utc_timezone (); - - /* This is our UTC time that we will use to iterate over the period. */ - tt.year = DUMP_START_YEAR; - tt.month = 1; - tt.day = 1; - tt.hour = 0; - tt.minute = 0; - tt.second = 0; - tt.is_utc = 0; - tt.is_date = 0; - tt.zone = ""; - - tm.tm_year = tt.year - 1900; - tm.tm_mon = tt.month - 1; - tm.tm_mday = tt.day; - tm.tm_hour = tt.hour; - tm.tm_min = tt.minute; - tm.tm_sec = tt.second; - tm.tm_isdst = -1; - - /* Convert it to a time_t by saying it is in UTC. */ - putenv ("TZ=UTC"); - t = mktime (&tm); - - location = icaltimezone_get_location (zone); - sprintf (tzstring, "TZ=%s", location); - - /*printf ("Zone: %s\n", location);*/ - putenv (tzstring); - - /* Loop around converting the UTC time to local time, outputting it, and - then adding on 15 minutes to the UTC time. */ - while (tt.year <= DUMP_END_YEAR) { - if (tt.year > last_year_output) { - last_year_output = tt.year; -#if 0 - printf (" %i\n", last_year_output); - fprintf (fp, " %i\n", last_year_output); -#endif - } - -#if 1 - /* First use the Unix functions. */ - /* Now convert it to a local time in the given timezone. */ - local_tm = *localtime (&t); -#endif - -#if 1 - /* Now use libical. */ - tt_copy = tt; - icaltimezone_convert_time (&tt_copy, utc_timezone, zone); -#endif - -#if 1 - if (local_tm.tm_year + 1900 != tt_copy.year - || local_tm.tm_mon + 1 != tt_copy.month - || local_tm.tm_mday != tt_copy.day - || local_tm.tm_hour != tt_copy.hour - || local_tm.tm_min != tt_copy.minute - || local_tm.tm_sec != tt_copy.second) { - - /* The error format is: - - ERROR: Original-UTC-Time Local-Time-From-mktime Local-Time-From-Libical - - */ - - total_error++; - - fprintf (fp, "ERROR:%2i %s %04i %2i:%02i:%02i UTC", - tt.day, months[tt.month - 1], tt.year, - tt.hour, tt.minute, tt.second); - fprintf (fp, " ->%2i %s %04i %2i:%02i:%02i", - local_tm.tm_mday, months[local_tm.tm_mon], - local_tm.tm_year + 1900, - local_tm.tm_hour, local_tm.tm_min, local_tm.tm_sec); - fprintf (fp, " Us:%2i %s %04i %2i:%02i:%02i\n", - tt_copy.day, months[tt_copy.month - 1], tt_copy.year, - tt_copy.hour, tt_copy.minute, tt_copy.second); - } -#endif - - /* Now convert it back, and check we get the original time. */ - icaltimezone_convert_time (&tt_copy, zone, utc_timezone); - if (tt.year != tt_copy.year - || tt.month != tt_copy.month - || tt.day != tt_copy.day - || tt.hour != tt_copy.hour - || tt.minute != tt_copy.minute - || tt.second != tt_copy.second) { - - total_error2++; - - fprintf (fp, "ERROR 2: %2i %s %04i %2i:%02i:%02i UTC", - tt.day, months[tt.month - 1], tt.year, - tt.hour, tt.minute, tt.second); - fprintf (fp, " Us:%2i %s %04i %2i:%02i:%02i UTC\n", - tt_copy.day, months[tt_copy.month - 1], tt_copy.year, - tt_copy.hour, tt_copy.minute, tt_copy.second); - } - - - /* Increment the time. */ - icaltime_adjust (&tt, 0, 0, 15, 0); - - /* We assume leap seconds are not included in time_t values, which should - be true on POSIX systems. */ - t += 15 * 60; - } - - printf ("Zone: %40s Errors: %i (%i)\n", icaltimezone_get_location (zone), - total_error, total_error2); -} diff --git a/libkcal/libical/vzic-1.3/vzic-dump.c b/libkcal/libical/vzic-1.3/vzic-dump.c deleted file mode 100644 index 8e76aa80c..000000000 --- a/libkcal/libical/vzic-1.3/vzic-dump.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * These functions are for dumping all the parsed Zones and Rules to - * files, to be compared with the output of vzic-dump.pl to check our parsing - * code is OK. Some of the functions are also used for producing debugging - * output. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "vzic.h" -#include "vzic-dump.h" - - -static void dump_add_rule (char *name, - GArray *rule_array, - GPtrArray *name_array); -static int dump_compare_strings (const void *arg1, - const void *arg2); - - -void -dump_zone_data (GArray *zone_data, - char *filename) -{ - static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - FILE *fp; - ZoneData *zone; - ZoneLineData *zone_line; - int i, j; - gboolean output_month, output_day, output_time; - - fp = fopen (filename, "w"); - if (!fp) { - fprintf (stderr, "Couldn't create file: %s\n", filename); - exit (1); - } - - for (i = 0; i < zone_data->len; i++) { - zone = &g_array_index (zone_data, ZoneData, i); - - fprintf (fp, "Zone\t%s\t", zone->zone_name); - - for (j = 0; j < zone->zone_line_data->len; j++) { - zone_line = &g_array_index (zone->zone_line_data, ZoneLineData, j); - - if (j != 0) - fprintf (fp, "\t\t\t"); - - fprintf (fp, "%s\t", dump_time (zone_line->stdoff_seconds, TIME_WALL, - FALSE)); - - if (zone_line->rules) - fprintf (fp, "%s\t", zone_line->rules); - else if (zone_line->save_seconds != 0) - fprintf (fp, "%s\t", dump_time (zone_line->save_seconds, TIME_WALL, - FALSE)); - else - fprintf (fp, "-\t"); - - fprintf (fp, "%s\t", zone_line->format ? zone_line->format : "-"); - - if (zone_line->until_set) { - fprintf (fp, "%s\t", dump_year (zone_line->until_year)); - - output_month = output_day = output_time = FALSE; - - if (zone_line->until_time_code != TIME_WALL - || zone_line->until_time_seconds != 0) - output_month = output_day = output_time = TRUE; - else if (zone_line->until_day_code != DAY_SIMPLE - || zone_line->until_day_number != 1) - output_month = output_day = TRUE; - else if (zone_line->until_month != 0) - output_month = TRUE; - - if (output_month) - fprintf (fp, "%s", months[zone_line->until_month]); - - fprintf (fp, "\t"); - - if (output_day) - fprintf (fp, "%s", dump_day_coded (zone_line->until_day_code, - zone_line->until_day_number, - zone_line->until_day_weekday)); - - fprintf (fp, "\t"); - - if (output_time) - fprintf (fp, "%s", dump_time (zone_line->until_time_seconds, - zone_line->until_time_code, FALSE)); - - } else { - fprintf (fp, "\t\t\t"); - } - - fprintf (fp, "\n"); - } - } - - fclose (fp); -} - - -void -dump_rule_data (GHashTable *rule_data, - char *filename) -{ - FILE *fp; - GPtrArray *name_array; - GArray *rule_array; - int i; - char *name; - - fp = fopen (filename, "w"); - if (!fp) { - fprintf (stderr, "Couldn't create file: %s\n", filename); - exit (1); - } - - /* We need to sort the rules by their names, so they are in the same order - as the Perl output. So we place all the names in a temporary GPtrArray, - sort it, then output them. */ - name_array = g_ptr_array_new (); - g_hash_table_foreach (rule_data, (GHFunc) dump_add_rule, name_array); - qsort (name_array->pdata, name_array->len, sizeof (char*), - dump_compare_strings); - - for (i = 0; i < name_array->len; i++) { - name = g_ptr_array_index (name_array, i); - rule_array = g_hash_table_lookup (rule_data, name); - if (!rule_array) { - fprintf (stderr, "Couldn't access rules: %s\n", name); - exit (1); - } - dump_rule_array (name, rule_array, fp); - } - - g_ptr_array_free (name_array, TRUE); - - fclose (fp); -} - - -static void -dump_add_rule (char *name, - GArray *rule_array, - GPtrArray *name_array) -{ - g_ptr_array_add (name_array, name); -} - - -static int -dump_compare_strings (const void *arg1, - const void *arg2) -{ - char **a, **b; - - a = (char**) arg1; - b = (char**) arg2; - - return strcmp (*a, *b); -} - - -void -dump_rule_array (char *name, - GArray *rule_array, - FILE *fp) -{ - static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - RuleData *rule; - int i; - -#if 0 - fprintf (fp, "\n# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S"); -#endif - - for (i = 0; i < rule_array->len; i++) { - rule = &g_array_index (rule_array, RuleData, i); - - fprintf (fp, "Rule\t%s\t%s\t", name, dump_year (rule->from_year)); - - if (rule->to_year == rule->from_year) - fprintf (fp, "only\t"); - else - fprintf (fp, "%s\t", dump_year (rule->to_year)); - - fprintf (fp, "%s\t", rule->type ? rule->type : "-"); - - fprintf (fp, "%s\t", months[rule->in_month]); - - fprintf (fp, "%s\t", - dump_day_coded (rule->on_day_code, rule->on_day_number, - rule->on_day_weekday)); - - fprintf (fp, "%s\t", dump_time (rule->at_time_seconds, rule->at_time_code, - FALSE)); - - fprintf (fp, "%s\t", dump_time (rule->save_seconds, TIME_WALL, TRUE)); - - fprintf (fp, "%s", rule->letter_s ? rule->letter_s : "-"); - - fprintf (fp, "\n"); - } -} - - -char* -dump_time (int seconds, - TimeCode time_code, - gboolean use_zero) -{ - static char buffer[256], *sign; - int hours, minutes; - char *code; - - if (time_code == TIME_STANDARD) - code = "s"; - else if (time_code == TIME_UNIVERSAL) - code = "u"; - else - code = ""; - - if (seconds < 0) { - seconds = -seconds; - sign = "-"; - } else { - sign = ""; - } - - hours = seconds / 3600; - minutes = (seconds % 3600) / 60; - seconds = seconds % 60; - - if (use_zero && hours == 0 && minutes == 0 && seconds == 0) - return "0"; - else if (seconds == 0) - sprintf (buffer, "%s%i:%02i%s", sign, hours, minutes, code); - else - sprintf (buffer, "%s%i:%02i:%02i%s", sign, hours, minutes, seconds, code); - - return buffer; -} - - -char* -dump_day_coded (DayCode day_code, - int day_number, - int day_weekday) -{ - static char buffer[256]; - static char *weekdays[] = { "Sun", "Mon", "Tue", "Wed", - "Thu", "Fri", "Sat" }; - - switch (day_code) { - case DAY_SIMPLE: - sprintf (buffer, "%i", day_number); - break; - case DAY_WEEKDAY_ON_OR_AFTER: - sprintf (buffer, "%s>=%i", weekdays[day_weekday], day_number); - break; - case DAY_WEEKDAY_ON_OR_BEFORE: - sprintf (buffer, "%s<=%i", weekdays[day_weekday], day_number); - break; - case DAY_LAST_WEEKDAY: - sprintf (buffer, "last%s", weekdays[day_weekday]); - break; - default: - fprintf (stderr, "Invalid day code: %i\n", day_code); - exit (1); - } - - return buffer; -} - - -char* -dump_year (int year) -{ - static char buffer[256]; - - if (year == YEAR_MINIMUM) - return "min"; - if (year == YEAR_MAXIMUM) - return "max"; - - sprintf (buffer, "%i", year); - return buffer; -} - - -void -dump_time_zone_names (GList *names, - char *output_dir, - GHashTable *zones_hash) -{ - char filename[PATHNAME_BUFFER_SIZE], *zone_name, *zone_name_in_hash = NULL; - char strings_filename[PATHNAME_BUFFER_SIZE]; - FILE *fp, *strings_fp = NULL; - GList *elem; - ZoneDescription *zone_desc; - - sprintf (filename, "%s/zones.tab", output_dir); - sprintf (strings_filename, "%s/zones.h", output_dir); - - fp = fopen (filename, "w"); - if (!fp) { - fprintf (stderr, "Couldn't create file: %s\n", filename); - exit (1); - } - - if (VzicDumpZoneTranslatableStrings) { - strings_fp = fopen (strings_filename, "w"); - if (!strings_fp) { - fprintf (stderr, "Couldn't create file: %s\n", strings_filename); - exit (1); - } - } - - names = g_list_sort (names, (GCompareFunc) strcmp); - - elem = names; - while (elem) { - zone_name = (char*) elem->data; - - zone_desc = g_hash_table_lookup (zones_hash, zone_name); - - /* SPECIAL CASES: These timezones are links from other zones and are - almost exactly the same - they are basically there so users can find - them a bit easier. But they don't have entries in the zone.tab file, - so we use the entry from the timezone linked from. */ - if (!zone_desc) { - if (!strcmp (zone_name, "America/Indiana/Indianapolis")) - zone_name_in_hash = "America/Indianapolis"; - else if (!strcmp (zone_name, "America/Kentucky/Louisville")) - zone_name_in_hash = "America/Louisville"; - else if (!strcmp (zone_name, "Asia/Istanbul")) - zone_name_in_hash = "Europe/Istanbul"; - else if (!strcmp (zone_name, "Europe/Nicosia")) - zone_name_in_hash = "Asia/Nicosia"; - - if (zone_name_in_hash) - zone_desc = g_hash_table_lookup (zones_hash, zone_name_in_hash); - } - - if (zone_desc) { - fprintf (fp, "%+04i%02i%02i %+04i%02i%02i %s\n", - zone_desc->latitude[0], zone_desc->latitude[1], - zone_desc->latitude[2], - zone_desc->longitude[0], zone_desc->longitude[1], - zone_desc->longitude[2], - zone_name); - } else { - g_print ("Zone description not found for: %s\n", zone_name); - fprintf (fp, "%s\n", zone_name); - } - - - if (VzicDumpZoneTranslatableStrings) { -#if 0 - char zone_name_buffer[1024], *src, *dest; - - for (src = zone_name, dest = zone_name_buffer; *src; src++, dest++) - *dest = (*src == '_') ? ' ' : *src; - *dest = '\0'; -#endif - - fprintf (strings_fp, "N_(\"%s\");\n", zone_name); - } - - elem = elem->next; - } - - fclose (fp); - - if (VzicDumpZoneTranslatableStrings) - fclose (strings_fp); -} - diff --git a/libkcal/libical/vzic-1.3/vzic-dump.h b/libkcal/libical/vzic-1.3/vzic-dump.h deleted file mode 100644 index b37741a1e..000000000 --- a/libkcal/libical/vzic-1.3/vzic-dump.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * These functions are for dumping all the parsed Zones and Rules to - * files, to be compared with the output of vzic-dump.pl to check our parsing - * code is OK. Some of the functions are also used for producing debugging - * output. - */ - -#ifndef _VZIC_DUMP_H_ -#define _VZIC_DUMP_H_ - -#include <glib.h> - -void dump_zone_data (GArray *zone_data, - char *filename); -void dump_rule_data (GHashTable *rule_data, - char *filename); - -void dump_rule_array (char *name, - GArray *rule_array, - FILE *fp); - -char* dump_year (int year); -char* dump_day_coded (DayCode day_code, - int day_number, - int day_weekday); -char* dump_time (int seconds, - TimeCode time_code, - gboolean use_zero); - -void dump_time_zone_names (GList *names, - char *output_dir, - GHashTable *zones_hash); - -#endif /* _VZIC_DUMP_H_ */ diff --git a/libkcal/libical/vzic-1.3/vzic-dump.pl b/libkcal/libical/vzic-1.3/vzic-dump.pl deleted file mode 100755 index e73185cae..000000000 --- a/libkcal/libical/vzic-1.3/vzic-dump.pl +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/perl -w - -# -# Vzic - a program to convert Olson timezone database files into VZTIMEZONE -# files compatible with the iCalendar specification (RFC2445). -# -# Copyright (C) 2000-2001 Ximian, Inc. -# Copyright (C) 2003 Damon Chaplin. -# -# Author: Damon Chaplin <damon@gnome.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -# -# This reads the Olson timezone files, strips any comments, and outputs them -# in a very simple format with tab-separated fields. It is used to compare -# with the output of dump_zone_data() and dump_rule_data() to double-check -# that we have parsed the files correctly. -# - -my $zones_fh = "zonesfile"; -my $rules_fh = "rulesfile"; - -my %Rules; - -if ($#ARGV != 0) { - die "Usage: $0 <OlsonDirectory>"; -} - -my $OLSON_DIR = $ARGV[0]; - -# We place output in subdirectories of the current directory. -my $OUTPUT_DIR = "zoneinfo"; - -if (! -d "$OUTPUT_DIR") { - mkdir ("$OUTPUT_DIR", 0777) - || die "Can't create directory: $OUTPUT_DIR"; -} -if (! -d "$OUTPUT_DIR/ZonesPerl") { - mkdir ("$OUTPUT_DIR/ZonesPerl", 0777) - || die "Can't create directory: $OUTPUT_DIR/ZonesPerl"; -} -if (! -d "$OUTPUT_DIR/RulesPerl") { - mkdir ("$OUTPUT_DIR/RulesPerl", 0777) - || die "Can't create directory: $OUTPUT_DIR/RulesPerl"; -} - - -&ReadOlsonFile ("africa"); -&ReadOlsonFile ("antarctica"); -&ReadOlsonFile ("asia"); -&ReadOlsonFile ("australasia"); -&ReadOlsonFile ("europe"); -&ReadOlsonFile ("northamerica"); -&ReadOlsonFile ("southamerica"); - -# These are backwards-compatability and weird stuff. -#&ReadOlsonFile ("backward"); -#&ReadOlsonFile ("etcetera"); -#&ReadOlsonFile ("leapseconds"); -#&ReadOlsonFile ("pacificnew"); -#&ReadOlsonFile ("solar87"); -#&ReadOlsonFile ("solar88"); -#&ReadOlsonFile ("solar89"); - -# We don't do this one since it is not useful and the use of '"' in the Zone -# line messes up our split() command. -#&ReadOlsonFile ("factory"); - -# We don't do this since the vzic program can't do it. -#&ReadOlsonFile ("systemv"); - - - - -1; - - -sub ReadOlsonFile { - my ($file) = @_; - -# print ("Reading olson file: $file\n"); - - open (OLSONFILE, "$OLSON_DIR/$file") - || die "Can't open file: $file"; - - open ($zones_fh, ">$OUTPUT_DIR/ZonesPerl/$file") - || die "Can't open file: $OUTPUT_DIR/ZonesPerl/$file"; - - open ($rules_fh, ">$OUTPUT_DIR/RulesPerl/$file") - || die "Can't open file: $OUTPUT_DIR/RulesPerl/$file"; - - %Rules = (); - - my $zone_continues = 0; - - while (<OLSONFILE>) { - next if (m/^#/); - - # '#' characters can appear in strings, but the Olson files don't use - # that feature at present so we treat all '#' as comments for now. - s/#.*//; - - next if (m/^\s*$/); - - if ($zone_continues) { - $zone_continues = &ReadZoneContinuationLine; - - } elsif (m/^Rule\s/) { - &ReadRuleLine; - - } elsif (m/^Zone\s/) { - $zone_continues = &ReadZoneLine; - - } elsif (m/^Link\s/) { -# print "Link: $link_from, $link_to\n"; - - } elsif (m/^Leap\s/) { -# print "Leap\n"; - - } else { - die "Invalid line: $_"; - } - } - -# print ("Read olson file: $file\n"); - - foreach $key (sort (keys (%Rules))) { - print $rules_fh "$Rules{$key}" - } - - close ($zones_fh); - close ($rules_fh); - close (OLSONFILE); -} - - -sub ReadZoneLine { - my ($zone, $name, $gmtoff, $rules_save, $format, - $until_year, $until_month, $until_day, $until_time, $remainder) - = split ' ', $_, 10; - - return &ReadZoneLineCommon ($zone, $name, $gmtoff, $rules_save, $format, - $until_year, $until_month, $until_day, - $until_time); -} - - -sub ReadZoneContinuationLine { - my ($gmtoff, $rules_save, $format, - $until_year, $until_month, $until_day, $until_time, $remainder) - = split ' ', $_, 8; - - return &ReadZoneLineCommon ("", "", $gmtoff, $rules_save, $format, - $until_year, $until_month, $until_day, - $until_time); -} - - -sub ReadZoneLineCommon { - my ($zone, $name, $gmtoff, $rules_save, $format, - $until_year, $until_month, $until_day, $until_time) = @_; - - if (!defined ($until_year)) { $until_year = ""; } - if (!defined ($until_month)) { $until_month = ""; } - if (!defined ($until_day)) { $until_day = ""; } - if (!defined ($until_time)) { $until_time = ""; } - - # A few of the gmtoffsets have an unnecessary :00 seconds. - $gmtoff =~ s/(\d+):(\d+):00/$1:$2/; - - # Make sure the gmtoff does have minutes. - $gmtoff =~ s/^(-?\d+)$/$1:00/; - - # Fix a few other bits so they all use the same format. - if ($gmtoff eq "0") { $gmtoff = "0:00"; } - $until_time =~ s/^0(\d):/$1:/; - if ($until_time eq "0:00") { $until_time = ""; } - if ($until_day eq "1" && $until_time eq "") { $until_day = ""; } - if ($until_month eq "Jan" && $until_day eq "" && $until_time eq "") { - $until_month = ""; - } - - # For Zone continuation lines we need to insert an extra TAB. - if (!$zone) { $zone = "\t" }; - - print $zones_fh "$zone\t$name\t$gmtoff\t$rules_save\t$format\t$until_year\t$until_month\t$until_day\t$until_time\n"; - - if (defined ($until_year) && $until_year) { - return 1; - } else { - return 0; - } -} - - -sub ReadRuleLine { - my ($rule, $name, $from, $to, $type, $in, $on, $at, $save, $letter_s, - $remainder) = split; - - $at =~ s/(\d+:\d+):00/$1/; - $save =~ s/(\d+:\d+):00/$1/; - if ($save eq "0:00") { $save = "0"; } - - $Rules{$name} .= "$rule\t$name\t$from\t$to\t$type\t$in\t$on\t$at\t$save\t$letter_s\n"; - -# print $rules_fh "$rule\t$name\t$from\t$to\t$type\t$in\t$on\t$at\t$save\t$letter_s\n"; -} - diff --git a/libkcal/libical/vzic-1.3/vzic-merge.pl b/libkcal/libical/vzic-1.3/vzic-merge.pl deleted file mode 100755 index 020f57089..000000000 --- a/libkcal/libical/vzic-1.3/vzic-merge.pl +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/perl -w - -# -# Vzic - a program to convert Olson timezone database files into VZTIMEZONE -# files compatible with the iCalendar specification (RFC2445). -# -# Copyright (C) 2001 Ximian, Inc. -# Copyright (C) 2003 Damon Chaplin. -# -# Author: Damon Chaplin <damon@gnome.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -# -# This merges in a new set of VTIMEZONE files with the 'master' set. It only -# updates the files in the master set if the VTIMEZONE component has really -# been changes. Note that the TZID normally includes the date the VTIMEZONE -# file was generated on, so we have to ignore this when comparing the files. -# - -# Set these to the toplevel directories of the 2 sets of VTIMEZONE files. -#$MASTER_ZONEINFO_DIR = "/home/damon/cvs/libical/zoneinfo"; -$MASTER_ZONEINFO_DIR = "/usr/share/libical-evolution/zoneinfo"; -$NEW_ZONEINFO_DIR = "/home/damon/src/vzic-1.0/zoneinfo"; - -# Set this to 1 if you have version numbers in the TZID like libical. -$LIBICAL_VERSIONING = 1; - -# Set this to 0 for dry-runs, and 1 to actually update. -$DO_UPDATES = 1; - -# Save this so we can restore it later. -$input_record_separator = $/; - -chdir $NEW_ZONEINFO_DIR - || die "Can't cd to $NEW_ZONEINFO_DIR"; - -foreach $new_file (`find -name "*.ics"`) { - # Get rid of './' at start and whitespace at end. - $new_file =~ s/^\.\///; - $new_file =~ s/\s+$//; - -# print "File: $new_file\n"; - - open (NEWZONEFILE, "$new_file") - || die "Can't open file: $NEW_ZONEINFO_DIR/$new_file"; - undef $/; - $new_contents = <NEWZONEFILE>; - $/ = $input_record_separator; - close (NEWZONEFILE); - - $master_file = $MASTER_ZONEINFO_DIR . "/$new_file"; - -# print "Master File: $master_file\n"; - - $copy_to_master = 0; - - # If the ics file exists in the master copy we have to compare them, - # otherwise we can just copy the new file into the master directory. - if (-e $master_file) { - open (MASTERZONEFILE, "$master_file") - || die "Can't open file: $master_file"; - undef $/; - $master_contents = <MASTERZONEFILE>; - $/ = $input_record_separator; - close (MASTERZONEFILE); - - $new_contents_copy = $new_contents; - - # Strip the TZID from both contents. - $new_contents_copy =~ s/^TZID:\S+$//m; - $new_tzid = $&; - $master_contents =~ s/^TZID:\S+$//m; - $master_tzid = $&; - -# print "Matched: $master_tzid\n"; - - - if ($new_contents_copy ne $master_contents) { - print "$new_file has changed. Updating...\n"; - $copy_to_master = 1; - - if ($LIBICAL_VERSIONING) { - # We bump the version number in the new file. - $master_tzid =~ m%_(\d+)/%; - $version_num = $1; -# print "Version: $version_num\n"; - - $version_num++; - $new_tzid =~ s%_(\d+)/%_$version_num/%; - -# print "New TZID: $new_tzid\n"; - $new_contents =~ s/^TZID:\S+$/$new_tzid/m; - } - } - - } else { - print "$new_file doesn't exist in master directory. Copying...\n"; - $copy_to_master = 1; - } - - if ($copy_to_master) { -# print "Updating: $new_file\n"; - - if ($DO_UPDATES) { - open (MASTERZONEFILE, ">$master_file") - || die "Can't create file: $master_file"; - print MASTERZONEFILE $new_contents; - close (MASTERZONEFILE); - } - } - -} - diff --git a/libkcal/libical/vzic-1.3/vzic-output.c b/libkcal/libical/vzic-1.3/vzic-output.c deleted file mode 100644 index 87dd7529c..000000000 --- a/libkcal/libical/vzic-1.3/vzic-output.c +++ /dev/null @@ -1,2325 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* ALGORITHM: - * - * First we expand all the Rule arrays, so that each element only represents 1 - * year. If a Rule extends to infinity we expand it up to a few years past the - * maximum UNTIL year used in any of the timezones. We do this to make sure - * that the last of the expanded Rules (which may be infinite) is only used - * in the last of the time periods (i.e. the last Zone line). - * - * The Rule arrays are also sorted by the start time (FROM + IN + ON + AT). - * Doing all this makes it much easier to find which rules apply to which - * periods. - * - * For each timezone (i.e. ZoneData element), we step through each of the - * time periods, the ZoneLineData elements (which represent each Zone line - * from the Olson file.) - * - * We calculate the start & end time of the period. - * - For the first line the start time is -infinity. - * - For the last line the end time is +infinity. - * - The end time of each line is also the start time of the next. - * - * We create an array of time changes which occur in this period, including - * the one implied by the Zone line itself (though this is later taken out - * if it is found to be at exactly the same time as the first Rule). - * - * Now we iterate over the time changes, outputting them as STANDARD or - * DAYLIGHT components. We also try to merge them together into RRULEs or - * use RDATEs. - */ - - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "vzic.h" -#include "vzic-output.h" - -#include "vzic-dump.h" - - -/* These come from the Makefile. See the comments there. */ -char *ProductID = PRODUCT_ID; -char *TZIDPrefix = TZID_PREFIX; - -/* We expand the TZIDPrefix, replacing %D with the date, in here. */ -char TZIDPrefixExpanded[1024]; - - -/* We only use RRULEs if there are at least MIN_RRULE_OCCURRENCES occurrences, - since otherwise RDATEs are more efficient. Actually, I've set this high - so we only use RRULEs for infinite recurrences. Since expanding RRULEs is - very time-consuming, this seems sensible. */ -#define MIN_RRULE_OCCURRENCES 100 - - -/* The year we go up to when dumping the list of timezone changes (used - for testing & debugging). */ -#define MAX_CHANGES_YEAR 2030 - -/* This is the maximum year that time_t value can typically hold on 32-bit - systems. */ -#define MAX_TIME_T_YEAR 2037 - - -/* The year we use to start RRULEs. */ -#define RRULE_START_YEAR 1970 - -/* The year we use for RDATEs. */ -#define RDATE_YEAR 1970 - - -static char *WeekDays[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA" }; -static int DaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -char *CurrentZoneName; - - -typedef struct _VzicTime VzicTime; -struct _VzicTime -{ - /* Normal years, e.g. 2001. */ - int year; - - /* 0 (Jan) to 11 (Dec). */ - int month; - - /* The day, either a simple month day number, 1-31, or a rule such as - the last Sunday, or the first Monday on or after the 8th. */ - DayCode day_code; - int day_number; /* 1 to 31. */ - int day_weekday; /* 0 (Sun) to 6 (Sat). */ - - /* The time, in seconds from midnight. The code specifies whether the - time is a wall clock time, local standard time, or universal time. */ - int time_seconds; - TimeCode time_code; - - /* The offset from UTC for local standard time. */ - int stdoff; - - /* The offset from UTC for local wall clock time. If this is different to - stdoff then this is a DAYLIGHT component. This is TZOFFSETTO. */ - int walloff; - - /* TRUE if the time change recurs every year to infinity. */ - gboolean is_infinite; - - /* TRUE if the change has already been output. */ - gboolean output; - - /* These are the offsets of the previous VzicTime, and are used when - calculating the time of the change. We place them here in - output_zone_components() to simplify the output code. */ - int prev_stdoff; - int prev_walloff; - - /* The abbreviated form of the timezone name. Note that this may not be - unique. */ - char *tzname; -}; - - -static void expand_and_sort_rule_array (gpointer key, - gpointer value, - gpointer data); -static int rule_sort_func (const void *arg1, - const void *arg2); -static void output_zone (char *directory, - ZoneData *zone, - char *zone_name, - GHashTable *rule_data); -static gboolean parse_zone_name (char *name, - char **directory, - char **subdirectory, - char **filename); -static void output_zone_to_files (ZoneData *zone, - char *zone_name, - GHashTable *rule_data, - FILE *fp, - FILE *changes_fp); -static gboolean add_rule_changes (ZoneLineData *zone_line, - char *zone_name, - GArray *changes, - GHashTable *rule_data, - VzicTime *start, - VzicTime *end, - char **start_letter_s, - int *save_seconds); -static char* expand_tzname (char *zone_name, - char *format, - gboolean have_letter_s, - char *letter_s, - gboolean is_daylight); -static int compare_times (VzicTime *time1, - int stdoff1, - int walloff1, - VzicTime *time2, - int stdoff2, - int walloff2); -static gboolean times_match (VzicTime *time1, - int stdoff1, - int walloff1, - VzicTime *time2, - int stdoff2, - int walloff2); -static void output_zone_components (FILE *fp, - char *name, - GArray *changes); -static void set_previous_offsets (GArray *changes); -static gboolean check_for_recurrence (FILE *fp, - GArray *changes, - int idx); -static void check_for_rdates (FILE *fp, - GArray *changes, - int idx); -static gboolean timezones_match (char *tzname1, - char *tzname2); -static int output_component_start (char *buffer, - VzicTime *vzictime, - gboolean output_rdate, - gboolean use_same_tz_offset); -static void output_component_end (FILE *fp, - VzicTime *vzictime); - -static void vzictime_init (VzicTime *vzictime); -static int calculate_actual_time (VzicTime *vzictime, - TimeCode time_code, - int stdoff, - int walloff); -static int calculate_wall_time (int time, - TimeCode time_code, - int stdoff, - int walloff, - int *day_offset); -static int calculate_until_time (int time, - TimeCode time_code, - int stdoff, - int walloff, - int *year, - int *month, - int *day); -static void fix_time_overflow (int *year, - int *month, - int *day, - int day_offset); - -static char* format_time (int year, - int month, - int day, - int time); -static char* format_tz_offset (int tz_offset, - gboolean round_seconds); -static gboolean output_rrule (char *rrule_buffer, - int month, - DayCode day_code, - int day_number, - int day_weekday, - int day_offset, - char *until); -static gboolean output_rrule_2 (char *buffer, - int month, - int day_number, - int day_weekday); - -static char* format_vzictime (VzicTime *vzictime); - -static void dump_changes (FILE *fp, - char *zone_name, - GArray *changes); -static void dump_change (FILE *fp, - char *zone_name, - VzicTime *vzictime, - int year); - -static void expand_tzid_prefix (void); - - -void -output_vtimezone_files (char *directory, - GArray *zone_data, - GHashTable *rule_data, - GHashTable *link_data, - int max_until_year) -{ - ZoneData *zone; - GList *links; - char *link_to; - int i; - - /* Insert today's date into the TZIDs we output. */ - expand_tzid_prefix (); - - /* Expand the rule data so that each entry specifies only one year, and - sort it so we can easily find the rules applicable to each Zone span. */ - g_hash_table_foreach (rule_data, expand_and_sort_rule_array, - GINT_TO_POINTER (max_until_year)); - - /* Output each timezone. */ - for (i = 0; i < zone_data->len; i++) { - zone = &g_array_index (zone_data, ZoneData, i); - output_zone (directory, zone, zone->zone_name, rule_data); - - /* Look for any links from this zone. */ - links = g_hash_table_lookup (link_data, zone->zone_name); - - while (links) { - link_to = links->data; - - /* We ignore Links that don't have a '/' in them (things like 'EST5EDT'). - */ - if (strchr (link_to, '/')) { - output_zone (directory, zone, link_to, rule_data); - } - - links = links->next; - } - } -} - - -static void -expand_and_sort_rule_array (gpointer key, - gpointer value, - gpointer data) -{ - char *name = key; - GArray *rule_array = value; - RuleData *rule, tmp_rule; - int len, max_year, i, from, to, year; - gboolean is_infinite; - - /* We expand the rule data to a year greater than any year used in a Zone - UNTIL value. This is so that we can easily get parts of the array to - use for each Zone line. */ - max_year = GPOINTER_TO_INT (data) + 2; - - /* If any of the rules apply to several years, we turn it into a single rule - for each year. If the Rule is infinite we go up to max_year. - We change the FROM field in the copies of the Rule, setting it to each - of the years, and set TO to FROM, except if TO was YEAR_MAXIMUM we set - the last TO to YEAR_MAXIMUM, so we still know the Rule is infinite. */ - len = rule_array->len; - for (i = 0; i < len; i++) { - rule = &g_array_index (rule_array, RuleData, i); - - /* None of the Rules currently use the TYPE field, but we'd better check. - */ - if (rule->type) { - fprintf (stderr, "Rules %s has a TYPE: %s\n", name, rule->type); - exit (1); - } - - if (rule->from_year != rule->to_year) { - from = rule->from_year; - to = rule->to_year; - - tmp_rule = *rule; - - /* Flag that this is a shallow copy so we don't free anything twice. */ - tmp_rule.is_shallow_copy = TRUE; - - /* See if it is an infinite Rule. */ - if (to == YEAR_MAXIMUM) { - is_infinite = TRUE; - to = max_year; - if (from < to) - rule->to_year = rule->from_year; - } else { - is_infinite = FALSE; - } - - /* Create a copy of the Rule for each year. */ - for (year = from + 1; year <= to; year++) { - tmp_rule.from_year = year; - - /* If the Rule is infinite, mark the last copy as infinite. */ - if (year == to && is_infinite) - tmp_rule.to_year = YEAR_MAXIMUM; - else - tmp_rule.to_year = year; - - g_array_append_val (rule_array, tmp_rule); - } - } - } - - /* Now sort the rules. */ - qsort (rule_array->data, rule_array->len, sizeof (RuleData), rule_sort_func); - -#if 0 - dump_rule_array (name, rule_array, stdout); -#endif -} - - -/* This is used to sort the rules, after the rules have all been expanded so - that each one is only for one year. */ -static int -rule_sort_func (const void *arg1, - const void *arg2) -{ - RuleData *rule1, *rule2; - int time1_year, time1_month, time1_day; - int time2_year, time2_month, time2_day; - int month_diff, result; - VzicTime t1, t2; - - rule1 = (RuleData*) arg1; - rule2 = (RuleData*) arg2; - - time1_year = rule1->from_year; - time1_month = rule1->in_month; - time2_year = rule2->from_year; - time2_month = rule2->in_month; - - /* If there is more that one month difference we don't need to calculate - the day or time. */ - month_diff = (time1_year - time2_year) * 12 + time1_month - time2_month; - - if (month_diff > 1) - return 1; - if (month_diff < -1) - return -1; - - /* Now we have to calculate the day and time of the Rule start and the - VzicTime, using the given offsets. */ - t1.year = time1_year; - t1.month = time1_month; - t1.day_code = rule1->on_day_code; - t1.day_number = rule1->on_day_number; - t1.day_weekday = rule1->on_day_weekday; - t1.time_code = rule1->at_time_code; - t1.time_seconds = rule1->at_time_seconds; - - t2.year = time2_year; - t2.month = time2_month; - t2.day_code = rule2->on_day_code; - t2.day_number = rule2->on_day_number; - t2.day_weekday = rule2->on_day_weekday; - t2.time_code = rule2->at_time_code; - t2.time_seconds = rule2->at_time_seconds; - - /* FIXME: We don't know the offsets yet, but I don't think any Rules are - close enough together that the offsets can make a difference. Should - check this. */ - calculate_actual_time (&t1, TIME_WALL, 0, 0); - calculate_actual_time (&t2, TIME_WALL, 0, 0); - - /* Now we can compare the entire time. */ - if (t1.year > t2.year) - result = 1; - else if (t1.year < t2.year) - result = -1; - - else if (t1.month > t2.month) - result = 1; - else if (t1.month < t2.month) - result = -1; - - else if (t1.day_number > t2.day_number) - result = 1; - else if (t1.day_number < t2.day_number) - result = -1; - - else if (t1.time_seconds > t2.time_seconds) - result = 1; - else if (t1.time_seconds < t2.time_seconds) - result = -1; - - else { - printf ("WARNING: Rule dates matched.\n"); - result = 0; - } - - return result; -} - - -static void -output_zone (char *directory, - ZoneData *zone, - char *zone_name, - GHashTable *rule_data) -{ - FILE *fp, *changes_fp = NULL; - char output_directory[PATHNAME_BUFFER_SIZE]; - char filename[PATHNAME_BUFFER_SIZE]; - char changes_filename[PATHNAME_BUFFER_SIZE]; - char *zone_directory, *zone_subdirectory, *zone_filename; - - /* Set a global for the zone_name, to be used only for debug messages. */ - CurrentZoneName = zone_name; - - /* Use this to only output a particular zone. */ -#if 0 - if (strcmp (zone_name, "Atlantic/Azores")) - return; -#endif - -#if 0 - printf ("Outputting Zone: %s\n", zone_name); -#endif - - if (!parse_zone_name (zone_name, &zone_directory, &zone_subdirectory, - &zone_filename)) - return; - - if (VzicDumpZoneNamesAndCoords) { - VzicTimeZoneNames = g_list_prepend (VzicTimeZoneNames, - g_strdup (zone_name)); - } - - sprintf (output_directory, "%s/%s", directory, zone_directory); - ensure_directory_exists (output_directory); - sprintf (filename, "%s/%s.ics", output_directory, zone_filename); - - if (VzicDumpChanges) { - sprintf (output_directory, "%s/ChangesVzic/%s", directory, zone_directory); - ensure_directory_exists (output_directory); - sprintf (changes_filename, "%s/%s", output_directory, zone_filename); - } - - if (zone_subdirectory) { - sprintf (output_directory, "%s/%s/%s", directory, zone_directory, - zone_subdirectory); - ensure_directory_exists (output_directory); - sprintf (filename, "%s/%s.ics", output_directory, zone_filename); - - if (VzicDumpChanges) { - sprintf (output_directory, "%s/ChangesVzic/%s/%s", directory, - zone_directory, zone_subdirectory); - ensure_directory_exists (output_directory); - sprintf (changes_filename, "%s/%s", output_directory, zone_filename); - } - } - - /* Create the files. */ - fp = fopen (filename, "w"); - if (!fp) { - fprintf (stderr, "Couldn't create file: %s\n", filename); - exit (1); - } - - if (VzicDumpChanges) { - changes_fp = fopen (changes_filename, "w"); - if (!changes_fp) { - fprintf (stderr, "Couldn't create file: %s\n", changes_filename); - exit (1); - } - } - - fprintf (fp, "BEGIN:VCALENDAR\nPRODID:%s\nVERSION:2.0\n", ProductID); - - output_zone_to_files (zone, zone_name, rule_data, fp, changes_fp); - - if (ferror (fp)) { - fprintf (stderr, "Error writing file: %s\n", filename); - exit (1); - } - - fprintf (fp, "END:VCALENDAR\n"); - - fclose (fp); - - g_free (zone_directory); - g_free (zone_subdirectory); - g_free (zone_filename); -} - - -/* This checks that the Zone name only uses the characters in [-+_/a-zA-Z0-9], - and outputs a warning if it isn't. */ -static gboolean -parse_zone_name (char *name, - char **directory, - char **subdirectory, - char **filename) -{ - static int invalid_zone_num = 1; - - char *p, ch, *first_slash_pos = NULL, *second_slash_pos = NULL; - gboolean invalid = FALSE; - - for (p = name; (ch = *p) != 0; p++) { - if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z') - && (ch < '0' || ch > '9') && ch != '/' && ch != '_' - && ch != '-' && ch != '+') { - fprintf (stderr, "WARNING: Unusual Zone name: %s\n", name); - invalid = TRUE; - break; - } - - if (ch == '/') { - if (!first_slash_pos) { - first_slash_pos = p; - } else if (!second_slash_pos) { - second_slash_pos = p; - } else { - fprintf (stderr, "WARNING: More than 2 '/' characters in Zone name: %s\n", name); - invalid = TRUE; - break; - } - } - } - - if (!first_slash_pos) { -#if 0 - fprintf (stderr, "No '/' character in Zone name: %s. Skipping.\n", name); -#endif - return FALSE; - } - - if (invalid) { - *directory = g_strdup ("Invalid"); - *filename = g_strdup_printf ("Zone%i", invalid_zone_num++); - } else { - *first_slash_pos = '\0'; - *directory = g_strdup (name); - *first_slash_pos = '/'; - - if (second_slash_pos) { - *second_slash_pos = '\0'; - *subdirectory = g_strdup (first_slash_pos + 1); - *second_slash_pos = '/'; - - *filename = g_strdup (second_slash_pos + 1); - } else { - *subdirectory = NULL; - *filename = g_strdup (first_slash_pos + 1); - } - } - - return invalid ? FALSE : TRUE; -} - - -static void -output_zone_to_files (ZoneData *zone, - char *zone_name, - GHashTable *rule_data, - FILE *fp, - FILE *changes_fp) -{ - ZoneLineData *zone_line; - GArray *changes; - int i, stdoff, walloff, start_index, save_seconds; - VzicTime start, end, *vzictime_start, *vzictime, *vzictime_first_rule_change; - gboolean is_daylight, found_letter_s; - char *start_letter_s; - - changes = g_array_new (FALSE, FALSE, sizeof (VzicTime)); - - vzictime_init (&start); - vzictime_init (&end); - - /* The first period starts at -infinity. */ - start.year = YEAR_MINIMUM; - - for (i = 0; i < zone->zone_line_data->len; i++) { - zone_line = &g_array_index (zone->zone_line_data, ZoneLineData, i); - - /* This is the local standard time offset from GMT for this period. */ - start.stdoff = stdoff = zone_line->stdoff_seconds; - start.walloff = walloff = stdoff + zone_line->save_seconds; - - if (zone_line->until_set) { - end.year = zone_line->until_year; - end.month = zone_line->until_month; - end.day_code = zone_line->until_day_code; - end.day_number = zone_line->until_day_number; - end.day_weekday = zone_line->until_day_weekday; - end.time_seconds = zone_line->until_time_seconds; - end.time_code = zone_line->until_time_code; - } else { - /* The last period ends at +infinity. */ - end.year = YEAR_MAXIMUM; - } - - /* Add a time change for the start of the period. This may be removed - later if one of the rules expands to exactly the same time. */ - start_index = changes->len; - g_array_append_val (changes, start); - - /* If there are Rules associated with this period, add all the relevant - time changes. */ - save_seconds = 0; - if (zone_line->rules) - found_letter_s = add_rule_changes (zone_line, zone_name, changes, - rule_data, &start, &end, - &start_letter_s, &save_seconds); - else - found_letter_s = FALSE; - - /* FIXME: I'm not really sure what to do about finding a LETTER_S for the - first part of the period (i.e. before the first Rule comes into effect). - Currently we try to use the same LETTER_S as the first Rule of the - period which is in local standard time. */ - if (zone_line->save_seconds) - save_seconds = zone_line->save_seconds; - is_daylight = save_seconds ? TRUE : FALSE; - vzictime_start = &g_array_index (changes, VzicTime, start_index); - walloff = vzictime_start->walloff = stdoff + save_seconds; - - /* TEST: See if the first Rule time is exactly the same as the change from - the Zone line. In which case we can remove the Zone line change. */ - if (changes->len > start_index + 1) { - int prev_stdoff, prev_walloff; - - if (start_index > 0) { - VzicTime *v = &g_array_index (changes, VzicTime, start_index - 1); - prev_stdoff = v->stdoff; - prev_walloff = v->walloff; - } else { - prev_stdoff = 0; - prev_walloff = 0; - } - vzictime_first_rule_change = &g_array_index (changes, VzicTime, - start_index + 1); - if (times_match (vzictime_start, prev_stdoff, prev_walloff, - vzictime_first_rule_change, stdoff, walloff)) { -#if 0 - printf ("Removing zone-line change (using new offsets)\n"); -#endif - g_array_remove_index (changes, start_index); - vzictime_start = NULL; - } else if (times_match (vzictime_start, prev_stdoff, prev_walloff, - vzictime_first_rule_change, prev_stdoff, prev_walloff)) { -#if 0 - printf ("Removing zone-line change (using previous offsets)\n"); -#endif - g_array_remove_index (changes, start_index); - vzictime_start = NULL; - } - } - - - if (vzictime_start) { - vzictime_start->tzname = expand_tzname (zone_name, zone_line->format, - found_letter_s, - start_letter_s, is_daylight); - } - - /* The start of the next Zone line is the end time of this one. */ - start = end; - } - - set_previous_offsets (changes); - - output_zone_components (fp, zone_name, changes); - - if (VzicDumpChanges) - dump_changes (changes_fp, zone_name, changes); - - /* Free all the TZNAME fields. */ - for (i = 0; i < changes->len; i++) { - vzictime = &g_array_index (changes, VzicTime, i); - g_free (vzictime->tzname); - } - - g_array_free (changes, TRUE); -} - - -/* This appends any timezone changes specified by the rules associated with - the timezone, that happen between the start and end times. - It returns the letter_s field of the first STANDARD rule found in the - search. We need this to fill in any %s in the FORMAT field of the first - component of the time period (the Zone line). */ -static gboolean -add_rule_changes (ZoneLineData *zone_line, - char *zone_name, - GArray *changes, - GHashTable *rule_data, - VzicTime *start, - VzicTime *end, - char **start_letter_s, - int *save_seconds) -{ - GArray *rule_array; - RuleData *rule, *prev_rule = NULL; - int stdoff, walloff, i, prev_stdoff, prev_walloff; - VzicTime vzictime; - gboolean is_daylight, found_start_letter_s = FALSE; - gboolean checked_for_previous = FALSE; - - *save_seconds = 0; - - rule_array = g_hash_table_lookup (rule_data, zone_line->rules); - if (!rule_array) { - fprintf (stderr, "Couldn't access rules: %s\n", zone_line->rules); - exit (1); - } - - /* The stdoff is the same for all the rules. */ - stdoff = start->stdoff; - - /* The walloff changes as we go through the rules. */ - walloff = start->walloff; - - /* Get the stdoff & walloff from the last change before this period. */ - if (changes->len >= 2) { - VzicTime *change = &g_array_index (changes, VzicTime, changes->len - 2); - prev_stdoff = change->stdoff; - prev_walloff = change->walloff; - } else { - prev_stdoff = prev_walloff = 0; - } - - - for (i = 0; i < rule_array->len; i++) { - rule = &g_array_index (rule_array, RuleData, i); - - is_daylight = rule->save_seconds != 0 ? TRUE : FALSE; - - vzictime_init (&vzictime); - vzictime.year = rule->from_year; - vzictime.month = rule->in_month; - vzictime.day_code = rule->on_day_code; - vzictime.day_number = rule->on_day_number; - vzictime.day_weekday = rule->on_day_weekday; - vzictime.time_seconds = rule->at_time_seconds; - vzictime.time_code = rule->at_time_code; - vzictime.stdoff = stdoff; - vzictime.walloff = stdoff + rule->save_seconds; - vzictime.is_infinite = (rule->to_year == YEAR_MAXIMUM) ? TRUE : FALSE; - - /* If the rule time is before the given start time, skip it. */ - if (compare_times (&vzictime, stdoff, walloff, - start, prev_stdoff, prev_walloff) < 0) - continue; - - /* If the previous Rule was a daylight Rule, then we may want to use the - walloff from that. */ - if (!checked_for_previous) { - checked_for_previous = TRUE; - if (i > 0) { - prev_rule = &g_array_index (rule_array, RuleData, i - 1); - if (prev_rule->save_seconds) { - walloff = start->walloff = stdoff + prev_rule->save_seconds; - *save_seconds = prev_rule->save_seconds; - found_start_letter_s = TRUE; - *start_letter_s = prev_rule->letter_s; -#if 0 - printf ("Could use save_seconds from previous Rule: %s\n", - zone_name); -#endif - } - } - } - - /* If an end time has been given, then if the rule time is on or after it - break out of the loop. */ - if (end->year != YEAR_MAXIMUM - && compare_times (&vzictime, stdoff, walloff, - end, stdoff, walloff) >= 0) - break; - - vzictime.tzname = expand_tzname (zone_name, zone_line->format, TRUE, - rule->letter_s, is_daylight); - - g_array_append_val (changes, vzictime); - - /* When we find the first STANDARD time we set letter_s. */ - if (!found_start_letter_s && !is_daylight) { - found_start_letter_s = TRUE; - *start_letter_s = rule->letter_s; - } - - /* Now that we have added the Rule, the new walloff comes into effect - for any following Rules. */ - walloff = vzictime.walloff; - } - - return found_start_letter_s; -} - - -/* This expands the Zone line FORMAT field, using the given LETTER_S from a - Rule line. There are 3 types of FORMAT field: - 1. a string with an %s in, e.g. "WE%sT". The %s is replaced with LETTER_S. - 2. a string with an '/' in, e.g. "CAT/CAWT". The first part is used for - standard time and the second part for when daylight-saving is in effect. - 3. a plain string, e.g. "LMT", which we leave as-is. - Note that (1) is the only type in which letter_s is required. -*/ -static char* -expand_tzname (char *zone_name, - char *format, - gboolean have_letter_s, - char *letter_s, - gboolean is_daylight) -{ - char *p, buffer[256], *guess = NULL; - int len; - -#if 0 - printf ("Expanding %s with %s\n", format, letter_s); -#endif - - if (!format || !format[0]) { - fprintf (stderr, "Missing FORMAT\n"); - exit (1); - } - - /* 1. Look for a "%s". */ - p = strchr (format, '%'); - if (p && *(p + 1) == 's') { - if (!have_letter_s) { - - /* NOTE: These are a few hard-coded TZNAMEs that I've looked up myself. - These are needed in a few places where a Zone line comes into effect - but no Rule has been found, so we have no LETTER_S to use. - I've tried to use whatever is the normal LETTER_S in the Rules for - the particular zone, in local standard time. */ - if (!strcmp (zone_name, "Asia/Macao") - && !strcmp (format, "C%sT")) - guess = "CST"; - else if (!strcmp (zone_name, "Asia/Macau") - && !strcmp (format, "C%sT")) - guess = "CST"; - else if (!strcmp (zone_name, "Asia/Ashgabat") - && !strcmp (format, "ASH%sT")) - guess = "ASHT"; - else if (!strcmp (zone_name, "Asia/Ashgabat") - && !strcmp (format, "TM%sT")) - guess = "TMT"; - else if (!strcmp (zone_name, "Asia/Samarkand") - && !strcmp (format, "TAS%sT")) - guess = "TAST"; - else if (!strcmp (zone_name, "Atlantic/Azores") - && !strcmp (format, "WE%sT")) - guess = "WET"; - else if (!strcmp (zone_name, "Europe/Paris") - && !strcmp (format, "WE%sT")) - guess = "WET"; - else if (!strcmp (zone_name, "Europe/Warsaw") - && !strcmp (format, "CE%sT")) - guess = "CET"; - else if (!strcmp (zone_name, "America/Phoenix") - && !strcmp (format, "M%sT")) - guess = "MST"; - else if (!strcmp (zone_name, "America/Nome") - && !strcmp (format, "Y%sT")) - guess = "YST"; - - if (guess) { -#if 0 - fprintf (stderr, - "WARNING: Couldn't find a LETTER_S to use in FORMAT: %s in Zone: %s Guessing: %s\n", - format, zone_name, guess); -#endif - return g_strdup (guess); - } - -#if 1 - fprintf (stderr, - "WARNING: Couldn't find a LETTER_S to use in FORMAT: %s in Zone: %s Leaving TZNAME empty\n", - format, zone_name); -#endif - -#if 0 - /* This is useful to spot exactly which component had a problem. */ - sprintf (buffer, "FIXME: %s", format); - return g_strdup (buffer); -#else - /* We give up and don't output a TZNAME. */ - return NULL; -#endif - } - - sprintf (buffer, format, letter_s ? letter_s : ""); - return g_strdup (buffer); - } - - /* 2. Look for a "/". */ - p = strchr (format, '/'); - if (p) { - if (is_daylight) { - return g_strdup (p + 1); - } else { - len = p - format; - strncpy (buffer, format, len); - buffer[len] = '\0'; - return g_strdup (buffer); - } - } - - /* 3. Just use format as it is. */ - return g_strdup (format); -} - - -/* Compares 2 VzicTimes, returning strcmp()-like values, i.e. 0 if equal, - 1 if the 1st is after the 2nd and -1 if the 1st is before the 2nd. */ -static int -compare_times (VzicTime *time1, - int stdoff1, - int walloff1, - VzicTime *time2, - int stdoff2, - int walloff2) -{ - VzicTime t1, t2; - int result; - - t1 = *time1; - t2 = *time2; - - calculate_actual_time (&t1, TIME_UNIVERSAL, stdoff1, walloff1); - calculate_actual_time (&t2, TIME_UNIVERSAL, stdoff2, walloff2); - - /* Now we can compare the entire time. */ - if (t1.year > t2.year) - result = 1; - else if (t1.year < t2.year) - result = -1; - - else if (t1.month > t2.month) - result = 1; - else if (t1.month < t2.month) - result = -1; - - else if (t1.day_number > t2.day_number) - result = 1; - else if (t1.day_number < t2.day_number) - result = -1; - - else if (t1.time_seconds > t2.time_seconds) - result = 1; - else if (t1.time_seconds < t2.time_seconds) - result = -1; - - else - result = 0; - -#if 0 - printf ("%i/%i/%i %i <=> %i/%i/%i %i -> %i\n", - t1.day_number, t1.month + 1, t1.year, t1.time_seconds, - t2.day_number, t2.month + 1, t2.year, t2.time_seconds, - result); -#endif - - return result; -} - - -/* Returns TRUE if the 2 times are exactly the same. It will calculate the - actual day, but doesn't convert times. */ -static gboolean -times_match (VzicTime *time1, - int stdoff1, - int walloff1, - VzicTime *time2, - int stdoff2, - int walloff2) -{ - VzicTime t1, t2; - - t1 = *time1; - t2 = *time2; - - calculate_actual_time (&t1, TIME_UNIVERSAL, stdoff1, walloff1); - calculate_actual_time (&t2, TIME_UNIVERSAL, stdoff2, walloff2); - - if (t1.year == t2.year - && t1.month == t2.month - && t1.day_number == t2.day_number - && t1.time_seconds == t2.time_seconds) - return TRUE; - - return FALSE; -} - - -static void -output_zone_components (FILE *fp, - char *name, - GArray *changes) -{ - VzicTime *vzictime; - int i, start_index = 0; - gboolean only_one_change = FALSE; - char start_buffer[1024]; - - fprintf (fp, "BEGIN:VTIMEZONE\nTZID:%s%s\n", TZIDPrefixExpanded, name); - - if (VzicUrlPrefix != NULL) - fprintf (fp, "TZURL:%s/%s\n", VzicUrlPrefix, name); - - /* We use an 'X-' property to place the city name in. */ - fprintf (fp, "X-LIC-LOCATION:%s\n", name); - - /* We try to find any recurring components first, or they may get output - as lots of RDATES instead. */ - if (!VzicNoRRules) { - int num_rrules_output = 0; - - for (i = 1; i < changes->len; i++) { - if (check_for_recurrence (fp, changes, i)) { - num_rrules_output++; - } - } - -#if 0 - printf ("Zone: %s had %i infinite RRULEs\n", CurrentZoneName, - num_rrules_output); -#endif - - if (!VzicPureOutput && num_rrules_output == 2) { -#if 0 - printf ("Zone: %s using 2 RRULEs\n", CurrentZoneName); -#endif - fprintf (fp, "END:VTIMEZONE\n"); - return; - } - } - - /* We skip the first change, which starts at -infinity, unless it is the only - change for the timezone. */ - if (changes->len > 1) - start_index = 1; - else - only_one_change = TRUE; - - /* For pure output, we start at the start of the array and step through it - outputting RDATEs. For Outlook-compatible output we start at the end - and step backwards to find the first STANDARD time to output. */ - if (VzicPureOutput) - i = start_index - 1; - else - i = changes->len; - - for (;;) { - if (VzicPureOutput) - i++; - else - i--; - - if (VzicPureOutput) { - if (i >= changes->len) - break; - } else { - if (i < start_index) - break; - } - - vzictime = &g_array_index (changes, VzicTime, i); - - /* If we have already output this component as part of an RRULE or RDATE, - then we skip it. */ - if (vzictime->output) - continue; - - /* For Outlook-compatible output we only want to output the last STANDARD - time as a DTSTART, so skip any DAYLIGHT changes. */ - if (!VzicPureOutput && vzictime->stdoff != vzictime->walloff) { - printf ("Skipping DAYLIGHT change\n"); - continue; - } - -#if 0 - printf ("Zone: %s using DTSTART Year: %i\n", CurrentZoneName, - vzictime->year); -#endif - - if (VzicPureOutput) { - output_component_start (start_buffer, vzictime, TRUE, only_one_change); - } else { - /* For Outlook compatability we don't output the RDATE and use the same - TZOFFSET for TZOFFSETFROM and TZOFFSETTO. */ - vzictime->year = RDATE_YEAR; - vzictime->month = 0; - vzictime->day_code = DAY_SIMPLE; - vzictime->day_number = 1; - vzictime->time_code = TIME_WALL; - vzictime->time_seconds = 0; - - output_component_start (start_buffer, vzictime, FALSE, TRUE); - } - - fprintf (fp, "%s", start_buffer); - - /* This will look for matching components and output them as RDATEs - instead of separate components. */ - if (VzicPureOutput && !VzicNoRDates) - check_for_rdates (fp, changes, i); - - output_component_end (fp, vzictime); - - vzictime->output = TRUE; - - if (!VzicPureOutput) - break; - } - - fprintf (fp, "END:VTIMEZONE\n"); -} - - -/* This sets the prev_stdoff and prev_walloff (i.e. the TZOFFSETFROM) of each - VzicTime, using the stdoff and walloff of the previous VzicTime. It makes - the rest of the code much simpler. */ -static void -set_previous_offsets (GArray *changes) -{ - VzicTime *vzictime, *prev_vzictime; - int i; - - prev_vzictime = &g_array_index (changes, VzicTime, 0); - prev_vzictime->prev_stdoff = 0; - prev_vzictime->prev_walloff = 0; - - for (i = 1; i < changes->len; i++) { - vzictime = &g_array_index (changes, VzicTime, i); - - vzictime->prev_stdoff = prev_vzictime->stdoff; - vzictime->prev_walloff = prev_vzictime->walloff; - - prev_vzictime = vzictime; - } -} - - -/* Returns TRUE if we output an infinite recurrence. */ -static gboolean -check_for_recurrence (FILE *fp, - GArray *changes, - int idx) -{ - VzicTime *vzictime_start, *vzictime, vzictime_start_copy; - gboolean is_daylight_start, is_daylight; - int last_match, i, next_year, day_offset; - char until[256], rrule_buffer[2048], start_buffer[1024]; - GList *matching_elements = NULL, *elem; - - vzictime_start = &g_array_index (changes, VzicTime, idx); - - /* If this change has already been output, skip it. */ - if (vzictime_start->output) - return FALSE; - - /* There can't possibly be an RRULE starting from YEAR_MINIMUM. */ - if (vzictime_start->year == YEAR_MINIMUM) - return FALSE; - - is_daylight_start = (vzictime_start->stdoff != vzictime_start->walloff) - ? TRUE : FALSE; - -#if 0 - printf ("\nChecking: %s OFFSETFROM: %i %s\n", - format_vzictime (vzictime_start), vzictime_start->prev_walloff, - is_daylight_start ? "DAYLIGHT" : ""); -#endif - - /* If this is an infinitely recurring change, output the RRULE and return. - There won't be any changes after it that we could merge. */ - if (vzictime_start->is_infinite) { - - /* Change the year to our minimum start year. */ - vzictime_start_copy = *vzictime_start; - if (!VzicPureOutput) - vzictime_start_copy.year = RRULE_START_YEAR; - - day_offset = output_component_start (start_buffer, &vzictime_start_copy, - FALSE, FALSE); - - if (!output_rrule (rrule_buffer, vzictime_start_copy.month, - vzictime_start_copy.day_code, - vzictime_start_copy.day_number, - vzictime_start_copy.day_weekday, day_offset, "")) { - if (vzictime_start->year != MAX_TIME_T_YEAR) { - fprintf (stderr, "WARNING: Failed to output infinite recurrence with start year: %i\n", vzictime_start->year); - } - return TRUE; - } - - fprintf (fp, "%s%s", start_buffer, rrule_buffer); - output_component_end (fp, vzictime_start); - vzictime_start->output = TRUE; - return TRUE; - } - - last_match = idx; - next_year = vzictime_start->year + 1; - for (i = idx + 1; i < changes->len; i++) { - vzictime = &g_array_index (changes, VzicTime, i); - - is_daylight = (vzictime->stdoff != vzictime->walloff) ? TRUE : FALSE; - - if (vzictime->output) - continue; - -#if 0 - printf (" %s OFFSETFROM: %i %s\n", - format_vzictime (vzictime), vzictime->prev_walloff, - is_daylight ? "DAYLIGHT" : ""); -#endif - - /* If it is more than one year ahead, we are finished, since we want - consecutive years. */ - if (vzictime->year > next_year) { - break; - } - - /* It must be the same type of component - STANDARD or DAYLIGHT. */ - if (is_daylight != is_daylight_start) { - continue; - } - - /* It must be the following year, with the same month, day & time. - It is possible that the time has a different code but does in fact - match when normalized, but we don't care (for now at least). */ - if (vzictime->year != next_year - || vzictime->month != vzictime_start->month - || vzictime->day_code != vzictime_start->day_code - || vzictime->day_number != vzictime_start->day_number - || vzictime->day_weekday != vzictime_start->day_weekday - || vzictime->time_seconds != vzictime_start->time_seconds - || vzictime->time_code != vzictime_start->time_code) { - continue; - } - - /* The TZOFFSETFROM and TZOFFSETTO must match. */ - if (vzictime->prev_walloff != vzictime_start->prev_walloff) { - continue; - } - - if (vzictime->walloff != vzictime_start->walloff) { - continue; - } - - /* TZNAME must match. */ - if (!timezones_match (vzictime->tzname, vzictime_start->tzname)) { - continue; - } - - /* We have a match. */ - last_match = i; - next_year = vzictime->year + 1; - - matching_elements = g_list_prepend (matching_elements, vzictime); - } - - if (last_match == idx) - return FALSE; - -#if 0 - printf ("Found recurrence %i - %i!!!\n", vzictime_start->year, - next_year - 1); -#endif - - vzictime = &g_array_index (changes, VzicTime, last_match); - -/* We only use RRULEs if there are at least MIN_RRULE_OCCURRENCES occurrences, - since otherwise RDATEs are more efficient. */ - if (!vzictime->is_infinite) { - int years = vzictime->year - vzictime_start->year + 1; -#if 0 - printf ("RRULE Years: %i\n", years); -#endif - if (years < MIN_RRULE_OCCURRENCES) - return FALSE; - } - - if (vzictime->is_infinite) { - until[0] = '\0'; - } else { - VzicTime t1 = *vzictime; - - printf ("RRULE with UNTIL - aborting\n"); - abort (); - - calculate_actual_time (&t1, TIME_UNIVERSAL, vzictime->prev_stdoff, - vzictime->prev_walloff); - - /* Output UNTIL, in UTC. */ - sprintf (until, ";UNTIL=%sZ", format_time (t1.year, t1.month, - t1.day_number, - t1.time_seconds)); - } - - /* Change the year to our minimum start year. */ - vzictime_start_copy = *vzictime_start; - if (!VzicPureOutput) - vzictime_start_copy.year = RRULE_START_YEAR; - - day_offset = output_component_start (start_buffer, &vzictime_start_copy, - FALSE, FALSE); - if (output_rrule (rrule_buffer, vzictime_start_copy.month, - vzictime_start_copy.day_code, - vzictime_start_copy.day_number, - vzictime_start_copy.day_weekday, day_offset, until)) { - fprintf (fp, "%s%s", start_buffer, rrule_buffer); - output_component_end (fp, vzictime_start); - - /* Mark all the changes as output. */ - vzictime_start->output = TRUE; - for (elem = matching_elements; elem; elem = elem->next) { - vzictime = elem->data; - vzictime->output = TRUE; - } - } - - g_list_free (matching_elements); - - return TRUE; -} - - -static void -check_for_rdates (FILE *fp, - GArray *changes, - int idx) -{ - VzicTime *vzictime_start, *vzictime, tmp_vzictime; - gboolean is_daylight_start, is_daylight; - int i, year, month, day, time; - - vzictime_start = &g_array_index (changes, VzicTime, idx); - - is_daylight_start = (vzictime_start->stdoff != vzictime_start->walloff) - ? TRUE : FALSE; - -#if 0 - printf ("\nChecking: %s OFFSETFROM: %i %s\n", - format_vzictime (vzictime_start), vzictime_start->prev_walloff, - is_daylight_start ? "DAYLIGHT" : ""); -#endif - - /* We want to go backwards through the array now, for Outlook compatability. - (It only looks at the first DTSTART/RDATE.) */ - for (i = idx + 1; i < changes->len; i++) { - vzictime = &g_array_index (changes, VzicTime, i); - - is_daylight = (vzictime->stdoff != vzictime->walloff) ? TRUE : FALSE; - - if (vzictime->output) - continue; - -#if 0 - printf (" %s OFFSETFROM: %i %s\n", format_vzictime (vzictime), - vzictime->prev_walloff, is_daylight ? "DAYLIGHT" : ""); -#endif - - /* It must be the same type of component - STANDARD or DAYLIGHT. */ - if (is_daylight != is_daylight_start) { - continue; - } - - /* The TZOFFSETFROM and TZOFFSETTO must match. */ - if (vzictime->prev_walloff != vzictime_start->prev_walloff) { - continue; - } - - if (vzictime->walloff != vzictime_start->walloff) { - continue; - } - - /* TZNAME must match. */ - if (!timezones_match (vzictime->tzname, vzictime_start->tzname)) { - continue; - } - - /* We have a match. */ - - tmp_vzictime = *vzictime; - calculate_actual_time (&tmp_vzictime, TIME_WALL, vzictime->prev_stdoff, - vzictime->prev_walloff); - - fprintf (fp, "RDATE:%s\n", format_time (tmp_vzictime.year, - tmp_vzictime.month, - tmp_vzictime.day_number, - tmp_vzictime.time_seconds)); - - vzictime->output = TRUE; - } -} - - -static gboolean -timezones_match (char *tzname1, - char *tzname2) -{ - if (tzname1 && tzname2 && !strcmp (tzname1, tzname2)) - return TRUE; - - if (!tzname1 && !tzname2) - return TRUE; - - return FALSE; -} - - -/* Outputs the start of a VTIMEZONE component, with the BEGIN line, - the DTSTART, TZOFFSETFROM, TZOFFSETTO & TZNAME properties. */ -static int -output_component_start (char *buffer, - VzicTime *vzictime, - gboolean output_rdate, - gboolean use_same_tz_offset) -{ - gboolean is_daylight, skip_day_offset = FALSE; - gint year, month, day, time, day_offset = 0; - GDate old_date, new_date; - char *formatted_time; - char line1[1024], line2[1024], line3[1024]; - char line4[1024], line5[1024], line6[1024]; - VzicTime tmp_vzictime; - int prev_walloff; - - is_daylight = (vzictime->stdoff != vzictime->walloff) ? TRUE : FALSE; - - tmp_vzictime = *vzictime; - day_offset = calculate_actual_time (&tmp_vzictime, TIME_WALL, - vzictime->prev_stdoff, - vzictime->prev_walloff); - - sprintf (line1, "BEGIN:%s\n", is_daylight ? "DAYLIGHT" : "STANDARD"); - - /* If the timezone only has one change, that means it uses the same offset - forever, so we use the same TZOFFSETFROM as the TZOFFSETTO. (If the zone - has more than one change, we don't output the first one.) */ - if (use_same_tz_offset) - prev_walloff = vzictime->walloff; - else - prev_walloff = vzictime->prev_walloff; - - sprintf (line2, "TZOFFSETFROM:%s\n", - format_tz_offset (prev_walloff, !VzicPureOutput)); - - sprintf (line3, "TZOFFSETTO:%s\n", - format_tz_offset (vzictime->walloff, !VzicPureOutput)); - - if (vzictime->tzname) - sprintf (line4, "TZNAME:%s\n", vzictime->tzname); - else - line4[0] = '\0'; - - formatted_time = format_time (tmp_vzictime.year, tmp_vzictime.month, - tmp_vzictime.day_number, - tmp_vzictime.time_seconds); - sprintf (line5, "DTSTART:%s\n", formatted_time); - if (output_rdate) - sprintf (line6, "RDATE:%s\n", formatted_time); - else - line6[0] = '\0'; - - sprintf (buffer, "%s%s%s%s%s%s", line1, line2, line3, line4, line5, line6); - - return day_offset; -} - - -/* Outputs the END line of the VTIMEZONE component. */ -static void -output_component_end (FILE *fp, - VzicTime *vzictime) -{ - gboolean is_daylight; - - is_daylight = (vzictime->stdoff != vzictime->walloff) ? TRUE : FALSE; - - fprintf (fp, "END:%s\n", is_daylight ? "DAYLIGHT" : "STANDARD"); -} - - -/* Initializes a VzicTime to 1st Jan in YEAR_MINIMUM at midnight, with all - offsets set to 0. */ -static void -vzictime_init (VzicTime *vzictime) -{ - vzictime->year = YEAR_MINIMUM; - vzictime->month = 0; - vzictime->day_code = DAY_SIMPLE; - vzictime->day_number = 1; - vzictime->day_weekday = 0; - vzictime->time_seconds = 0; - vzictime->time_code = TIME_UNIVERSAL; - vzictime->stdoff = 0; - vzictime->walloff = 0; - vzictime->is_infinite = FALSE; - vzictime->output = FALSE; - vzictime->prev_stdoff = 0; - vzictime->prev_walloff = 0; - vzictime->tzname = NULL; -} - - -/* This calculates the actual local time that a change will occur, given - the offsets from standard and wall-clock time. It returns -1 or 1 if it - had to move backwards or forwards one day while converting to local time. - If it does this then we need to change the RRULEs we output. */ -static int -calculate_actual_time (VzicTime *vzictime, - TimeCode time_code, - int stdoff, - int walloff) -{ - GDate date; - gint day_offset, days_in_month, weekday, offset, result; - - vzictime->time_seconds = calculate_wall_time (vzictime->time_seconds, - vzictime->time_code, - stdoff, walloff, &day_offset); - - if (vzictime->day_code != DAY_SIMPLE) { - if (vzictime->year == YEAR_MINIMUM || vzictime->year == YEAR_MAXIMUM) { - fprintf (stderr, "In calculate_actual_time: invalid year\n"); - exit (0); - } - - g_date_clear (&date, 1); - days_in_month = g_date_days_in_month (vzictime->month + 1, vzictime->year); - - /* Note that the day_code refers to the date before we convert it to - a wall-clock date and time. So we find the day it was referring to, - then make any adjustments needed due to converting the time. */ - if (vzictime->day_code == DAY_LAST_WEEKDAY) { - /* Find out what day the last day of the month is. */ - g_date_set_dmy (&date, days_in_month, vzictime->month + 1, - vzictime->year); - weekday = g_date_weekday (&date) % 7; - - /* Calculate how many days we have to go back to get to day_weekday. */ - offset = (weekday + 7 - vzictime->day_weekday) % 7; - - vzictime->day_number = days_in_month - offset; - } else { - /* Find out what day day_number actually is. */ - g_date_set_dmy (&date, vzictime->day_number, vzictime->month + 1, - vzictime->year); - weekday = g_date_weekday (&date) % 7; - - if (vzictime->day_code == DAY_WEEKDAY_ON_OR_AFTER) - offset = (vzictime->day_weekday + 7 - weekday) % 7; - else - offset = - ((weekday + 7 - vzictime->day_weekday) % 7); - - vzictime->day_number = vzictime->day_number + offset; - } - - vzictime->day_code = DAY_SIMPLE; - - if (vzictime->day_number <= 0 || vzictime->day_number > days_in_month) { - fprintf (stderr, "Day overflow: %i\n", vzictime->day_number); - exit (1); - } - } - -#if 0 - fprintf (stderr, "%s -> %i/%i/%i\n", - dump_day_coded (vzictime->day_code, vzictime->day_number, - vzictime->day_weekday), - vzictime->day_number, vzictime->month + 1, vzictime->year); -#endif - - fix_time_overflow (&vzictime->year, &vzictime->month, - &vzictime->day_number, day_offset); - - /* If we want UTC time, we have to convert it now. */ - if (time_code == TIME_UNIVERSAL) { - vzictime->time_seconds = calculate_until_time (vzictime->time_seconds, - TIME_WALL, stdoff, walloff, - &vzictime->year, - &vzictime->month, - &vzictime->day_number); - } - - return day_offset; -} - - -/* This converts the given time into universal time (UTC), to be used in - the UNTIL property. */ -static int -calculate_until_time (int time, - TimeCode time_code, - int stdoff, - int walloff, - int *year, - int *month, - int *day) -{ - int result, day_offset; - - day_offset = 0; - - switch (time_code) { - case TIME_WALL: - result = time - walloff; - break; - case TIME_STANDARD: - result = time - stdoff; - break; - case TIME_UNIVERSAL: - return time; - default: - fprintf (stderr, "Invalid time code\n"); - exit (1); - } - - if (result < 0) { - result += 24 * 60 * 60; - day_offset = -1; - } else if (result >= 24 * 60 * 60) { - result -= 24 * 60 * 60; - day_offset = 1; - } - - /* Sanity check - we shouldn't have an overflow any more. */ - if (result < 0 || result >= 24 * 60 * 60) { - fprintf (stderr, "Time overflow: %i\n", result); - abort (); - } - - fix_time_overflow (year, month, day, day_offset); - - return result; -} - - -/* This converts the given time into wall clock time (the local standard time - with any adjustment for daylight-saving). */ -static int -calculate_wall_time (int time, - TimeCode time_code, - int stdoff, - int walloff, - int *day_offset) -{ - int result; - - *day_offset = 0; - - switch (time_code) { - case TIME_WALL: - return time; - case TIME_STANDARD: - /* We have a local standard time, so we have to subtract stdoff to get - back to UTC, then add walloff to get wall time. */ - result = time - stdoff + walloff; - break; - case TIME_UNIVERSAL: - result = time + walloff; - break; - default: - fprintf (stderr, "Invalid time code\n"); - exit (1); - } - - if (result < 0) { - result += 24 * 60 * 60; - *day_offset = -1; - } else if (result >= 24 * 60 * 60) { - result -= 24 * 60 * 60; - *day_offset = 1; - } - - /* Sanity check - we shouldn't have an overflow any more. */ - if (result < 0 || result >= 24 * 60 * 60) { - fprintf (stderr, "Time overflow: %i\n", result); - exit (1); - } - -#if 0 - printf ("%s -> ", dump_time (time, time_code, TRUE)); - printf ("%s (%i)\n", dump_time (result, TIME_WALL, TRUE), *day_offset); -#endif - - return result; -} - - -static void -fix_time_overflow (int *year, - int *month, - int *day, - int day_offset) -{ - if (day_offset == -1) { - *day = *day - 1; - - if (*day == 0) { - *month = *month - 1; - if (*month == -1) { - *month = 11; - *year = *year - 1; - } - *day = g_date_days_in_month (*month + 1, *year); - } - } else if (day_offset == 1) { - *day = *day + 1; - - if (*day > g_date_days_in_month (*month + 1, *year)) { - *month = *month + 1; - if (*month == 12) { - *month = 0; - *year = *year + 1; - } - *day = 1; - } - } -} - - -static char* -format_time (int year, - int month, - int day, - int time) -{ - static char buffer[128]; - int hour, minute, second; - - /* When we are outputting the first component year will be YEAR_MINIMUM. - We used to use 1 when outputting this, but Outlook doesn't like any years - less that 1600, so we use 1600 instead. We don't output the first change - for most zones now, so it doesn't matter too much. */ - if (year == YEAR_MINIMUM) - year = 1601; - - /* We just use 9999 here, so we keep to 4 characters. But this should only - be needed when debugging - it shouldn't be needed in the VTIMEZONEs. */ - if (year == YEAR_MAXIMUM) { - fprintf (stderr, "format_time: YEAR_MAXIMUM used\n"); - year = 9999; - } - - hour = time / 3600; - minute = (time % 3600) / 60; - second = time % 60; - - sprintf (buffer, "%04i%02i%02iT%02i%02i%02i", - year, month + 1, day, hour, minute, second); - - return buffer; -} - - -/* Outlook doesn't support 6-digit values, i.e. including the seconds, so - we round to the nearest minute. No current offsets use the seconds value, - so we aren't losing much. */ -static char* -format_tz_offset (int tz_offset, - gboolean round_seconds) -{ - static char buffer[128]; - char *sign = "+"; - int hours, minutes, seconds; - - if (tz_offset < 0) { - tz_offset = -tz_offset; - sign = "-"; - } - - if (round_seconds) - tz_offset += 30; - - hours = tz_offset / 3600; - minutes = (tz_offset % 3600) / 60; - seconds = tz_offset % 60; - - if (round_seconds) - seconds = 0; - - /* Sanity check. Standard timezone offsets shouldn't be much more than 12 - hours, and daylight saving shouldn't change it by more than a few hours. - (The maximum offset is 15 hours 56 minutes at present.) */ - if (hours < 0 || hours >= 24 || minutes < 0 || minutes >= 60 - || seconds < 0 || seconds >= 60) { - fprintf (stderr, "WARNING: Strange timezone offset: H:%i M:%i S:%i\n", - hours, minutes, seconds); - } - - if (seconds == 0) - sprintf (buffer, "%s%02i%02i", sign, hours, minutes); - else - sprintf (buffer, "%s%02i%02i%02i", sign, hours, minutes, seconds); - - return buffer; -} - - -static gboolean -output_rrule (char *rrule_buffer, - int month, - DayCode day_code, - int day_number, - int day_weekday, - int day_offset, - char *until) -{ - char buffer[1024], buffer2[1024]; - - buffer[0] = '\0'; - - if (day_offset > 1 || day_offset < -1) { - fprintf (stderr, "Invalid day_offset: %i\n", day_offset); - exit (0); - } - - /* If the DTSTART time was moved to another day when converting to local - time, we need to adjust the RRULE accordingly. e.g. If the original RRULE - was on the 19th of the month, but DTSTART was moved 1 day forward, then - we output the 20th of the month instead. */ - if (day_offset == 1) { - if (day_code != DAY_LAST_WEEKDAY) - day_number++; - day_weekday = (day_weekday + 1) % 7; - - /* Check we don't use February 29th. */ - if (month == 1 && day_number > 28) { - fprintf (stderr, "Can't format RRULE - out of bounds. Month: %i Day number: %i\n", month + 1, day_number); - exit (0); - } - - /* If we go past the end of the month, move to the next month. */ - if (day_code != DAY_LAST_WEEKDAY && day_number > DaysInMonth[month]) { - month++; - day_number = 1; - } - - } else if (day_offset == -1) { - if (day_code != DAY_LAST_WEEKDAY) - day_number--; - day_weekday = (day_weekday + 6) % 7; - - if (day_code != DAY_LAST_WEEKDAY && day_number < 1) - fprintf (stderr, "Month: %i Day number: %i\n", month + 1, day_number); - } - - switch (day_code) { - case DAY_SIMPLE: - /* Outlook (2000) will not parse the simple YEARLY RRULEs in VTIMEZONEs, - or BYMONTHDAY, or BYYEARDAY, which makes this option difficult! - Currently we use something like BYDAY=1SU, which will be incorrect - at times. This only affects Asia/Baghdad, Asia/Gaza, Asia/Jerusalem & - Asia/Damascus at present (and Jerusalem doesn't have specific rules - at the moment anyway, so that isn't a big loss). */ - if (!VzicPureOutput) { - if (day_number < 8) { - printf ("WARNING: %s: Outputting BYDAY=1SU instead of BYMONTHDAY=1-7 for Outlook compatability\n", CurrentZoneName); - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=1SU", - month + 1); - } else if (day_number < 15) { - printf ("WARNING: %s: Outputting BYDAY=2SU instead of BYMONTHDAY=8-14 for Outlook compatability\n", CurrentZoneName); - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=2SU", - month + 1); - } else if (day_number < 22) { - printf ("WARNING: %s: Outputting BYDAY=3SU instead of BYMONTHDAY=15-21 for Outlook compatability\n", CurrentZoneName); - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=3SU", - month + 1); - } else { - printf ("ERROR: %s: Couldn't output RRULE (day=%i) compatible with Outlook\n", CurrentZoneName, day_number); - exit (1); - } - } else { - sprintf (buffer, "RRULE:FREQ=YEARLY"); - } - break; - - case DAY_WEEKDAY_ON_OR_AFTER: - if (day_number > DaysInMonth[month] - 6) { - /* This isn't actually needed at present. */ -#if 0 - fprintf (stderr, "DAY_WEEKDAY_ON_OR_AFTER: %i %i\n", day_number, - month + 1); -#endif - - if (!VzicPureOutput) { - printf ("ERROR: %s: Couldn't output RRULE (day>=x) compatible with Outlook\n", CurrentZoneName); - exit (1); - } else { - /* We do 6 days at the end of this month, and 1 at the start of the - next. We can't do this if we want Outlook compatability, as it - needs BYMONTHDAY, which Outlook doesn't support. */ - sprintf (buffer, - "RRULE:FREQ=YEARLY;BYMONTH=%i;BYMONTHDAY=%i,%i,%i,%i,%i,%i;BYDAY=%s", - month + 1, - day_number, day_number + 1, day_number + 2, day_number + 3, - day_number + 4, day_number + 5, - WeekDays[day_weekday]); - - sprintf (buffer2, - "RRULE:FREQ=YEARLY;BYMONTH=%i;BYMONTHDAY=1;BYDAY=%s", - (month + 1) % 12 + 1, - WeekDays[day_weekday]); - - sprintf (rrule_buffer, "%s%s\n%s%s\n", - buffer, until, buffer2, until); - - return TRUE; - } - } - - if (!output_rrule_2 (buffer, month, day_number, day_weekday)) - return FALSE; - - break; - - case DAY_WEEKDAY_ON_OR_BEFORE: - if (day_number < 7) { - /* FIXME: This is unimplemented, but it isn't needed at present anway. */ - fprintf (stderr, "DAY_WEEKDAY_ON_OR_BEFORE: %i. Unimplemented. Exiting...\n", day_number); - exit (0); - } - - if (!output_rrule_2 (buffer, month, day_number - 6, day_weekday)) - return FALSE; - - break; - - case DAY_LAST_WEEKDAY: - if (day_offset == 1) { - if (month == 1) { - fprintf (stderr, "DAY_LAST_WEEKDAY - day moved, in February - can't fix\n"); - exit (0); - } - - /* This is only used once at present, for Africa/Cairo. */ -#if 0 - fprintf (stderr, "DAY_LAST_WEEKDAY - day moved\n"); -#endif - - if (!VzicPureOutput) { - printf ("WARNING: %s: Modifying RRULE (last weekday) for Outlook compatability\n", CurrentZoneName); - sprintf (buffer, - "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=-1%s", - month + 1, WeekDays[day_weekday]); - printf (" Outputting: %s\n", buffer); - } else { - /* We do 6 days at the end of this month, and 1 at the start of the - next. We can't do this if we want Outlook compatability, as it needs - BYMONTHDAY, which Outlook doesn't support. */ - day_number = DaysInMonth[month]; - sprintf (buffer, - "RRULE:FREQ=YEARLY;BYMONTH=%i;BYMONTHDAY=%i,%i,%i,%i,%i,%i;BYDAY=%s", - month + 1, - day_number - 5, day_number - 4, day_number - 3, - day_number - 2, day_number - 1, day_number, - WeekDays[day_weekday]); - - sprintf (buffer2, - "RRULE:FREQ=YEARLY;BYMONTH=%i;BYMONTHDAY=1;BYDAY=%s", - (month + 1) % 12 + 1, - WeekDays[day_weekday]); - - sprintf (rrule_buffer, "%s%s\n%s%s\n", - buffer, until, buffer2, until); - - return TRUE; - } - - } else if (day_offset == -1) { - /* We do 7 days 1 day before the end of this month. */ - day_number = DaysInMonth[month]; - - if (!output_rrule_2 (buffer, month, day_number - 7, day_weekday)) - return FALSE; - - sprintf (rrule_buffer, "%s%s\n", buffer, until); - return TRUE; - } - - sprintf (buffer, - "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=-1%s", - month + 1, WeekDays[day_weekday]); - break; - - default: - fprintf (stderr, "Invalid day code\n"); - exit (1); - } - - sprintf (rrule_buffer, "%s%s\n", buffer, until); - return TRUE; -} - - -/* This tries to convert a RRULE like 'BYMONTHDAY=8,9,10,11,12,13,14;BYDAY=FR' - into 'BYDAY=2FR'. We need this since Outlook doesn't accept BYMONTHDAY. - It returns FALSE if conversion is not possible. */ -static gboolean -output_rrule_2 (char *buffer, - int month, - int day_number, - int day_weekday) -{ - - if (day_number == 1) { - /* Convert it to a BYDAY=1SU type of RRULE. */ - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=1%s", - month + 1, WeekDays[day_weekday]); - - } else if (day_number == 8) { - /* Convert it to a BYDAY=2SU type of RRULE. */ - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=2%s", - month + 1, WeekDays[day_weekday]); - - } else if (day_number == 15) { - /* Convert it to a BYDAY=3SU type of RRULE. */ - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=3%s", - month + 1, WeekDays[day_weekday]); - - } else if (day_number == 22) { - /* Convert it to a BYDAY=4SU type of RRULE. (Currently not used.) */ - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=4%s", - month + 1, WeekDays[day_weekday]); - - } else if (month != 1 && day_number == DaysInMonth[month] - 6) { - /* Convert it to a BYDAY=-1SU type of RRULE. (But never for February.) */ - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=-1%s", - month + 1, WeekDays[day_weekday]); - - } else { - /* Can't convert to a correct RRULE. If we want Outlook compatability we - have to use a slightly incorrect RRULE, so the time change will be 1 - week out every 7 or so years. Alternatively we could possibly move the - change by an hour or so so we would always be 1 or 2 hours out, but - never 1 week out. Yes, that sounds a better idea. */ - if (!VzicPureOutput) { - printf ("WARNING: %s: Modifying RRULE to be compatible with Outlook (day >= %i, month = %i)\n", CurrentZoneName, day_number, month + 1); - - if (day_number == 2) { - /* Convert it to a BYDAY=1SU type of RRULE. - This is needed for Asia/Karachi. */ - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=1%s", - month + 1, WeekDays[day_weekday]); - } else if (day_number == 9) { - /* Convert it to a BYDAY=2SU type of RRULE. - This is needed for Antarctica/Palmer & America/Santiago. */ - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=2%s", - month + 1, WeekDays[day_weekday]); - } else if (month != 1 && day_number == DaysInMonth[month] - 7) { - /* Convert it to a BYDAY=-1SU type of RRULE. (But never for February.) - This is needed for America/Godthab. */ - sprintf (buffer, "RRULE:FREQ=YEARLY;BYMONTH=%i;BYDAY=-1%s", - month + 1, WeekDays[day_weekday]); - } else { - printf ("ERROR: %s: Couldn't modify RRULE to be compatible with Outlook (day >= %i, month = %i)\n", CurrentZoneName, day_number, month + 1); - exit (1); - } - - } else { - sprintf (buffer, - "RRULE:FREQ=YEARLY;BYMONTH=%i;BYMONTHDAY=%i,%i,%i,%i,%i,%i,%i;BYDAY=%s", - month + 1, - day_number, day_number + 1, day_number + 2, day_number + 3, - day_number + 4, day_number + 5, day_number + 6, - WeekDays[day_weekday]); - } - } - - return TRUE; -} - - -static char* -format_vzictime (VzicTime *vzictime) -{ - static char buffer[1024]; - - sprintf (buffer, "%s %2i %s %s %i %i %s", - dump_year (vzictime->year), vzictime->month + 1, - dump_day_coded (vzictime->day_code, vzictime->day_number, - vzictime->day_weekday), - dump_time (vzictime->time_seconds, vzictime->time_code, TRUE), - vzictime->stdoff, vzictime->walloff, - vzictime->is_infinite ? "INFINITE" : ""); - - return buffer; -} - - -static void -dump_changes (FILE *fp, - char *zone_name, - GArray *changes) -{ - VzicTime *vzictime, *vzictime2 = NULL; - int i, year_offset, year; - - for (i = 0; i < changes->len; i++) { - vzictime = &g_array_index (changes, VzicTime, i); - - if (vzictime->year > MAX_CHANGES_YEAR) - return; - - dump_change (fp, zone_name, vzictime, vzictime->year); - } - - if (changes->len < 2) - return; - - /* Now see if the changes array ends with a pair of recurring changes. */ - vzictime = &g_array_index (changes, VzicTime, changes->len - 2); - vzictime2 = &g_array_index (changes, VzicTime, changes->len - 1); - if (!vzictime->is_infinite || !vzictime2->is_infinite) - return; - - year_offset = 1; - for (;;) { - year = vzictime->year + year_offset; - if (year > MAX_CHANGES_YEAR) - break; - dump_change (fp, zone_name, vzictime, year); - - year = vzictime2->year + year_offset; - if (year > MAX_CHANGES_YEAR) - break; - dump_change (fp, zone_name, vzictime2, year); - - year_offset++; - } -} - - -static void -dump_change (FILE *fp, - char *zone_name, - VzicTime *vzictime, - int year) -{ - int hour, minute, second; - VzicTime tmp_vzictime; - static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - - /* Output format is: - - Zone-Name [tab] Date [tab] Time [tab] UTC-Offset - - The Date and Time fields specify the time change in UTC. - - The UTC Offset is for local (wall-clock) time. It is the amount of time - to add to UTC to get local time. - */ - - fprintf (fp, "%s\t", zone_name); - - if (year == YEAR_MINIMUM) { - fprintf (fp, " 1 Jan 0001\t 0:00:00", zone_name); - } else if (year == YEAR_MAXIMUM) { - fprintf (stderr, "Maximum year found in change time\n"); - exit (1); - } else { - tmp_vzictime = *vzictime; - tmp_vzictime.year = year; - calculate_actual_time (&tmp_vzictime, TIME_UNIVERSAL, - vzictime->prev_stdoff, vzictime->prev_walloff); - - hour = tmp_vzictime.time_seconds / 3600; - minute = (tmp_vzictime.time_seconds % 3600) / 60; - second = tmp_vzictime.time_seconds % 60; - - fprintf (fp, "%2i %s %04i\t%2i:%02i:%02i", - tmp_vzictime.day_number, months[tmp_vzictime.month], - tmp_vzictime.year, hour, minute, second); - } - - fprintf (fp, "\t%s", format_tz_offset (vzictime->walloff, FALSE)); - - fprintf (fp, "\n"); -} - - -void -ensure_directory_exists (char *directory) -{ - struct stat filestat; - - if (stat (directory, &filestat) != 0) { - /* If the directory doesn't exist, try to create it. */ - if (errno == ENOENT) { - if (mkdir (directory, 0777) != 0) { - fprintf (stderr, "Can't create directory: %s\n", directory); - exit (1); - } - } else { - fprintf (stderr, "Error calling stat() on directory: %s\n", directory); - exit (1); - } - } else if (!S_ISDIR (filestat.st_mode)) { - fprintf (stderr, "Can't create directory, already exists: %s\n", - directory); - exit (1); - } -} - - -static void -expand_tzid_prefix (void) -{ - char *src, *dest; - char date_buf[16]; - char ch1, ch2; - time_t t; - struct tm *tm; - - /* Get today's date as a string in the format "YYYYMMDD". */ - t = time (NULL); - tm = localtime (&t); - sprintf (date_buf, "%4i%02i%02i", tm->tm_year + 1900, - tm->tm_mon + 1, tm->tm_mday); - - src = TZIDPrefix; - dest = TZIDPrefixExpanded; - - while (ch1 = *src++) { - - /* Look for a '%'. */ - if (ch1 == '%') { - ch2 = *src++; - - if (ch2 == 'D') { - /* '%D' gets expanded into the date string. */ - strcpy (dest, date_buf); - dest += strlen (dest); - } else if (ch2 == '%') { - /* '%%' gets converted into one '%'. */ - *dest++ = '%'; - } else { - /* Anything else is output as is. */ - *dest++ = '%'; - *dest++ = ch2; - } - } else { - *dest++ = ch1; - } - } - -#if 0 - printf ("TZID : %s\n", TZIDPrefix); - printf ("Expanded: %s\n", TZIDPrefixExpanded); -#endif -} diff --git a/libkcal/libical/vzic-1.3/vzic-output.h b/libkcal/libical/vzic-1.3/vzic-output.h deleted file mode 100644 index 1e2df9f80..000000000 --- a/libkcal/libical/vzic-1.3/vzic-output.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _VZIC_OUTPUT_H_ -#define _VZIC_OUTPUT_H_ - -#include <glib.h> - -void output_vtimezone_files (char *directory, - GArray *zone_data, - GHashTable *rule_data, - GHashTable *link_data, - int max_until_year); - -void ensure_directory_exists (char *directory); - -#endif /* _VZIC_OUTPUT_H_ */ diff --git a/libkcal/libical/vzic-1.3/vzic-parse.c b/libkcal/libical/vzic-1.3/vzic-parse.c deleted file mode 100644 index aa50ff265..000000000 --- a/libkcal/libical/vzic-1.3/vzic-parse.c +++ /dev/null @@ -1,901 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <ctype.h> -#include <limits.h> -#include <stdio.h> -#include <string.h> - -#include "vzic.h" -#include "vzic-parse.h" - -/* This is the maximum line length we allow. */ -#define MAX_LINE_LEN 1024 - -/* The maximum number of fields on a line. */ -#define MAX_FIELDS 12 - - -typedef enum -{ - ZONE_ID = 0, /* The 'Zone' at the start of the line. */ - ZONE_NAME = 1, - ZONE_GMTOFF = 2, - ZONE_RULES_SAVE = 3, - ZONE_FORMAT = 4, - ZONE_UNTIL_YEAR = 5, - ZONE_UNTIL_MONTH = 6, - ZONE_UNTIL_DAY = 7, - ZONE_UNTIL_TIME = 8 -} ZoneFieldNumber; - - -typedef enum -{ - RULE_ID = 0, /* The 'Rule' at the start of the line. */ - RULE_NAME = 1, - RULE_FROM = 2, - RULE_TO = 3, - RULE_TYPE = 4, - RULE_IN = 5, - RULE_ON = 6, - RULE_AT = 7, - RULE_SAVE = 8, - RULE_LETTER_S = 9 -} RuleFieldNumber; - - -typedef enum -{ - LINK_ID = 0, /* The 'Link' at the start of the line. */ - LINK_FROM = 1, - LINK_TO = 2 -} LinkFieldNumber; - - -/* This struct contains information used while parsing the files, and is - passed to most parsing functions. */ -typedef struct _ParsingData ParsingData; -struct _ParsingData -{ - /* This is the line being parsed. buffer is a copy that we break into fields - and sub-fields as it is parsed. */ - char line[MAX_LINE_LEN]; - char buffer[MAX_LINE_LEN]; - - /* These are pointers to the start of each field in buffer. */ - char *fields[MAX_FIELDS]; - int num_fields; - - /* These are just for producing error messages. */ - char *filename; - int line_number; - - - /* This is an array of ZoneData structs, 1 for each timezone read. */ - GArray *zone_data; - - /* This is a hash table of arrays of RuleData structs. As each Rule line is - read in, a new RuleData struct is filled in and appended to the - appropriate GArray in the hash table. */ - GHashTable *rule_data; - - /* A hash containing data on the Link lines. The keys are the timezones - where the link is from (i.e. the timezone we will be outputting anyway) - and the data is a GList of timezones to link to (where we will copy the - timezone data to). */ - GHashTable *link_data; - - int max_until_year; -}; - - -/* - * Parsing functions, used when reading the Olson timezone data file. - */ -static void parse_fields (ParsingData *data); -static gboolean parse_zone_line (ParsingData *data); -static gboolean parse_zone_continuation_line (ParsingData *data); -static gboolean parse_zone_common (ParsingData *data, - int offset); -static void parse_rule_line (ParsingData *data); -static void parse_link_line (ParsingData *data); - -static int parse_year (ParsingData *data, - char *field, - gboolean accept_only, - int only_value); -static int parse_month (ParsingData *data, - char *field); -static DayCode parse_day (ParsingData *data, - char *field, - int *day, - int *weekday); -static int parse_weekday (ParsingData *data, - char *field); -static int parse_time (ParsingData *data, - char *field, - TimeCode *time_code); -static int parse_number (ParsingData *data, - char **num); -static int parse_rules_save (ParsingData *data, - char *field, - char **rules); - -static void parse_coord (char *coord, - int len, - int *result); - -void -parse_olson_file (char *filename, - GArray **zone_data, - GHashTable **rule_data, - GHashTable **link_data, - int *max_until_year) -{ - ParsingData data; - FILE *fp; - int zone_continues = 0; - - *zone_data = g_array_new (FALSE, FALSE, sizeof (ZoneData)); - *rule_data = g_hash_table_new (g_str_hash, g_str_equal); - *link_data = g_hash_table_new (g_str_hash, g_str_equal); - - fp = fopen (filename, "r"); - if (!fp) { - fprintf (stderr, "Couldn't open file: %s\n", filename); - exit (1); - } - - data.filename = filename; - data.zone_data = *zone_data; - data.rule_data = *rule_data; - data.link_data = *link_data; - data.max_until_year = 0; - - for (data.line_number = 0; ; data.line_number++) { - if (fgets (data.line, sizeof (data.line), fp) != data.line) - break; - - strcpy (data.buffer, data.line); - - parse_fields (&data); - if (data.num_fields == 0) - continue; - - if (zone_continues) { - zone_continues = parse_zone_continuation_line (&data); - } else if (!strcmp (data.fields[0], "Zone")) { - zone_continues = parse_zone_line (&data); - } else if (!strcmp (data.fields[0], "Rule")) { - parse_rule_line (&data); - } else if (!strcmp (data.fields[0], "Link")) { - parse_link_line (&data); - } else if (!strcmp (data.fields[0], "Leap")) { - /* We don't care about Leap lines. */ - } else { - fprintf (stderr, "%s:%i: Invalid line.\n%s\n", filename, - data.line_number, data.line); - exit (1); - } - } - - if (ferror (fp)) { - fprintf (stderr, "Error reading file: %s\n", filename); - exit (1); - } - - if (zone_continues) { - fprintf (stderr, "%s:%i: Zone continuation line expected.\n%s\n", - filename, data.line_number, data.line); - exit (1); - } - - fclose (fp); - -#if 0 - printf ("Max UNTIL year: %i\n", data.max_until_year); -#endif - *max_until_year = data.max_until_year; -} - - -/* Converts the line into fields. */ -static void -parse_fields (ParsingData *data) -{ - int i; - char *p, *s, ch; - - /* Reset all fields to NULL. */ - for (i = 0; i < MAX_FIELDS; i++) - data->fields[i] = 0; - - data->num_fields = 0; - p = data->buffer; - - for (;;) { - /* Skip whitespace. */ - while (isspace (*p)) - p++; - - /* See if we have reached the end of the line or a comment. */ - if (*p == '\0' || *p == '#') - break; - - /* We must have another field, so save the start position. */ - data->fields[data->num_fields++] = p; - - /* Now find the end of the field. If the field contains '"' characters - they are removed and we have to move the rest of the chars back. */ - s = p; - for (;;) { - ch = *p; - if (ch == '\0' || ch == '#') { - /* Don't move p on since this is the end of the line. */ - *s = '\0'; - break; - } else if (isspace (ch)) { - *s = '\0'; - p++; - break; - } else if (ch == '"') { - p++; - for (;;) { - ch = *p; - if (ch == '\0') { - fprintf (stderr, - "%s:%i: Closing quote character ('\"') missing.\n%s\n", - data->filename, data->line_number, data->line); - exit (1); - } else if (ch == '"') { - p++; - break; - } else { - *s++ = ch; - } - p++; - } - } else { - *s++ = ch; - } - p++; - } - } - -#if 0 - printf ("%i fields: ", data->num_fields); - for (i = 0; i < data->num_fields; i++) - printf ("'%s' ", data->fields[i]); - printf ("\n"); -#endif -} - - -static gboolean -parse_zone_line (ParsingData *data) -{ - ZoneData zone; - - /* All 5 fields up to FORMAT must be present. */ - if (data->num_fields < 5 || data->num_fields > 9) { - fprintf (stderr, "%s:%i: Invalid Zone line - %i fields.\n%s\n", - data->filename, data->line_number, data->num_fields, - data->line); - exit (1); - } - - zone.zone_name = g_strdup (data->fields[ZONE_NAME]); - zone.zone_line_data = g_array_new (FALSE, FALSE, sizeof (ZoneLineData)); - - g_array_append_val (data->zone_data, zone); - - return parse_zone_common (data, 0); -} - - -static gboolean -parse_zone_continuation_line (ParsingData *data) -{ - /* All 3 fields up to FORMAT must be present. */ - if (data->num_fields < 3 || data->num_fields > 7) { - fprintf (stderr, - "%s:%i: Invalid Zone continuation line - %i fields.\n%s\n", - data->filename, data->line_number, data->num_fields, - data->line); - exit (1); - } - - return parse_zone_common (data, -2); -} - - -static gboolean -parse_zone_common (ParsingData *data, - int offset) -{ - ZoneData *zone; - ZoneLineData zone_line; - TimeCode time_code; - - zone_line.stdoff_seconds = parse_time (data, - data->fields[ZONE_GMTOFF + offset], - &time_code); - zone_line.save_seconds = parse_rules_save (data, - data->fields[ZONE_RULES_SAVE + offset], - &zone_line.rules); - - if (!VzicPureOutput) { - /* We round the UTC offsets to the nearest minute, to be compatible with - Outlook. This also works with -ve numbers, I think. - -56 % 60 = -59. -61 % 60 = -1. */ - if (zone_line.stdoff_seconds >= 0) - zone_line.stdoff_seconds += 30; - else - zone_line.stdoff_seconds -= 29; - zone_line.stdoff_seconds -= zone_line.stdoff_seconds % 60; - - if (zone_line.save_seconds >= 0) - zone_line.save_seconds += 30; - else - zone_line.save_seconds -= 29; - zone_line.save_seconds -= zone_line.save_seconds % 60; - } - - zone_line.format = g_strdup (data->fields[ZONE_FORMAT + offset]); - - if (data->num_fields - offset >= 6) { - zone_line.until_set = TRUE; - zone_line.until_year = parse_year (data, - data->fields[ZONE_UNTIL_YEAR + offset], - FALSE, 0); - zone_line.until_month = parse_month (data, - data->fields[ZONE_UNTIL_MONTH + offset]); - zone_line.until_day_code = parse_day (data, - data->fields[ZONE_UNTIL_DAY + offset], - &zone_line.until_day_number, - &zone_line.until_day_weekday); - zone_line.until_time_seconds = parse_time (data, - data->fields[ZONE_UNTIL_TIME + offset], - &zone_line.until_time_code); - - /* We also want to know the maximum year used in any UNTIL value, so we - know where to expand all the infinite Rule data to. */ - if (zone_line.until_year != YEAR_MAXIMUM - && zone_line.until_year != YEAR_MINIMUM) - data->max_until_year = MAX (data->max_until_year, zone_line.until_year); - - } else { - zone_line.until_set = FALSE; - } - - /* Append it to the last Zone, since that is the one we are currently - reading. */ - zone = &g_array_index (data->zone_data, ZoneData, data->zone_data->len - 1); - g_array_append_val (zone->zone_line_data, zone_line); - - return zone_line.until_set; -} - - -static void -parse_rule_line (ParsingData *data) -{ - GArray *rule_array; - RuleData rule; - char *name; - TimeCode time_code; - - /* All 10 fields must be present. */ - if (data->num_fields != 10) { - fprintf (stderr, "%s:%i: Invalid Rule line - %i fields.\n%s\n", - data->filename, data->line_number, data->num_fields, - data->line); - exit (1); - } - - name = data->fields[RULE_NAME]; - - /* Create the GArray and add it to the hash table if it doesn't already - exist. */ - rule_array = g_hash_table_lookup (data->rule_data, name); - if (!rule_array) { - rule_array = g_array_new (FALSE, FALSE, sizeof (RuleData)); - g_hash_table_insert (data->rule_data, g_strdup (name), rule_array); - } - - rule.from_year = parse_year (data, data->fields[RULE_FROM], FALSE, 0); - if (rule.from_year == YEAR_MAXIMUM) { - fprintf (stderr, "%s:%i: Invalid Rule FROM value: '%s'\n", - data->filename, data->line_number, data->fields[RULE_FROM]); - exit (1); - } - - rule.to_year = parse_year (data, data->fields[RULE_TO], TRUE, - rule.from_year); - if (rule.to_year == YEAR_MINIMUM) { - fprintf (stderr, "%s:%i: Invalid Rule TO value: %s\n", - data->filename, data->line_number, data->fields[RULE_TO]); - exit (1); - } - - if (!strcmp (data->fields[RULE_TYPE], "-")) - rule.type = NULL; - else { - printf ("Type: %s\n", data->fields[RULE_TYPE]); - rule.type = g_strdup (data->fields[RULE_TYPE]); - } - - rule.in_month = parse_month (data, data->fields[RULE_IN]); - rule.on_day_code = parse_day (data, data->fields[RULE_ON], - &rule.on_day_number, &rule.on_day_weekday); - rule.at_time_seconds = parse_time (data, data->fields[RULE_AT], - &rule.at_time_code); - rule.save_seconds = parse_time (data, data->fields[RULE_SAVE], &time_code); - - if (!strcmp (data->fields[RULE_LETTER_S], "-")) { - rule.letter_s = NULL; - } else { - rule.letter_s = g_strdup (data->fields[RULE_LETTER_S]); - } - - rule.is_shallow_copy = FALSE; - - g_array_append_val (rule_array, rule); -} - - -static void -parse_link_line (ParsingData *data) -{ - char *from, *to, *old_from; - GList *zone_list; - - /* We must have 3 fields for a Link. */ - if (data->num_fields != 3) { - fprintf (stderr, "%s:%i: Invalid Rule line - %i fields.\n%s\n", - data->filename, data->line_number, data->num_fields, - data->line); - exit (1); - } - - from = data->fields[LINK_FROM]; - to = data->fields[LINK_TO]; - -#if 0 - printf ("LINK FROM: %s\tTO: %s\n", from, to); -#endif - - if (g_hash_table_lookup_extended (data->link_data, from, - (gpointer) &old_from, - (gpointer) &zone_list)) { - from = old_from; - } else { - from = g_strdup (from); - zone_list = NULL; - } - - zone_list = g_list_prepend (zone_list, g_strdup (to)); - - g_hash_table_insert (data->link_data, from, zone_list); -} - - -static int -parse_year (ParsingData *data, - char *field, - gboolean accept_only, - int only_value) -{ - int len, year = 0; - char *p; - - if (!field) { - fprintf (stderr, "%s:%i: Missing year.\n%s\n", data->filename, - data->line_number, data->line); - exit (1); - } - - len = strlen (field); - if (accept_only && !strncmp (field, "only", len)) - return only_value; - if (len >= 2) { - if (!strncmp (field, "maximum", len)) - return YEAR_MAXIMUM; - else if (!strncmp (field, "minimum", len)) - return YEAR_MINIMUM; - } - - for (p = field; *p; p++) { - if (*p < '0' || *p > '9') { - fprintf (stderr, "%s:%i: Invalid year: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); - } - - year = year * 10 + *p - '0'; - } - - if (year < 1000 || year > 2037) { - fprintf (stderr, "%s:%i: Strange year: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); - } - - return year; -} - - -/* Parses a month name, returning 0 (Jan) to 11 (Dec). */ -static int -parse_month (ParsingData *data, - char *field) -{ - static char* months[] = { "january", "february", "march", "april", "may", - "june", "july", "august", "september", "october", - "november", "december" }; - char *p; - int len, i; - - /* If the field is missing, it must be the optional UNTIL month, so we return - 0 for January. */ - if (!field) - return 0; - - for (p = field, len = 0; *p; p++, len++) { - *p = tolower (*p); - } - - for (i = 0; i < 12; i++) { - if (!strncmp (field, months[i], len)) - return i; - } - - fprintf (stderr, "%s:%i: Invalid month: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); -} - - -/* Parses a day specifier, returning a code representing the type of match - together with a day of the month and a weekday number (0=Sun). */ -static DayCode -parse_day (ParsingData *data, - char *field, - int *day, - int *weekday) -{ - char *day_part, *p; - DayCode day_code; - - if (!field) { - *day = 1; - return DAY_SIMPLE; - } - - *day = *weekday = 0; - - if (!strncmp (field, "last", 4)) { - *weekday = parse_weekday (data, field + 4); - /* We set the day to the end of the month to make sorting Rules easy. */ - *day = 31; - return DAY_LAST_WEEKDAY; - } - - day_part = field; - day_code = DAY_SIMPLE; - - for (p = field; *p; p++) { - if (*p == '<' || *p == '>') { - if (*(p + 1) == '=') { - day_code = (*p == '<') ? DAY_WEEKDAY_ON_OR_BEFORE - : DAY_WEEKDAY_ON_OR_AFTER; - *p = '\0'; - *weekday = parse_weekday (data, field); - day_part = p + 2; - break; - } - - fprintf (stderr, "%s:%i: Invalid day: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); - } - } - - for (p = day_part; *p; p++) { - if (*p < '0' || *p > '9') { - fprintf (stderr, "%s:%i: Invalid day: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); - } - - *day = *day * 10 + *p - '0'; - } - - if (*day < 1 || *day > 31) { - fprintf (stderr, "%s:%i: Invalid day: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); - } - - return day_code; -} - - -/* Parses a weekday name, returning 0 (Sun) to 6 (Sat). */ -static int -parse_weekday (ParsingData *data, - char *field) -{ - static char* weekdays[] = { "sunday", "monday", "tuesday", "wednesday", - "thursday", "friday", "saturday" }; - char *p; - int len, i; - - for (p = field, len = 0; *p; p++, len++) { - *p = tolower (*p); - } - - for (i = 0; i < 7; i++) { - if (!strncmp (field, weekdays[i], len)) - return i; - } - - fprintf (stderr, "%s:%i: Invalid weekday: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); -} - - -/* Parses a time (hour + minute + second) and returns the result in seconds, - together with a time code specifying whether it is Wall clock time, - local standard time, or universal time. - The time can start with a '-' in which case it will be negative. */ -static int -parse_time (ParsingData *data, - char *field, - TimeCode *time_code) -{ - char *p; - int hours = 0, minutes = 0, seconds = 0, result, negative = 0; - - if (!field) { - *time_code = TIME_WALL; - return 0; - } - - p = field; - if (*p == '-') { - p++; - negative = 1; - } - - hours = parse_number (data, &p); - - if (*p == ':') { - p++; - minutes = parse_number (data, &p); - - if (*p == ':') { - p++; - seconds = parse_number (data, &p); - } - } - - if (hours < 0 || hours > 24 - || minutes < 0 || minutes > 59 - || seconds < 0 || seconds > 59 - || (hours == 24 && (minutes != 0 || seconds != 0))) { - fprintf (stderr, "%s:%i: Invalid time: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); - } - - if (hours == 24) { - hours = 23; - minutes = 59; - seconds = 59; - } - -#if 0 - printf ("Time: %s -> %i:%02i:%02i\n", field, hours, minutes, seconds); -#endif - - result = hours * 3600 + minutes * 60 + seconds; - if (negative) - result = -result; - - if (*p == '\0') { - *time_code = TIME_WALL; - return result; - } - - if (*(p + 1) == '\0') { - if (*p == 'w') { - *time_code = TIME_WALL; - return result; - } else if (*p == 's') { - *time_code = TIME_STANDARD; - return result; - } else if (*p == 'u' || *p == 'g' || *p == 'z') { - *time_code = TIME_UNIVERSAL; - return result; - } - } - - fprintf (stderr, "%s:%i: Invalid time: %s\n%s\n", data->filename, - data->line_number, field, data->line); - exit (1); -} - - -/* Parses a simple number and returns the result. The pointer argument - is moved to the first character after the number. */ -static int -parse_number (ParsingData *data, - char **num) -{ - char *p; - int result; - - p = *num; - -#if 0 - printf ("In parse_number p:%s\n", p); -#endif - - if (*p < '0' || *p > '9') { - fprintf (stderr, "%s:%i: Invalid number: %s\n%s\n", data->filename, - data->line_number, *num, data->line); - exit (1); - } - - result = *p++ - '0'; - - while (*p >= '0' && *p <= '9') - result = result * 10 + *p++ - '0'; - - *num = p; - return result; -} - - -static int -parse_rules_save (ParsingData *data, - char *field, - char **rules) -{ - TimeCode time_code; - - *rules = NULL; - - /* Check for just "-". */ - if (field[0] == '-' && field[1] == '\0') - return 0; - - /* Check for a time to add to local standard time. We don't care about a - time code here, since it is just an offset. */ - if (*field == '-' || (*field >= '0' && *field <= '9')) - return parse_time (data, field, &time_code); - - /* It must be a rules name. */ - *rules = g_strdup (field); - return 0; -} - - - - - -GHashTable* -parse_zone_tab (char *filename) -{ - GHashTable *zones_hash; - ZoneDescription *zone_desc; - FILE *fp; - char buf[4096]; - gchar **fields, *zone_name, *latitude, *longitude, *p; - - - fp = fopen (filename, "r"); - if (!fp) { - fprintf (stderr, "Couldn't open file: %s\n", filename); - exit (1); - } - - zones_hash = g_hash_table_new (g_str_hash, g_str_equal); - - while (fgets (buf, sizeof(buf), fp)) { - if (*buf == '#') continue; - - g_strchomp (buf); - fields = g_strsplit (buf,"\t", 4); - - if (strlen (fields[0]) != 2) { - fprintf (stderr, "Invalid zone description line: %s\n", buf); - exit (1); - } - - zone_name = g_strdup (fields[2]); - - zone_desc = g_new (ZoneDescription, 1); - zone_desc->country_code[0] = fields[0][0]; - zone_desc->country_code[1] = fields[0][1]; - zone_desc->comment = (fields[3] && fields[3][0]) ? g_strdup (fields[3]) - : NULL; - - /* Now parse the latitude and longitude. */ - latitude = fields[1]; - longitude = latitude + 1; - while (*longitude != '+' && *longitude != '-') - longitude++; - - parse_coord (latitude, longitude - latitude, zone_desc->latitude); - parse_coord (longitude, strlen (longitude), zone_desc->longitude); - - g_hash_table_insert (zones_hash, zone_name, zone_desc); - -#if 0 - g_print ("Found zone: %s %i %02i %02i,%i %02i %02i\n", zone_name, - zone_desc->latitude[0], zone_desc->latitude[1], - zone_desc->latitude[2], - zone_desc->longitude[0], zone_desc->longitude[1], - zone_desc->longitude[2]); -#endif - } - - fclose (fp); - - return zones_hash; -} - - -static void -parse_coord (char *coord, - int len, - int *result) -{ - int degrees = 0, minutes = 0, seconds = 0; - - if (len == 5) - sscanf (coord + 1, "%2d%2d", °rees, &minutes); - else if (len == 6) - sscanf (coord + 1, "%3d%2d", °rees, &minutes); - else if (len == 7) - sscanf (coord + 1, "%2d%2d%2d", °rees, &minutes, &seconds); - else if (len == 8) - sscanf (coord + 1, "%3d%2d%2d", °rees, &minutes, &seconds); - else { - fprintf (stderr, "Invalid coordinate: %s\n", coord); - exit (1); - } - - if (coord[0] == '-') - degrees = -degrees; - - result[0] = degrees; - result[1] = minutes; - result[2] = seconds; -} - diff --git a/libkcal/libical/vzic-1.3/vzic-parse.h b/libkcal/libical/vzic-1.3/vzic-parse.h deleted file mode 100644 index c6d7c1be7..000000000 --- a/libkcal/libical/vzic-1.3/vzic-parse.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _VZIC_PARSE_H_ -#define _VZIC_PARSE_H_ - -#include <glib.h> - -void parse_olson_file (char *filename, - GArray **zone_data, - GHashTable **rule_data, - GHashTable **link_data, - int *max_until_year); - -GHashTable* parse_zone_tab (char *filename); - -#endif /* _VZIC_PARSE_H_ */ diff --git a/libkcal/libical/vzic-1.3/vzic-test.pl b/libkcal/libical/vzic-1.3/vzic-test.pl deleted file mode 100755 index 0bf20ea7f..000000000 --- a/libkcal/libical/vzic-1.3/vzic-test.pl +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/perl -w - -# -# Vzic - a program to convert Olson timezone database files into VZTIMEZONE -# files compatible with the iCalendar specification (RFC2445). -# -# Copyright (C) 2001 Ximian, Inc. -# Copyright (C) 2003 Damon Chaplin. -# -# Author: Damon Chaplin <damon@gnome.org> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -# -# This outputs an iCalendar file containing one event in each timezone, -# as well as all the VTIMEZONEs. We use it for testing compatability with -# other iCalendar apps like Outlook, by trying to import it there. -# -# Currently we have 377 timezones (with tzdata2001d). -# - -# Set this to the toplevel directory of the VTIMEZONE files. -$ZONEINFO_DIR = "/home/damon/src/zoneinfo"; - -$output_file = "calendar.ics"; - - -# Save this so we can restore it later. -$input_record_separator = $/; - -chdir $ZONEINFO_DIR - || die "Can't cd to $ZONEINFO_DIR"; - -# Create the output file, to contain all the VEVENTs & VTIMEZONEs. -open (OUTPUTFILE, ">$output_file") - || die "Can't create file: $output_file"; - -# Output the standard header. - print OUTPUTFILE <<EOF; -BEGIN:VCALENDAR -PRODID:-//Ximian//NONSGML Vzic Test//EN -VERSION:2.0 -METHOD:PUBLISH -EOF - -$zone_num = 0; - -# 365 days in a non-leap year. -@days_in_month = ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); - -foreach $file (`find -name "*.ics"`) { - # Get rid of './' at start and whitespace at end. - $file =~ s/^\.\///; - $file =~ s/\s+$//; - - if ($file eq $output_file) { - next; - } - -# print "File: $file\n"; - - # Get the VTIMEZONE data. - open (ZONEFILE, "$file") - || die "Can't open file: $ZONEINFO_DIR/$file"; - undef $/; - $vtimezone = <ZONEFILE>; - $/ = $input_record_separator; - close (ZONEFILE); - - # Strip the stuff before and after the VTIMEZONE component - $vtimezone =~ s/^.*BEGIN:VTIMEZONE/BEGIN:VTIMEZONE/s; - $vtimezone =~ s/END:VTIMEZONE.*$/END:VTIMEZONE\n/s; - - print OUTPUTFILE $vtimezone; - - # Find the TZID. - $vtimezone =~ m/TZID:(.*)/; - $tzid = $1; -# print "TZID: $tzid\n"; - - # Find the location. - $file =~ m/(.*)\.ics/; - $location = $1; -# print "LOCATION: $location\n"; - - # Try to find the current UTC offset that Outlook will use. - # If there is an RRULE, we look for the first 2 TZOFFSETTO properties, - # else we just get the first one. - if ($vtimezone =~ m/RRULE/) { - $vtimezone =~ m/TZOFFSETTO:([+-]?\d+)/; - $tzoffsetto = $1; - $vtimezone =~ m/TZOFFSETFROM:([+-]?\d+)/; - $tzoffsetfrom = $1; - $tzoffset = "$tzoffsetfrom/$tzoffsetto"; - } else { - $vtimezone =~ m/TZOFFSETTO:([+-]?\d+)/s; - $tzoffset = $1; - } -# print "TZOFFSET: $tzoffset\n"; - - # We put each event on a separate day in 2001 and Jan 2002. - $day_num = $zone_num; - if ($day_num >= 365) { - $year = 2002; - $day_num -= 365; - } else { - $year = 2001; - } - $month = -1; - for ($i = 0; $i < 12; $i++) { - if ($day_num < $days_in_month[$i]) { - $month = $i; - last; - } - $day_num -= $days_in_month[$i] - } - if ($month == -1) { - die "month = -1"; - } - - $month++; - $day_num++; - $date = sprintf ("%i%02i%02i", $year, $month, $day_num); -# print "Date: $date\n"; - - # Output a VEVENT using the timezone. - print OUTPUTFILE <<EOF; -BEGIN:VEVENT -UID:vzic-test-${zone_num} -DTSTAMP:20010101T000000Z -DTSTART;TZID=${tzid}:${date}T120000 -DTEND;TZID=${tzid}:${date}T130000 -RRULE:FREQ=MONTHLY;BYMONTHDAY=${day_num} -SUMMARY:($tzoffset) ${location} 12:00-13:00 UTC -SEQUENCE:1 -END:VEVENT -EOF - - $zone_num++; - - # Use this to stop after a certain number. -# last if ($zone_num == 100); -} - -# Output the standard footer. - print OUTPUTFILE <<EOF; -END:VCALENDAR -EOF - -close (OUTPUTFILE); - diff --git a/libkcal/libical/vzic-1.3/vzic.c b/libkcal/libical/vzic-1.3/vzic.c deleted file mode 100644 index 41bfa3b4e..000000000 --- a/libkcal/libical/vzic-1.3/vzic.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include <stdio.h> -#include <string.h> - -#include "vzic.h" -#include "vzic-parse.h" -#include "vzic-dump.h" -#include "vzic-output.h" - - -/* - * Global command-line options. - */ - -/* By default we output Outlook-compatible output. If --pure is used we - output pure output, with no changes to be compatible with Outlook. */ -gboolean VzicPureOutput = FALSE; - -gboolean VzicDumpOutput = FALSE; -gboolean VzicDumpChanges = FALSE; -gboolean VzicDumpZoneNamesAndCoords = TRUE; -gboolean VzicDumpZoneTranslatableStrings= TRUE; -gboolean VzicNoRRules = FALSE; -gboolean VzicNoRDates = FALSE; -char* VzicOutputDir = "zoneinfo"; -char* VzicUrlPrefix = NULL; -char* VzicOlsonDir = OLSON_DIR; - -GList* VzicTimeZoneNames = NULL; - -static void convert_olson_file (char *olson_file); - -static void usage (void); - -static void free_zone_data (GArray *zone_data); -static void free_rule_array (gpointer key, - gpointer value, - gpointer data); -static void free_link_data (gpointer key, - gpointer value, - gpointer data); - - -int -main (int argc, - char *argv[]) -{ - int i; - char directory[PATHNAME_BUFFER_SIZE]; - char filename[PATHNAME_BUFFER_SIZE]; - GHashTable *zones_hash; - - /* - * Command-Line Option Parsing. - */ - for (i = 1; i < argc; i++) { - /* - * User Options. - */ - - /* --pure: Output the perfect VCALENDAR data, which Outlook won't parse - as it has problems with certain iCalendar constructs. */ - if (!strcmp (argv[i], "--pure")) - VzicPureOutput = TRUE; - - /* --output-dir: specify where to output all the files beneath. The - default is the current directory. */ - else if (argc > i + 1 && !strcmp (argv[i], "--output-dir")) - VzicOutputDir = argv[++i]; - - /* --url-prefix: Used as the base for the TZURL property in each - VTIMEZONE. The default is to not output TZURL properties. */ - else if (argc > i + 1 && !strcmp (argv[i], "--url-prefix")) { - int length; - VzicUrlPrefix = argv[++i]; - /* remove the trailing '/' if there is one */ - length = strlen (VzicUrlPrefix); - if (VzicUrlPrefix[length - 1] == '/') - VzicUrlPrefix[length - 1] = '\0'; - } - - else if (argc > i + 1 && !strcmp (argv[i], "--olson-dir")) { - VzicOlsonDir = argv[++i]; - } - - /* - * Debugging Options. - */ - - /* --dump: Dump the Rule and Zone data that we parsed from the Olson - timezone files. This is used to test the parsing code. */ - else if (!strcmp (argv[i], "--dump")) - VzicDumpOutput = TRUE; - - /* --dump-changes: Dumps a list of times when each timezone changed, - and the new local time offset from UTC. */ - else if (!strcmp (argv[i], "--dump-changes")) - VzicDumpChanges = TRUE; - - /* --no-rrules: Don't output RRULE properties in the VTIMEZONEs. Instead - it will just output RDATEs for each year up to a certain year. */ - else if (!strcmp (argv[i], "--no-rrules")) - VzicNoRRules = TRUE; - - /* --no-rdates: Don't output multiple RDATEs in a single VTIMEZONE - component. Instead they will be output separately. */ - else if (!strcmp (argv[i], "--no-rdates")) - VzicNoRDates = TRUE; - - else - usage (); - } - - /* - * Create any necessary directories. - */ - ensure_directory_exists (VzicOutputDir); - - if (VzicDumpOutput) { - /* Create the directories for the dump output, if they don't exist. */ - sprintf (directory, "%s/ZonesVzic", VzicOutputDir); - ensure_directory_exists (directory); - sprintf (directory, "%s/RulesVzic", VzicOutputDir); - ensure_directory_exists (directory); - } - - if (VzicDumpChanges) { - /* Create the directory for the changes output, if it doesn't exist. */ - sprintf (directory, "%s/ChangesVzic", VzicOutputDir); - ensure_directory_exists (directory); - } - - /* - * Convert the Olson timezone files. - */ - convert_olson_file ("africa"); - convert_olson_file ("antarctica"); - convert_olson_file ("asia"); - convert_olson_file ("australasia"); - convert_olson_file ("europe"); - convert_olson_file ("northamerica"); - convert_olson_file ("southamerica"); - - /* These are backwards-compatability and weird stuff. */ -#if 0 - convert_olson_file ("backward"); - convert_olson_file ("etcetera"); - convert_olson_file ("leapseconds"); - convert_olson_file ("pacificnew"); - convert_olson_file ("solar87"); - convert_olson_file ("solar88"); - convert_olson_file ("solar89"); -#endif - - /* This doesn't really do anything and it messes up vzic-dump.pl so we - don't bother. */ -#if 0 - convert_olson_file ("factory"); -#endif - - /* This is old System V stuff, which we don't currently support since it - uses 'min' as a Rule FROM value which messes up our algorithm, making - it too slow and use too much memory. */ -#if 0 - convert_olson_file ("systemv"); -#endif - - /* Output the timezone names and coordinates in a zone.tab file, and - the translatable strings to feed to gettext. */ - if (VzicDumpZoneNamesAndCoords) { - sprintf (filename, "%s/zone.tab", VzicOlsonDir); - zones_hash = parse_zone_tab (filename); - - dump_time_zone_names (VzicTimeZoneNames, VzicOutputDir, zones_hash); - } - - return 0; -} - - -static void -convert_olson_file (char *olson_file) -{ - char input_filename[PATHNAME_BUFFER_SIZE]; - GArray *zone_data; - GHashTable *rule_data, *link_data; - char dump_filename[PATHNAME_BUFFER_SIZE]; - ZoneData *zone; - int i, max_until_year; - - sprintf (input_filename, "%s/%s", VzicOlsonDir, olson_file); - - parse_olson_file (input_filename, &zone_data, &rule_data, &link_data, - &max_until_year); - - if (VzicDumpOutput) { - sprintf (dump_filename, "%s/ZonesVzic/%s", VzicOutputDir, olson_file); - dump_zone_data (zone_data, dump_filename); - - sprintf (dump_filename, "%s/RulesVzic/%s", VzicOutputDir, olson_file); - dump_rule_data (rule_data, dump_filename); - } - - output_vtimezone_files (VzicOutputDir, zone_data, rule_data, link_data, - max_until_year); - - free_zone_data (zone_data); - g_hash_table_foreach (rule_data, free_rule_array, NULL); - g_hash_table_destroy (rule_data); - g_hash_table_foreach (link_data, free_link_data, NULL); - g_hash_table_destroy (link_data); -} - - -static void -usage (void) -{ - fprintf (stderr, "Usage: vzic [--dump] [--dump-changes] [--no-rrules] [--no-rdates] [--pure] [--output-dir <directory>] [--url-prefix <url>] [--olson-dir <directory>]\n"); - - exit (1); -} - - - - -/* - * Functions to free the data structures. - */ - -static void -free_zone_data (GArray *zone_data) -{ - ZoneData *zone; - ZoneLineData *zone_line; - int i, j; - - for (i = 0; i < zone_data->len; i++) { - zone = &g_array_index (zone_data, ZoneData, i); - - g_free (zone->zone_name); - - for (j = 0; j < zone->zone_line_data->len; j++) { - zone_line = &g_array_index (zone->zone_line_data, ZoneLineData, j); - - g_free (zone_line->rules); - g_free (zone_line->format); - } - - g_array_free (zone->zone_line_data, TRUE); - } - - g_array_free (zone_data, TRUE); -} - - -static void -free_rule_array (gpointer key, - gpointer value, - gpointer data) -{ - char *name = key; - GArray *rule_array = value; - RuleData *rule; - int i; - - for (i = 0; i < rule_array->len; i++) { - rule = &g_array_index (rule_array, RuleData, i); - - if (!rule->is_shallow_copy) { - g_free (rule->type); - g_free (rule->letter_s); - } - } - - g_array_free (rule_array, TRUE); - - g_free (name); -} - - -static void -free_link_data (gpointer key, - gpointer value, - gpointer data) -{ - GList *link = data; - - g_free (key); - - while (link) { - g_free (link->data); - link = link->next; - } - - g_list_free (data); -} - diff --git a/libkcal/libical/vzic-1.3/vzic.h b/libkcal/libical/vzic-1.3/vzic.h deleted file mode 100644 index 3d0daf893..000000000 --- a/libkcal/libical/vzic-1.3/vzic.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Vzic - a program to convert Olson timezone database files into VZTIMEZONE - * files compatible with the iCalendar specification (RFC2445). - * - * Copyright (C) 2000-2001 Ximian, Inc. - * Copyright (C) 2003 Damon Chaplin. - * - * Author: Damon Chaplin <damon@gnome.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _VZIC_H_ -#define _VZIC_H_ - -#include <glib.h> - - -/* - * Global command-line options. - */ - -/* By default we output Outlook-compatible output. If --pure is used we output - pure output, with no changes to be compatible with Outlook. */ -extern gboolean VzicPureOutput; - -extern gboolean VzicDumpOutput; -extern gboolean VzicDumpChanges; -extern gboolean VzicDumpZoneNamesAndCoords; -extern gboolean VzicDumpZoneTranslatableStrings; -extern gboolean VzicNoRRules; -extern gboolean VzicNoRDates; -extern char* VzicUrlPrefix; - -extern GList* VzicTimeZoneNames; - -/* The minimum & maximum years we can use. */ -#define YEAR_MINIMUM G_MININT -#define YEAR_MAXIMUM G_MAXINT - -/* The maximum size of any complete pathname. */ -#define PATHNAME_BUFFER_SIZE 1024 - -/* Days can be expressed either as a simple month day number, 1-31, or a rule - such as the last Sunday, or the first Monday on or after the 8th. */ -typedef enum -{ - DAY_SIMPLE, - DAY_WEEKDAY_ON_OR_AFTER, - DAY_WEEKDAY_ON_OR_BEFORE, - DAY_LAST_WEEKDAY -} DayCode; - - -/* Times can be given either as universal time (UTC), local standard time - (without daylight-saving adjustments) or wall clock time (local standard - time plus daylight-saving adjustments, i.e. what you would see on a clock - on the wall!). */ -typedef enum -{ - TIME_WALL, - TIME_STANDARD, - TIME_UNIVERSAL -} TimeCode; - - -/* This represents one timezone, e.g. "Africa/Algiers". - It contains the timezone name, and an array of ZoneLineData structs which - hold data from each Zone line, including the continuation lines. */ -typedef struct _ZoneData ZoneData; -struct _ZoneData -{ - char *zone_name; - - /* An array of ZoneLineData, one for each Zone & Zone continuation line - read in. */ - GArray *zone_line_data; -}; - - -typedef struct _ZoneLineData ZoneLineData; -struct _ZoneLineData -{ - /* The amount of time to add to UTC to get local standard time for the - current time range, in seconds. */ - int stdoff_seconds; - - /* Either rules is set to the name of a set of rules, or rules is NULL and - save is set to the time to add to local standard time to get wall time, in - seconds. If save is 0 as well, then standard time always applies. */ - char *rules; - int save_seconds; - - /* The format to use for the abbreviated timezone name, e.g. WE%sT. - The %s is replaced by variable part of the name. (See the letter_s field - in the RuleData struct below). */ - char *format; - - /* TRUE if an UNTIL time is given. */ - gboolean until_set; - - /* The UNTIL year, e.g. 2000. */ - int until_year; - - /* The UNTIL month 0 (Jan) to 11 (Dec). */ - int until_month; - - /* The UNTIL day, either a simple month day number, 1-31, or a rule such as - the last Sunday, or the first Monday on or after the 8th. */ - DayCode until_day_code; - int until_day_number; /* 1 to 31. */ - int until_day_weekday; /* 0 (Sun) to 6 (Sat). */ - - /* The UNTIL time, in seconds from midnight. The code specifies whether the - time is a wall clock time, local standard time, or universal time. */ - int until_time_seconds; - TimeCode until_time_code; -}; - - -typedef struct _RuleData RuleData; -struct _RuleData -{ - /* The first year that the rule applies to, e.g. 1996. - Can also be YEAR_MINIMUM. */ - int from_year; - - /* The last year that the rule applies to, e.g. 1996. - Can also be YEAR_MAXIMUM. */ - int to_year; - - /* A string used to only match certain years between from and to. - The rule only applies to the years which match. If type is NULL the rule - applies to all years betweeen from and to. - zic uses an external program called yearistype to check the string. - Currently it is not used in the Olson database. */ - char *type; - - /* The month of the rule 0 (Jan) to 11 (Dec). */ - int in_month; - - /* The day, either a simple month day number, 1-31, or a rule such as - the last Sunday, or the first Monday on or after the 8th. */ - DayCode on_day_code; - int on_day_number; - int on_day_weekday; /* 0 (Sun) to 6 (Sat). */ - - /* The time, in seconds from midnight. The code specifies whether the - time is a wall clock time, local standard time, or universal time. */ - int at_time_seconds; - TimeCode at_time_code; - - /* The amount of time to add to local standard time when the rule is in - effect, in seconds. If this is not 0 then it must be a daylight-saving - time. */ - int save_seconds; - - /* The letter(s) to use as the variable part in the abbreviated timezone - name. If this is NULL then no variable part is used. (See the format field - in the ZoneLineData struct above.) */ - char *letter_s; - - - /* This is set to TRUE if this element is a shallow copy of another one, - in which case we don't free any of the fields. */ - gboolean is_shallow_copy; -}; - - -typedef struct _ZoneDescription ZoneDescription; -struct _ZoneDescription -{ - /* 2-letter ISO 3166 country code. */ - char country_code[2]; - - /* latitude and longitude in degrees, minutes & seconds. The degrees value - holds the sign of the entire latitude/longitude. */ - int latitude[3]; - int longitude[3]; - - char *comment; -}; - -#endif /* _VZIC_H_ */ |