"Fossies" - the Fresh Open Source Software Archive

Member "remind-03.03.09/contrib/rem2ics-0.93/rem2ics" (15 Oct 2021, 33023 Bytes) of package /linux/misc/remind-03.03.09.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/usr/bin/perl -w
    2 
    3 # rem2ics -- convert the output of "remind -s" into RFC2445 iCalendar format.
    4 
    5 # Copyright 2007,2008,2009
    6 #  Mark Atwood <me@mark.atwood.name>
    7 #  Paul Hinze <paul dot t dot hinze at gmail dot com>
    8 #  Michael Schultz <mjschultz at gmail dot com>
    9 # 
   10 # This program is free software; you can redistribute it and/or
   11 # modify it under the terms of the GNU General Public License
   12 # as published by the Free Software Foundation; either version 2
   13 # of the License, or (at your option) any later version.
   14 # 
   15 # This program is distributed in the hope that it will be useful,
   16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18 # GNU General Public License for more details.
   19 # 
   20 # You should have received a copy of the GNU General Public License
   21 # along with this program; if not, write to the
   22 #   Free Software Foundation, Inc.
   23 #   51 Franklin Street, Fifth Floor
   24 #   Boston MA  02110-1301 USA
   25 
   26 use strict;
   27 use warnings;
   28 
   29 =head1 NAME
   30 
   31 rem2ics - convert the output of "remind -s" into RFC2445 iCalendar format.
   32 
   33 =head1 SYNOPSIS
   34 
   35 TZ=I<timezone> B<rem2ics> [B<-man>] [B<-do>] [B<-norecur>] [B<-usetag>] E<lt>input E<gt>output
   36 
   37 =head1 OPTIONS AND ARGUMENTS
   38 
   39 =over 8
   40 
   41 =item B<-man>
   42 
   43 Print the manual page and exit.
   44 
   45 =item B<-do>
   46 
   47 Actually do the conversion.  Otherwise just print a brief help message
   48 and usage example, and then exit.
   49 
   50 =item B<-norecur>
   51 
   52 Do not attempt to detect and fold together recurring events.
   53 
   54 =item B<-usetag>
   55 
   56 Generate UIDs using remind TAG clauses.
   57 
   58 =back
   59 
   60 Input is from standard input
   61 
   62 Output is to standard output.
   63 
   64 =head1 USAGE
   65 
   66   remind -s360 -irem2ics=1 ~/.reminders 1 Jan 1991 | TZ=PST8PDT rem2ics -do >reminders.ics
   67 
   68 This tells B<remind> to use ~/.reminders, and to process the entire
   69 range of dates it can handle (from Jan 1 1991 to Dec 31 2020), and to
   70 define a variable named C<rem2ics>, which can be used in
   71 C<IF !defined("rem2ics")> / C<ENDIF> pairs.
   72 B<rem2ics> will use a timezone of PST8PDT, and will fold events that
   73 have the same name and duration into a single iCalendar VEVENT object.
   74 
   75 =head1 NOTES
   76 
   77 =head2 Timezones and the TZ environment variable.
   78 
   79 B<rem2ics> uses the TZ environment variable to determine the value of
   80 the RFC2445 TZID property.  If you are running on a Linux or other GNU
   81 libc based system, you probably don't (and probably shouldn't)
   82 normally have TZ set.  You can confirm this by running C<printenv TZ>
   83 at a shell prompt.  If your remind data is in your "local time", and
   84 it probably is, you should probably set TZ to a good name for your
   85 local timezone just for the run of this script.  You probably should
   86 NOT set TZ in your login scripts.
   87 
   88 You can use TZ like this:
   89 
   90   remind -s ~/.reminders | TZ=PST8PDT rem2ics -do >reminders.ics
   91 
   92 or
   93 
   94   remind -s ~/.reminders | TZ=US/Pacific rem2ics -do >reminders.ics
   95 
   96 
   97 If, for some reason, your remind files are all in GMT instead of
   98 localtime (you smart person you!), you can do this:
   99 
  100   remind -s ~/.reminders | TZ=GMT rem2ics -do >reminders.ics
  101 
  102 or
  103 
  104   remind -s ~/.reminders | TZ=0 rem2ics -do >reminders.ics
  105 
  106 and B<rem2ics> will use the ISO8601 "Z" notation for GMT time in the ics
  107 file.  (Other synonyms for GMT are the empty string (not the same as
  108 the TZ not set), "I<0>", "I<Z>", "I<Zulu>", "I<Greenwitch>", "I<GMT>",
  109 "I<GMT+0>, and "I<GMT-0>".)
  110 
  111 If you leave TZ undefined and unset, B<rem2ics> will use the ISO8601
  112 "T" notation date strings with no TZID property, which RFC2445 calls a
  113 "floating time".  Who knows, it might work for you!
  114 
  115 The TZ string value is literally incorporated into the iCalendar
  116 stream, so whatever your iCalendar-using application needs is what you
  117 should use.  You may have to experiment a bit.
  118 
  119 You can look around in C</usr/share/zoneinfo> to get the names of
  120 every timezone anywhere.  This is the "Olson database" that RFC2445
  121 refers to.  Read the man page for L<tzfile(5)> for more than you ever
  122 wanted to know about the format of these files, and about GNU libc's
  123 handling of timezones.  As complex as it is, it's certainly better
  124 than what POSIX defines or what most legacy UNIX systems do, and most
  125 certainly better than Microsoft, who in their "cutting edge" "state of
  126 the art" "server" OS, still hasn't figured out that daylight time
  127 rules might be different in different years.
  128 
  129 If you just ran B<rem2ics> without reading all this stuff, or if you
  130 don't want to worry about it at all, and somehow your iCalendar
  131 application manager is able to guess the proper timezone for you, just
  132 leave TZ undefined, and B<rem2ics> will use the ISO8601 "T" notation
  133 date strings with no TZID property, which RFC2445 calls a "floating
  134 time".  Who knows, it might work for you!
  135 
  136 =head2 Detecting recurring events
  137 
  138 B<rem2ics> tries to detect recurring events.  If any multiple events
  139 appear with exactly the text and exactly the same duration (including
  140 "no duration"), instead of multiple VEVENT objects, there will be just
  141 one VEVENT object, that will have a RFC2445 C<RDATE> property.
  142 
  143 B<rem2ics> is not yet smart enough to derive an C<RRULE> based
  144 recurrance.  If you really want that feature, either implement it and
  145 send in a patch, or contact the author and convince him to do it.
  146 
  147 =head2 Other iCalendar Properties
  148 
  149 B<rem2ics> does not generate C<DESCRIPTION> or C<LOCATION>.  One
  150 would have to heuristically parse them out of the text, and everyone
  151 uses a idiosyncratic way of putting things in B<remind>.
  152 
  153 If the B<-usetag> option is not used or no C<TAG> is set for a
  154 reminder, B<rem2ics> will synthesize C<UID> properties for each
  155 VEVENT, but the UIDs will be different (and unique) for each run of
  156 B<rem2ics>.  If you run rem2ics twice and import the two resulting ICS
  157 streams into your new scheduling program, your appointments will
  158 appear twice.  If, however, you have set C<TAG> clauses in your
  159 reminders and activated B<-usetag>, these will be used.  The same
  160 applies for tags synthesized by B<remind>'s B<-y> option.  Hence, it
  161 is more useful to use the B<-y> option than to let B<rem2ics>
  162 synthesize UIDs, because the UIDs will stay the same across multiple
  163 runs.
  164 
  165 =head2 Other iCalendar Perl objects
  166 
  167 Why does't B<rem2ics> use any of the iCalendar Perl stuff in CPAN?
  168 Because I don't trust them, and they are too big for this app.  One
  169 links to a binary library. Another hasn't been maintained since 1991,
  170 and is full of notes as to how buggy and incomplete it is.  And so
  171 forth.  I am not at this moment interested in groveling around in
  172 L<Net::iCal>, L<DateTime::Format::iCal>, L<Tie::iCal>,
  173 L<iCal::Parser>, or C<libical>.
  174 
  175 =head2 Previous implementation
  176 
  177 There is a working quick & dirty rem2ics written in awk
  178 by Anthony J. Chivetta E<lt>achivetta@gmail.comE<gt>.
  179 
  180 But it has the following problems: it doesn't escape the text, it
  181 doesn't handle events that cross over midnight, it doesn't do
  182 timezones, it doesn't enforce the correct EOL sequence, and it doesn't
  183 fold long lines.  This is a replacement for that script.
  184 
  185 =head1 TODO
  186 
  187  If TZ not set, grab out of system config somewhere
  188  Detect recurring events.
  189   If I'm REALLY smart, derive RRULE
  190  Handle characters not in US-ASCII. Latin1? UTF8?
  191 
  192 =head1 VERSION HISTORY
  193 
  194 =over 8
  195 
  196 =item version 0.1 2007-02-08
  197 
  198 First cut.
  199 
  200 =item version 0.2 2007-02-09
  201 
  202 Reorg into multipass over a data structure.
  203 
  204 =item version 0.3 2007-02-10
  205 
  206 Collapse repeating events. Fold output lines.
  207 
  208 =item version 0.9 2007-02-11
  209 
  210 POD. Command line options. First public release.
  211 
  212 =item version 0.91 2007-02-14
  213 
  214 Bug fix, error message for non-recurring events
  215 
  216 =item version 0.92 2008-01-28
  217 
  218 Bug fix, 
  219  rem2ics 0.91 chokes on timed reminders with
  220  duration using `remind -s` as it functions in remind-03.01.03.
  221  Remind 3.01 changed how the -s data is formated for events that have a duration
  222  Patch by Paul Hinze E<lt>paul dot t dot hinze at gmail dot comE<gt>
  223   and Michael Schultz E<lt>mjschultz at gmail dot comE<gt>
  224 
  225 =item version 0.93 2009-06-25
  226 
  227 Add B<-usetag> option to allow for UIDs to stay the same across multiple runs
  228  by using the remind TAG clause.
  229  Patch by Tim Weber E<lt>scy at scytale dot nameE<gt>
  230 
  231 =back
  232 
  233 =head1 SEE ALSO
  234 
  235 L<http://mark.atwood.name/code/rem2ics>
  236 
  237 L<http://en.wikipedia.org/wiki/ICalendar>
  238 
  239 L<http://tools.ietf.org/html/rfc2445>
  240 
  241 L<https://dianne.skoll.ca/projects/remind/>
  242 
  243 L<remind(1)>
  244 
  245 =head1 AUTHOR
  246 
  247 Copyright 2007,2008,2009 by Mark Atwood E<lt>me+rem2ics@mark.atwood.nameE<gt>. L<http://mark.atwood.name/>.
  248 
  249 Please report bugs (with patches, if possible).
  250 
  251 Inspired by Anthony J. Chivetta E<lt>achivetta@gmail.comE<gt>'s
  252 rem2ics in awk.
  253 
  254 Thank you to Dianne Skoll E<lt>dianne@skoll.ca<gt> for Remind,
  255 and to the IETF calsch wg for the iCalendar specification.
  256 
  257 =cut
  258 
  259 use Getopt::Long;
  260 use Pod::Usage;
  261 
  262 my $app_name = "rem2ics";
  263 my $app_version = "0.93";
  264 
  265 # process the command line
  266 my %options;
  267 GetOptions(\%options, qw(man do norecurr usetag))  ||  pod2usage(2);
  268 pod2usage(-verbose => 2)  if ($options{man});
  269 
  270 unless ($options{do}) {
  271     print STDERR "Run \"$0 -man\" for information and usage examples.\n"
  272     . "Pay special attention to information about timezone.\n";
  273     exit(99);
  274 }
  275 
  276 # grab the hostname
  277 # this is used as part of the UID property of each VEVENT
  278 my $ical_uid_hostname = $ENV{'HOSTNAME'};
  279 unless ($ical_uid_hostname) {
  280     print STDERR "Warning! "
  281     . "The environment variable HOSTNAME was not properly set.\n"
  282     . "Will use \"localhost\" in the RFC2445 UID property\n";
  283     $ical_uid_hostname = "localhost";
  284 }
  285 
  286 # look for the TZ
  287 my $ical_tzid = undef;
  288 if (exists $ENV{'TZ'}) {
  289     $ical_tzid = $ENV{'TZ'};
  290     my %synonyms_for_gmt = (
  291     '' => 1, '0' => 1, 'z' => 1, 'zulu' => 1, 'greenwitch' => 1, 
  292     'gmt' => 1, 'gmt+0' => 1, 'gmt-0' => 1, );
  293     if (exists $synonyms_for_gmt{lc($ical_tzid)}) {
  294     $ical_tzid = '';  # empty means GMT, below
  295     }
  296 } else {
  297     # leave it undefined, that has a meaning below
  298 }
  299 
  300 # RFC2445 DTSTAMP property will be the time we started running ($^T)
  301 my ($ical_dtstamp);
  302 {
  303     my @gt = gmtime($^T);
  304     $ical_dtstamp = sprintf("%04d%02d%02dZ%02d%02d%02dZ",
  305                 1900+$gt[5], $gt[4]+1, $gt[3],
  306                 $gt[2], $gt[1], $gt[0]);
  307 }
  308 
  309 my ($cnt, $v, @events);
  310 
  311 $cnt = 0;
  312 foreach (<STDIN>) {
  313     $cnt++;
  314 
  315     s/#.*//;  # toss comments
  316     next if /^\s*$/;  # skip blank lines
  317     chomp;
  318 
  319     $v = undef;
  320 
  321     # store the raw line
  322     $v->{src} = $_;
  323     $v->{cnt} = $cnt;
  324 
  325     # split and parse the line
  326     #  if we don't like it, skip it and go around again
  327     
  328     # sf[0] = date, in yyyy/mm/dd format
  329     # sf[1] = special, usually "*"
  330     # sf[2] = tag, usually "*"
  331     # sf[3] = duration, in minutes
  332     # sf[4] = time, since midnight, in minutes
  333     # sf[5] = text
  334 
  335     my @sf = split(' ', $_, 6);
  336     next unless ($sf[1] eq '*');  # ignore SPECIAL lines
  337     next unless (($sf[3] eq '*') or ($sf[3] =~ m/\d+/));
  338     next unless (($sf[4] eq '*') or ($sf[4] =~ m/\d+/));
  339     next unless (length($sf[5]) > 0);
  340 
  341     my @dt = split('/', $sf[0], 3);
  342     next unless ($dt[0] =~ m/^\d{4}$/);  # year
  343     next unless ($dt[1] =~ m/^\d{2}$/);  # month
  344     next unless ($dt[2] =~ m/^\d{2}$/);  # day
  345 
  346     if ($sf[4] ne "*") {  # a time was given
  347     # When an event has a time, remind -s "helpfully" also
  348     # puts it as text at the start of the text portion.
  349     # This takes the following form:
  350     #   ##:##[a|p]m <rest of MSG>
  351     # or, if the event has a duration:
  352     #   ##:##[a|p]m-##:##[a|p]m <rest of MSG>
  353     # Rather than a nasty regex, just splitting at the 
  354     # first space does the trick.
  355     my($extra_time, $textmsg) = split(' ', $sf[5], 2);
  356     $sf[5] = $textmsg;
  357     }
  358 
  359     $v->{sf} = \@sf;
  360     $v->{dt} = \@dt;
  361 
  362     push @events, $v;
  363 }
  364 
  365 # generate the "date time string" for each event
  366 foreach $v (@events) {
  367     if (${$v->{sf}}[4] eq "*") {  # no time was given
  368     $v->{dts} = sprintf("%04d%02d%02d", @{$v->{dt}});
  369     } else { # a time was given
  370     my ($t_hr, $t_mn) = &idiv(${$v->{sf}}[4], 60);
  371     $v->{dts} = sprintf("%04d%02d%02dT%02d%02d00",
  372                 @{$v->{dt}}, $t_hr, $t_mn);
  373 
  374     }
  375 }
  376 
  377 my(%grovel);
  378 
  379 # if the user doesnt want recurrance detection
  380 unless ($options{norecurr}) {
  381 
  382     # then dont put events in the grovel hash
  383 
  384     foreach $v (@events) {
  385     # key is duration followed by text
  386     #  \036 is "ASCII RS Record Separator"
  387     my $k = ${$v->{sf}}[3] . "\036" . ${$v->{sf}}[5];
  388     push @{$grovel{$k}}, $v;
  389     }
  390 
  391     foreach my $k (keys %grovel) {
  392     if ((scalar @{$grovel{$k}}) > 1) {
  393         $v = ${$grovel{$k}}[0];
  394         $v->{recurlist} = \@{$grovel{$k}};
  395         foreach my $v0 (@{$grovel{$k}}) {
  396         $v0->{is_recurrance} = $v;
  397         }
  398     }
  399     }
  400 }
  401 
  402 
  403 # All of the individual events are in the @events array.  All of the
  404 # unique combinations of duration/event name are the keys in the
  405 # %grovel hash, the elements of which are references to an arrays of
  406 # references to the events, in the same ordering as they we read by
  407 # us, which *ought* to be in datewise order.  I don't know if "remind
  408 # -s" actually sorts into true chronological order.  If it doesn't, we
  409 # might have a problem if a recurring event has two instances both on
  410 # the first day.
  411 
  412 # Every event that is recurring has a "is_recurrance" property.
  413 # Additionally, (hopefully) the first/earliest event in a set of
  414 # recurrances has a "recurlist" property.  The "recurlist" is a
  415 # reference to a list of references to each of the events.  The first
  416 # one on that list will be the same event that has the "recurlist"
  417 # property.  The "is_recurrance" property is a reference back to the
  418 # event that has the "recurlist" property.
  419 
  420 foreach my $k (keys %grovel) {
  421     next if ((scalar @{$grovel{$k}}) <= 1);
  422 
  423     my $recur_str = "";
  424     foreach $v (@{$grovel{$k}}) {
  425     if (${$v->{sf}}[4] eq "*") {  # no time was given
  426         $recur_str .= ($v->{dts} . ",");
  427     } else {
  428         if (defined($ical_tzid)) {
  429         if ($ical_tzid eq '') {  # tz is defined but empty, so in GMT
  430             $recur_str .= $v->{dts} . "Z,";
  431         } else {  # tz is non-zero, so output the tz as well
  432             $recur_str .= $v->{dts} . ",";
  433         }
  434         } else {  # undefined tz, just floating time
  435         $recur_str .= $v->{dts} . ",";
  436         }
  437     }
  438     }
  439 
  440     # the recur_str now has an extra comma at the end. chop it off
  441     chop($recur_str);
  442     ${$grovel{$k}}[0]->{recur_str} = $recur_str;
  443 }
  444 
  445 foreach my $k (keys %grovel) {
  446     next if ((scalar @{$grovel{$k}}) <= 1);
  447     my $v = ${$grovel{$k}}[0];  # grab the head of each list
  448     if (${$v->{sf}}[4] eq "*") {  # no time was given
  449     # the default value type for an RDATE is DATE-TIME,
  450     # we much change the type to DATE
  451     $v->{i_rdate} = sprintf("RDATE;VALUE=DATE:");
  452     } else {
  453     if (defined($ical_tzid)) {
  454         if ($ical_tzid eq '') {  # tz is defined but empty, so in GMT
  455         $v->{i_rdate} = sprintf("RDATE:");
  456         } else {  # tz is non-zero, so output the tz as well
  457         $v->{i_rdate} = sprintf("RDATE;TZID=%s:", $ical_tzid);
  458         }
  459     } else {  # undefined tz, just floating time
  460         $v->{i_rdate} = sprintf("RDATE:");
  461     }
  462     }
  463     # now stick the recur_str onto the end
  464     $v->{i_rdate} .= $v->{recur_str};
  465     # if we ever get memory tight, we can probably undef($v->{recur_str})
  466 }
  467 
  468 foreach $v (@events) {
  469     # for recurrant events, skip those that arnt the "head"
  470     next if ($v->{is_recurrance} and (not $v->{recurlist}));
  471 
  472     if (${$v->{sf}}[4] eq "*") {  # no time was given
  473     $v->{i_dtstart} = sprintf("DTSTART:%s", $v->{dts});
  474     } else {
  475     if (defined($ical_tzid)) {
  476         if ($ical_tzid eq '') {  # tz is defined but empty, so in GMT
  477         $v->{i_dtstart} = sprintf("DTSTART:%sZ", $v->{dts});
  478         } else {  # tz is non-zero, so output the tz as well
  479         $v->{i_dtstart} = sprintf("DTSTART;TZID=%s:%s",
  480                       $ical_tzid, $v->{dts});
  481         }
  482     } else {  # undefined tz, just floating time
  483         $v->{i_dtstart} = sprintf("DTSTART:%s", $v->{dts});
  484     }
  485     }
  486 
  487     if (${$v->{sf}}[3] ne "*") {  # a duration was given
  488     # It's convienient that RFC2445 defines DURATION, thus we
  489     # don't need to calculate DTEND, with awkward figuring out
  490     # crossing hours, days, months, year, etc.  Instead we
  491     # will let the iCalendar consuming application worry about it.
  492     $v->{i_duration} = sprintf("PT%dM", ${$v->{sf}}[3]);
  493     }
  494 }
  495 
  496 # output header
  497 print "BEGIN:VCALENDAR\015\012"
  498     . "VERSION:2.0\015\012"
  499     . "PRODID:http://mark.atwood.name/code/rem2ics"
  500     . " $app_name $app_version\015\012";
  501 
  502 # output each vevent
  503 foreach $v (@events) {
  504     # for recurrant events, only output the "head", skip the others
  505     next if ($v->{is_recurrance} and (not $v->{recurlist}));
  506 
  507     print "BEGIN:VEVENT\015\012";
  508     my $tag = ${$v->{sf}}[2];
  509     # if $tag is not set, fake up a UID from start time, process id & input line count
  510     if ($tag eq "*" || !$options{usetag}) {
  511         $tag = sprintf("%x.%x.%x", $^T, $$, $v->{cnt});
  512     }
  513     # add rem2ics and hostname to UID
  514     print &lineify(sprintf("UID:rem2ics.%s@%s",
  515                $tag, $ical_uid_hostname));
  516     print &lineify("SUMMARY:" . &quotify(${$v->{sf}}[5]));
  517     print &lineify($v->{i_dtstart});
  518     print &lineify("DURATION:" . $v->{i_duration})
  519     if ($v->{i_duration});
  520     print &lineify($v->{i_rdate})
  521     if ($v->{i_rdate});
  522     print &lineify("DTSTAMP:" . $ical_dtstamp);
  523     print &lineify("COMMENT: generated by $app_name $app_version\\n"
  524            . " http://mark.atwood.name/code/rem2ics\\n"
  525            . " data[" . $v->{cnt} . "]=|" . &quotify($v->{src}) . "|");
  526     print "END:VEVENT\015\012";
  527 }
  528 
  529 # output trailer
  530 print "END:VCALENDAR\015\012";
  531 
  532 
  533 # integer division, return both quotient and remainder
  534 sub idiv {
  535     my $n = shift; my $d = shift;
  536     my $r = $n; my $q = 0;
  537     while ($r >= $d) { 
  538     $r = $r - $d;
  539     $q = $q + 1;
  540     }
  541     return ($q, $r);
  542 }
  543 
  544 # todo, perl5 version that defines ()*, need to specify a requires up top
  545 sub lineify {
  546     return join("\015\012 ", unpack('(A72)*', shift)) . "\015\012";
  547 }
  548 
  549 sub quotify {
  550     my $s = shift;
  551     return $s if $s =~ m/^(\w| )*$/;
  552 
  553     $s =~ s/\\/\\\\/gso;
  554     $s =~ s/\n/\\n/gso;
  555     $s =~ s/\s/ /gso;
  556     $s =~ s/\"/\\"/gso;
  557     $s =~ s/\,/\\,/gso;
  558     $s =~ s/\:/\\:/gso;
  559     $s =~ s/\;/\\;/gso;
  560 
  561     return $s;
  562 }
  563 
  564 __END__
  565 
  566             GNU GENERAL PUBLIC LICENSE
  567                Version 2, June 1991
  568 
  569  Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
  570  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  571  Everyone is permitted to copy and distribute verbatim copies
  572  of this license document, but changing it is not allowed.
  573 
  574                 Preamble
  575 
  576   The licenses for most software are designed to take away your
  577 freedom to share and change it.  By contrast, the GNU General Public
  578 License is intended to guarantee your freedom to share and change free
  579 software--to make sure the software is free for all its users.  This
  580 General Public License applies to most of the Free Software
  581 Foundation's software and to any other program whose authors commit to
  582 using it.  (Some other Free Software Foundation software is covered by
  583 the GNU Lesser General Public License instead.)  You can apply it to
  584 your programs, too.
  585 
  586   When we speak of free software, we are referring to freedom, not
  587 price.  Our General Public Licenses are designed to make sure that you
  588 have the freedom to distribute copies of free software (and charge for
  589 this service if you wish), that you receive source code or can get it
  590 if you want it, that you can change the software or use pieces of it
  591 in new free programs; and that you know you can do these things.
  592 
  593   To protect your rights, we need to make restrictions that forbid
  594 anyone to deny you these rights or to ask you to surrender the rights.
  595 These restrictions translate to certain responsibilities for you if you
  596 distribute copies of the software, or if you modify it.
  597 
  598   For example, if you distribute copies of such a program, whether
  599 gratis or for a fee, you must give the recipients all the rights that
  600 you have.  You must make sure that they, too, receive or can get the
  601 source code.  And you must show them these terms so they know their
  602 rights.
  603 
  604   We protect your rights with two steps: (1) copyright the software, and
  605 (2) offer you this license which gives you legal permission to copy,
  606 distribute and/or modify the software.
  607 
  608   Also, for each author's protection and ours, we want to make certain
  609 that everyone understands that there is no warranty for this free
  610 software.  If the software is modified by someone else and passed on, we
  611 want its recipients to know that what they have is not the original, so
  612 that any problems introduced by others will not reflect on the original
  613 authors' reputations.
  614 
  615   Finally, any free program is threatened constantly by software
  616 patents.  We wish to avoid the danger that redistributors of a free
  617 program will individually obtain patent licenses, in effect making the
  618 program proprietary.  To prevent this, we have made it clear that any
  619 patent must be licensed for everyone's free use or not licensed at all.
  620 
  621   The precise terms and conditions for copying, distribution and
  622 modification follow.
  623 
  624             GNU GENERAL PUBLIC LICENSE
  625    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  626 
  627   0. This License applies to any program or other work which contains
  628 a notice placed by the copyright holder saying it may be distributed
  629 under the terms of this General Public License.  The "Program", below,
  630 refers to any such program or work, and a "work based on the Program"
  631 means either the Program or any derivative work under copyright law:
  632 that is to say, a work containing the Program or a portion of it,
  633 either verbatim or with modifications and/or translated into another
  634 language.  (Hereinafter, translation is included without limitation in
  635 the term "modification".)  Each licensee is addressed as "you".
  636 
  637 Activities other than copying, distribution and modification are not
  638 covered by this License; they are outside its scope.  The act of
  639 running the Program is not restricted, and the output from the Program
  640 is covered only if its contents constitute a work based on the
  641 Program (independent of having been made by running the Program).
  642 Whether that is true depends on what the Program does.
  643 
  644   1. You may copy and distribute verbatim copies of the Program's
  645 source code as you receive it, in any medium, provided that you
  646 conspicuously and appropriately publish on each copy an appropriate
  647 copyright notice and disclaimer of warranty; keep intact all the
  648 notices that refer to this License and to the absence of any warranty;
  649 and give any other recipients of the Program a copy of this License
  650 along with the Program.
  651 
  652 You may charge a fee for the physical act of transferring a copy, and
  653 you may at your option offer warranty protection in exchange for a fee.
  654 
  655   2. You may modify your copy or copies of the Program or any portion
  656 of it, thus forming a work based on the Program, and copy and
  657 distribute such modifications or work under the terms of Section 1
  658 above, provided that you also meet all of these conditions:
  659 
  660     a) You must cause the modified files to carry prominent notices
  661     stating that you changed the files and the date of any change.
  662 
  663     b) You must cause any work that you distribute or publish, that in
  664     whole or in part contains or is derived from the Program or any
  665     part thereof, to be licensed as a whole at no charge to all third
  666     parties under the terms of this License.
  667 
  668     c) If the modified program normally reads commands interactively
  669     when run, you must cause it, when started running for such
  670     interactive use in the most ordinary way, to print or display an
  671     announcement including an appropriate copyright notice and a
  672     notice that there is no warranty (or else, saying that you provide
  673     a warranty) and that users may redistribute the program under
  674     these conditions, and telling the user how to view a copy of this
  675     License.  (Exception: if the Program itself is interactive but
  676     does not normally print such an announcement, your work based on
  677     the Program is not required to print an announcement.)
  678 
  679 These requirements apply to the modified work as a whole.  If
  680 identifiable sections of that work are not derived from the Program,
  681 and can be reasonably considered independent and separate works in
  682 themselves, then this License, and its terms, do not apply to those
  683 sections when you distribute them as separate works.  But when you
  684 distribute the same sections as part of a whole which is a work based
  685 on the Program, the distribution of the whole must be on the terms of
  686 this License, whose permissions for other licensees extend to the
  687 entire whole, and thus to each and every part regardless of who wrote it.
  688 
  689 Thus, it is not the intent of this section to claim rights or contest
  690 your rights to work written entirely by you; rather, the intent is to
  691 exercise the right to control the distribution of derivative or
  692 collective works based on the Program.
  693 
  694 In addition, mere aggregation of another work not based on the Program
  695 with the Program (or with a work based on the Program) on a volume of
  696 a storage or distribution medium does not bring the other work under
  697 the scope of this License.
  698 
  699   3. You may copy and distribute the Program (or a work based on it,
  700 under Section 2) in object code or executable form under the terms of
  701 Sections 1 and 2 above provided that you also do one of the following:
  702 
  703     a) Accompany it with the complete corresponding machine-readable
  704     source code, which must be distributed under the terms of Sections
  705     1 and 2 above on a medium customarily used for software interchange; or,
  706 
  707     b) Accompany it with a written offer, valid for at least three
  708     years, to give any third party, for a charge no more than your
  709     cost of physically performing source distribution, a complete
  710     machine-readable copy of the corresponding source code, to be
  711     distributed under the terms of Sections 1 and 2 above on a medium
  712     customarily used for software interchange; or,
  713 
  714     c) Accompany it with the information you received as to the offer
  715     to distribute corresponding source code.  (This alternative is
  716     allowed only for noncommercial distribution and only if you
  717     received the program in object code or executable form with such
  718     an offer, in accord with Subsection b above.)
  719 
  720 The source code for a work means the preferred form of the work for
  721 making modifications to it.  For an executable work, complete source
  722 code means all the source code for all modules it contains, plus any
  723 associated interface definition files, plus the scripts used to
  724 control compilation and installation of the executable.  However, as a
  725 special exception, the source code distributed need not include
  726 anything that is normally distributed (in either source or binary
  727 form) with the major components (compiler, kernel, and so on) of the
  728 operating system on which the executable runs, unless that component
  729 itself accompanies the executable.
  730 
  731 If distribution of executable or object code is made by offering
  732 access to copy from a designated place, then offering equivalent
  733 access to copy the source code from the same place counts as
  734 distribution of the source code, even though third parties are not
  735 compelled to copy the source along with the object code.
  736 
  737   4. You may not copy, modify, sublicense, or distribute the Program
  738 except as expressly provided under this License.  Any attempt
  739 otherwise to copy, modify, sublicense or distribute the Program is
  740 void, and will automatically terminate your rights under this License.
  741 However, parties who have received copies, or rights, from you under
  742 this License will not have their licenses terminated so long as such
  743 parties remain in full compliance.
  744 
  745   5. You are not required to accept this License, since you have not
  746 signed it.  However, nothing else grants you permission to modify or
  747 distribute the Program or its derivative works.  These actions are
  748 prohibited by law if you do not accept this License.  Therefore, by
  749 modifying or distributing the Program (or any work based on the
  750 Program), you indicate your acceptance of this License to do so, and
  751 all its terms and conditions for copying, distributing or modifying
  752 the Program or works based on it.
  753 
  754   6. Each time you redistribute the Program (or any work based on the
  755 Program), the recipient automatically receives a license from the
  756 original licensor to copy, distribute or modify the Program subject to
  757 these terms and conditions.  You may not impose any further
  758 restrictions on the recipients' exercise of the rights granted herein.
  759 You are not responsible for enforcing compliance by third parties to
  760 this License.
  761 
  762   7. If, as a consequence of a court judgment or allegation of patent
  763 infringement or for any other reason (not limited to patent issues),
  764 conditions are imposed on you (whether by court order, agreement or
  765 otherwise) that contradict the conditions of this License, they do not
  766 excuse you from the conditions of this License.  If you cannot
  767 distribute so as to satisfy simultaneously your obligations under this
  768 License and any other pertinent obligations, then as a consequence you
  769 may not distribute the Program at all.  For example, if a patent
  770 license would not permit royalty-free redistribution of the Program by
  771 all those who receive copies directly or indirectly through you, then
  772 the only way you could satisfy both it and this License would be to
  773 refrain entirely from distribution of the Program.
  774 
  775 If any portion of this section is held invalid or unenforceable under
  776 any particular circumstance, the balance of the section is intended to
  777 apply and the section as a whole is intended to apply in other
  778 circumstances.
  779 
  780 It is not the purpose of this section to induce you to infringe any
  781 patents or other property right claims or to contest validity of any
  782 such claims; this section has the sole purpose of protecting the
  783 integrity of the free software distribution system, which is
  784 implemented by public license practices.  Many people have made
  785 generous contributions to the wide range of software distributed
  786 through that system in reliance on consistent application of that
  787 system; it is up to the author/donor to decide if he or she is willing
  788 to distribute software through any other system and a licensee cannot
  789 impose that choice.
  790 
  791 This section is intended to make thoroughly clear what is believed to
  792 be a consequence of the rest of this License.
  793 
  794   8. If the distribution and/or use of the Program is restricted in
  795 certain countries either by patents or by copyrighted interfaces, the
  796 original copyright holder who places the Program under this License
  797 may add an explicit geographical distribution limitation excluding
  798 those countries, so that distribution is permitted only in or among
  799 countries not thus excluded.  In such case, this License incorporates
  800 the limitation as if written in the body of this License.
  801 
  802   9. The Free Software Foundation may publish revised and/or new versions
  803 of the General Public License from time to time.  Such new versions will
  804 be similar in spirit to the present version, but may differ in detail to
  805 address new problems or concerns.
  806 
  807 Each version is given a distinguishing version number.  If the Program
  808 specifies a version number of this License which applies to it and "any
  809 later version", you have the option of following the terms and conditions
  810 either of that version or of any later version published by the Free
  811 Software Foundation.  If the Program does not specify a version number of
  812 this License, you may choose any version ever published by the Free Software
  813 Foundation.
  814 
  815   10. If you wish to incorporate parts of the Program into other free
  816 programs whose distribution conditions are different, write to the author
  817 to ask for permission.  For software which is copyrighted by the Free
  818 Software Foundation, write to the Free Software Foundation; we sometimes
  819 make exceptions for this.  Our decision will be guided by the two goals
  820 of preserving the free status of all derivatives of our free software and
  821 of promoting the sharing and reuse of software generally.
  822 
  823                 NO WARRANTY
  824 
  825   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
  826 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
  827 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
  828 PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
  829 OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  830 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
  831 TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
  832 PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
  833 REPAIR OR CORRECTION.
  834 
  835   12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  836 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
  837 REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  838 INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
  839 OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
  840 TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
  841 YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
  842 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
  843 POSSIBILITY OF SUCH DAMAGES.
  844 
  845              END OF TERMS AND CONDITIONS
  846 
  847 EOF