Compare commits

...

11 Commits

Author SHA1 Message Date
Dianne Skoll
ba4d44664f Clarify docs.
All checks were successful
Remind unit tests / tests (push) Successful in 34s
2024-12-11 15:36:17 -05:00
Dianne Skoll
d76c5499b5 Document how translation table is passed to back-ends. 2024-12-11 15:35:31 -05:00
Dianne Skoll
84e8244e48 Use localized names for "Full Moon", etc. 2024-12-11 15:35:23 -05:00
Dianne Skoll
92a6115a5c Send the translation table to back-ends. 2024-12-11 15:24:37 -05:00
Dianne Skoll
b98e336e9e Tweak release notes. 2024-12-11 14:02:30 -05:00
Dianne Skoll
ffcd21446e Update WHATSNEW 2024-12-11 13:55:23 -05:00
Dianne Skoll
af9ca68d99 Document the need for %-style escape sequences in translations to match those in the original message. 2024-12-11 13:42:49 -05:00
Dianne Skoll
71db7168a1 Increase update-for-changes delay to 250ms 2024-12-11 10:25:45 -05:00
Dianne Skoll
54f284c43f Note that strlen returns number of bytes, not characters. 2024-12-11 09:45:40 -05:00
Dianne Skoll
0ab93f2dea Guard against printf-style formatting attacks by malicious translation files. 2024-12-11 09:43:04 -05:00
Dianne Skoll
3d97f87bcd Remove obsolet error messages 2024-12-11 09:33:31 -05:00
14 changed files with 182 additions and 57 deletions

View File

@@ -6,15 +6,31 @@ CHANGES TO REMIND
built-in function. This allows you to localize your reminder files
more easily.
- MAJOR CHANGE: remind: Remind used to support compile-time localization
into different languages (French, English, etc.) That compile-time
support has been removed and all localization is now done at run-time.
- NEW FEATURE: remind: In JSON daemon mode (-zj), the front-end can
request translation table entries from the Remind daemon, allowing the
front-end to localize messages.
- UPDATE: Update national holidays following update to upstream Python
library.
- MINOR FEATURE: Add standard include/sun.rem file for sunrise/sunset.
- IMPROVEMENT: remind: Refuse to open subdirectories named "*.rem"
under a top-level directory rather than trying and failing with a
confusing error.
- IMPROVEMENT: contrib/remind-conf-mode: Fix a few bugs and choose colors
that are easier on the eyes.
- IMPROVEMENT: remind: Remind used to have three completely separate
hash table implementations. Replace them all with one piece of code.
hash table implementations. They have all been replaced with a single
implementation; this new implementation adapts the hash table size based
on the number of entries and is dramatically faster than the old code
when there are a large number of entries.
- MINOR FIXES: remind: Fix typos in comments; use memcpy to copy OMIT
contexts internally.

View File

@@ -98,25 +98,20 @@ FSET subst_min_future(m) iif(m==0, "", m + " minuutin ")
TRANSLATE "Missing ']'" "Puuttuva ']'"
TRANSLATE "Missing quote" "Puuttuva lainausmerkki"
TRANSLATE "Expression too complex" "Liian monimutkainen lauseke"
TRANSLATE "Expression too complex - too many operands" "Liian monimutkainen lauseke - liikaa operandeja"
TRANSLATE "Missing ')'" "Puuttuva ')'"
TRANSLATE "Undefined function" "Määrittelemätön funktio"
TRANSLATE "Illegal character" "Virheellinen merkki"
TRANSLATE "Expecting binary operator" "Kaksipaikkainen operaattori puuttuu"
TRANSLATE "Out of memory" "Muisti loppui"
TRANSLATE "Ill-formed number" "Virheellinen luku"
TRANSLATE "Op stack underflow - internal error" "Operaattoripino tyhjä - sisäinen virhe"
TRANSLATE "Va stack underflow - internal error" "Muuttujapino tyhjä - sisäinen virhe"
TRANSLATE "Can't coerce" "Tyyppimuunnos ei onnistu"
TRANSLATE "Type mismatch" "Virheellinen tyyppi"
TRANSLATE "Date overflow" "Liian suuri päiväys"
TRANSLATE "Stack error - internal error" "Pinovirhe - sisäinen virhe"
TRANSLATE "Division by zero" "Jako nollalla"
TRANSLATE "Undefined variable" "Määrittelemätön funktio"
TRANSLATE "Unexpected end of line" "Odottamaton rivin loppu"
TRANSLATE "Unexpected end of file" "Odottamaton tiedoston loppu"
TRANSLATE "I/O error" "Syöttö- tai tulostusvirhe"
TRANSLATE "Line too long" "Liian pitkä rivi"
TRANSLATE "Internal error" "Sisäinen virhe"
TRANSLATE "Bad date specification" "Virheellinen päiväys"
TRANSLATE "Not enough arguments" "Liian vähän argumentteja"
@@ -148,7 +143,6 @@ TRANSLATE "Month specified twice" "Kuukausi annettu kahdesti"
TRANSLATE "Day specified twice" "Päivä annettu kahdesti"
TRANSLATE "Unknown token" "Tuntematon sana tai merkki"
TRANSLATE "Must specify month in OMIT command" "OMIT-komennossa on annettava kuukausi"
TRANSLATE "Too many partial OMITs (max. 366)" "Liian monta osittaista OMIT-komentoa"
TRANSLATE "Too many full OMITs (max. 1000)" "Liian monta täydellistä OMIT-komentoa"
TRANSLATE "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT" "Varoitus: PUSH-OMIT-CONTEXT ilman POP-OMIT-CONTEXTia"
TRANSLATE "Error reading" "Virhe tiedoston luvussa"
@@ -186,7 +180,6 @@ TRANSLATE "Out of memory for environment\n" "Muisti ei riitä ympäristölle\n"
TRANSLATE "Missing '=' sign" "Puuttuva '='-merkki"
TRANSLATE "Missing variable name" "Puuttuva muuttujanimi"
TRANSLATE "Missing expression" "Puuttuva lauseke"
TRANSLATE "Can't reset access date of %s\n" "Päivän asetus %s:ksi ei onnitus\n"
TRANSLATE "Remind: '-i' option: %s\n" "Remind: tarkenne '-i': %s\n"
TRANSLATE "No reminders." "Ei viestejä."
TRANSLATE "%d reminder(s) queued for later today.\n" "%d viesti(ä) tämän päivän jonossa.\n"

View File

@@ -66,25 +66,20 @@ FSET subst_kx(alt, date, time) iif(alt, subst_k_alt(date), $On + " " + subst_k_a
TRANSLATE "Missing ']'" "']' manquant"
TRANSLATE "Missing quote" "Apostrophe manquant"
TRANSLATE "Expression too complex" "Expression trop complexe"
TRANSLATE "Expression too complex - too many operands" "Expression trop complexe - trop d'opérandes"
TRANSLATE "Missing ')'" "')' manquante"
TRANSLATE "Undefined function" "Fonction non-définie"
TRANSLATE "Illegal character" "Caractère illégal"
TRANSLATE "Expecting binary operator" "Opérateur binaire attendu"
TRANSLATE "Out of memory" "Manque de mémoire"
TRANSLATE "Ill-formed number" "Nombre mal formé"
TRANSLATE "Op stack underflow - internal error" "Erreur interne - 'underflow' de la pile d'opérateurs"
TRANSLATE "Va stack underflow - internal error" "Erreur interne - 'underflow' de la pile de variables"
TRANSLATE "Can't coerce" "Impossible de convertir"
TRANSLATE "Type mismatch" "Types non-équivalents"
TRANSLATE "Date overflow" "Débordement de date"
TRANSLATE "Stack error - internal error" "Erreur interne - erreur de pile"
TRANSLATE "Division by zero" "Division par zéro"
TRANSLATE "Undefined variable" "Variable non définie"
TRANSLATE "Unexpected end of line" "Fin de ligne non attendue"
TRANSLATE "Unexpected end of file" "Fin de fichier non attendue"
TRANSLATE "I/O error" "Erreur I/O"
TRANSLATE "Line too long" "Ligne trop longue"
TRANSLATE "Internal error" "Erreur interne"
TRANSLATE "Bad date specification" "Mauvaise date spécifiée"
TRANSLATE "Not enough arguments" "Pas assez d'arguments"
@@ -116,7 +111,6 @@ TRANSLATE "Month specified twice" "Mois spécifié deux fois"
TRANSLATE "Day specified twice" "Jour spécifié deux fois"
TRANSLATE "Unknown token" "Elément inconnu"
TRANSLATE "Must specify month in OMIT command" "Mois doit être spécifiés dans commande OMIT"
TRANSLATE "Too many partial OMITs (max. 366)" "Trop de OMITs partiels"
TRANSLATE "Too many full OMITs (max. 1000)" "Trop de OMITs complets"
TRANSLATE "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT" "Attention: PUSH-OMIT-CONTEXT sans POP-OMIT-CONTEXT correspondant"
TRANSLATE "Error reading" "Erreur à la lecture du fichier"
@@ -154,7 +148,6 @@ TRANSLATE "Out of memory for environment\n" "Manque de mémoire pour environneme
TRANSLATE "Missing '=' sign" "Signe '=' manquant"
TRANSLATE "Missing variable name" "Nom de variable absent"
TRANSLATE "Missing expression" "Expression absente"
TRANSLATE "Can't reset access date of %s\n" "Impossible de changer la date d'accès de %s\n"
TRANSLATE "%d reminder(s) queued for later today.\n" "%d rappel(s) en file pour aujourd'hui.\n"
TRANSLATE "Expecting number" "Nombre attendu"
TRANSLATE "Undefined WARN function" "Fonction illégale après WARN"

View File

@@ -74,25 +74,20 @@ TRANSLATE "Ok" "OK"
TRANSLATE "Missing ']'" "Brakujący ']'"
TRANSLATE "Missing quote" "Brakujący nawias"
TRANSLATE "Expression too complex" "Zbyt skomplikowane wyrażenie"
TRANSLATE "Expression too complex - too many operands" "Zbyt skomplikowane wyrażenie - za dużo argumentów"
TRANSLATE "Missing ')'" "Brakujący ')'"
TRANSLATE "Undefined function" "Nie zdefiniowana funkcja"
TRANSLATE "Illegal character" "Nielegalny znak"
TRANSLATE "Expecting binary operator" "Spodziewany operator binarny"
TRANSLATE "Out of memory" "Brak pamięci"
TRANSLATE "Ill-formed number" "Niepoprawny numer"
TRANSLATE "Op stack underflow - internal error" "Pusty stos operatorów - błąd wewnętrzny"
TRANSLATE "Va stack underflow - internal error" "Pusty stos zmiennych - błąd wewnętrzny"
TRANSLATE "Can't coerce" "Niemożliwa konwersja"
TRANSLATE "Type mismatch" "Błąd typu"
TRANSLATE "Date overflow" "Nadmiar daty"
TRANSLATE "Stack error - internal error" "Błąd stosu - błąd wewnętrzny"
TRANSLATE "Division by zero" "Dzielenie przez zero"
TRANSLATE "Undefined variable" "Niezdefiniowana zmienna"
TRANSLATE "Unexpected end of line" "Niespodziewany koniec linii"
TRANSLATE "Unexpected end of file" "Niespodziewany koniec pliku"
TRANSLATE "I/O error" "Błąd wejscia/wyjscia"
TRANSLATE "Line too long" "Za długa linia"
TRANSLATE "Internal error" "Błąd wewnętrzny"
TRANSLATE "Bad date specification" "Zła specyfikacja daty"
TRANSLATE "Not enough arguments" "Za mało argumentów"
@@ -124,7 +119,6 @@ TRANSLATE "Month specified twice" "Miesiąc podany dwókrotnie"
TRANSLATE "Day specified twice" "Dzień podany dwókrotnie"
TRANSLATE "Unknown token" "Nieznane słowo"
TRANSLATE "Must specify month in OMIT command" "W komendzie OMIT trzeba podać miesiąc"
TRANSLATE "Too many partial OMITs (max. 366)" "Za dużo częściowych komend OMIT"
TRANSLATE "Too many full OMITs (max. 1000)" "Za dużo pełnych komend OMIT"
TRANSLATE "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT" "Ostrzeżenie: PUSH-OMIT-CONTEXT bez POP-OMIT-CONTEXT"
TRANSLATE "Error reading" "Błąd odczytu pliku"
@@ -162,7 +156,6 @@ TRANSLATE "Out of memory for environment\n" "Brak pamięci na zmienne środowisk
TRANSLATE "Missing '=' sign" "Brak znaku '='"
TRANSLATE "Missing variable name" "Brak nazwy zmiennej"
TRANSLATE "Missing expression" "Brak wyrażenia"
TRANSLATE "Can't reset access date of %s\n" "Nie mogę zmienić daty dostępu pliku %s\n"
TRANSLATE "Remind: '-i' option: %s\n" "Remind: '-i' option: %s\n"
TRANSLATE "No reminders." "Brak przypomnień."
TRANSLATE "%d reminder(s) queued for later today.\n" "%d Przypomnienia zakolejkowane na później.\n"

View File

@@ -73,25 +73,20 @@ FSET subst_hplu(h) iif(h==1, "1 " + $Hour, h + " " + $Hour + $Hplu)
TRANSLATE "Missing ']'" "Falta um ']'"
TRANSLATE "Missing quote" "Falta uma aspa"
TRANSLATE "Expression too complex" "Expressao muito complexa"
TRANSLATE "Expression too complex - too many operands" "Expressao muito complexa - muitos operandos"
TRANSLATE "Missing ')'" "Falta um ')'"
TRANSLATE "Undefined function" "Funcao nao definida"
TRANSLATE "Illegal character" "Caracter ilegal"
TRANSLATE "Expecting binary operator" "Esperando operador binario"
TRANSLATE "Out of memory" "Sem memoria"
TRANSLATE "Ill-formed number" "Numero mal-formado"
TRANSLATE "Op stack underflow - internal error" "Op stack underflow - erro interno"
TRANSLATE "Va stack underflow - internal error" "Va stack underflow - erro interno"
TRANSLATE "Can't coerce" "Nao consigo fazer 'coerce'"
TRANSLATE "Type mismatch" "Type mismatch"
TRANSLATE "Date overflow" "Overflow na data"
TRANSLATE "Stack error - internal error" "Erro de stack - erro interno"
TRANSLATE "Division by zero" "Divisao por zero"
TRANSLATE "Undefined variable" "Variavel nao definida"
TRANSLATE "Unexpected end of line" "Fim da linha nao esperado"
TRANSLATE "Unexpected end of file" "Fim de arquivo nao esperado"
TRANSLATE "I/O error" "Erro de I/O"
TRANSLATE "Line too long" "Linha muito longa"
TRANSLATE "Internal error" "Erro interno"
TRANSLATE "Bad date specification" "Especificacao de data invalida"
TRANSLATE "Not enough arguments" "Argumentos insuficientes"
@@ -123,7 +118,6 @@ TRANSLATE "Month specified twice" "Mes especificado duas vezes"
TRANSLATE "Day specified twice" "Dia especificado duas vezes"
TRANSLATE "Unknown token" "Token desconhecido"
TRANSLATE "Must specify month in OMIT command" "O mes deve ser especificados no comando OMIT"
TRANSLATE "Too many partial OMITs (max. 366)" "Muitos OMITs parciais"
TRANSLATE "Too many full OMITs (max. 1000)" "Muitos OMITs full"
TRANSLATE "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT" "Aviso: PUSH-OMIT-CONTEXT sem POP-OMIT-CONTEXT correspondente"
TRANSLATE "Error reading" "Erro na leitura do arquivo"
@@ -161,7 +155,6 @@ TRANSLATE "Out of memory for environment\n" "Sem memoria para o environment\n"
TRANSLATE "Missing '=' sign" "Falta o sinal de '='"
TRANSLATE "Missing variable name" "Falta o nome da variavel"
TRANSLATE "Missing expression" "Falta a expressao"
TRANSLATE "Can't reset access date of %s\n" "Nao consigo resetar a data de acesso de %s\n"
TRANSLATE "Remind: '-i' option: %s\n" "Remind: '-i' opcao: %s\n"
TRANSLATE "No reminders." "Sem compromissos."
TRANSLATE "%d reminder(s) queued for later today.\n" "%d compromisso(s) colocados na fila para mais tarde.\n"

View File

@@ -337,6 +337,13 @@ older format contains enough information for them to work properly.
\fBRemind \-p\fR sends the following lines to standard output.
The information is designed to be easily parsed by back-end programs:
.TP
.B # translations
This line signifies that the next line will be the translation table.
The line following \fB# translations\fR is a JSON object (on a single
line) containing all of the entries of the translation table. Back-ends that
are not interested in the translation table can simply read and discard
the next line.
.TP
.B # rem2ps begin
This line signifies the start of calendar data. Back-ends can search
for it to verify they are being fed correct information.
@@ -435,6 +442,12 @@ each reminder as a one-off event.
.PP
The lines emitted by \fBremind \-pp\fR are as follows:
.TP
.B # translations
This line signifies that the next line will be the translation table.
The line following \fB# translations\fR is a JSON object (on a single
line) containing all of the entries of the translation table. Back-ends that
are not interested in the translation table can simply read and discard
.TP
.B # rem2ps2 begin
This line signifies the start of calendar data. Back-ends can search
for it to verify they are being fed correct information. Note the
@@ -664,6 +677,9 @@ The number of days in the following month.
The year of the following month. (The same as \fByear\fR unless the
current month is December.)
.TP
.B translations \fR{\fIobject\fR}
A complete dump of the Remind translation table.
.TP
.B entries \fR[\fIarray\fR]
The \fBentries\fR key consists of an array of calendar entries; each
entry is a JSON object that has the same format as described in the

View File

@@ -472,7 +472,16 @@ to standard output and then exit.
.B \-\-print-errs
The \fB\-\-print-errs\fR option causes \fBRemind\fR to print all possible
error messages to standard output and then exit. The messages are printed
in a format suitable for the first argument of a TRANSLATE command.
in a format suitable for the first argument of a TRANSLATE command. If
you TRANSLATE the error messages, then \fBRemind\fR will use the translated
versions when outputting error and warning messages.
.RS
.PP
Note that if an untranslated message contains printf-style formatting
sequences like "%s" or "%d", then the translated message \fImust\fR
contain the same sequences in the same order, or \fBRemind\fR will
ignore it and use the original untranslated message.
.RE
.TP
.B \-\-print-config-cmd
This option causes \fBRemind\fR to print the exact \fB./configure\fR
@@ -3991,7 +4000,10 @@ output is not going to a TTY.
.TP
.B strlen(s_str)
Returns the length of \fIstr\fR. If the length of \fIstr\fR is too large
to represent as an integer, emits a "Number too high" error.
to represent as an integer, emits a "Number too high" error. Note that
\fBstrlen\fR returns the number of \fIbytes\fR in the string, not the
number of \fIcharacters\fR. These numbers are the same for ASCII strings,
but may be different for UTF-8 strings.
.TP
.B substr(s_str, i_start [,i_end])
Returns a \fBSTRING\fR consisting of all characters in \fIstr\fR from

View File

@@ -10,6 +10,8 @@ use Encode;
my %Options;
my $Translations = {};
my $rem2html_version = '@VERSION@';
my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
@@ -265,6 +267,31 @@ sub end_output
print("</body>\n</html>\n");
}
sub slurp_translations
{
my $line;
$line = <STDIN>;
chomp $line;
eval {
if ($Options{utf8}) {
$Translations = decode_json(encode('UTF-8', $line, Encode::FB_DEFAULT));
} else {
$Translations = decode_json($line);
}
};
if ($@) {
$Translations = {};
}
}
sub t
{
my ($str) = @_;
return $Translations->{$str} if exists($Translations->{$str});
return $str;
}
sub parse_input
{
undef $days;
@@ -275,8 +302,12 @@ sub parse_input
my $found_data = 0;
while(<STDIN>) {
chomp;
last if /^\# rem2ps2? begin$/;
chomp;
if (/# translations/) {
slurp_translations();
next;
}
last if /^\# rem2ps2? begin$/;
}
my $line;
@@ -659,7 +690,7 @@ sub draw_day_cell
} else {
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAC6SURBVDiNpdNNbsIwFATgL0HKolchHKBX6yFaBOEyoPYUabvOIVKJRaCL2JX5TRNGGvnJ8ozGz89cYoElPvET+BX2yivn/1Bggw5HHMKa1h2qcPZC/JEIhvh+brIZIY6sorhMYo9hh3KGFzzfa84NZNjDt9OG/ZcH1BlaPE1IAG0+URhxzNGESKPFaHJs9Q0Ziww7HnvGeXSrJhis0jiFfjwnj3I0WRv+TKtr4hQl3lDrZ6QN9Wt654hfWfGDmBpUwDkAAAAASUVORK5CYII=';
}
$title = 'New Moon';
$title = t('New Moon');
$alt = 'new';
} elsif ($phase == 1) {
if ($Options{pngs}) {
@@ -667,7 +698,7 @@ sub draw_day_cell
} else {
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADfSURBVDiNndM9TsNAFATgzy5yjZSAE85JBygETgENUPF3iBCitHAFQkcIhZ/Ryn9gRlrZmp2Z3ef3TBOHOMULPrDBMrhpi/4HI5xjix2+4nmJRbx/Yh7ahvkpRPVV4QDXwT3UQy46zGkAZDgK/iytefvHgCrkJsqZUH6cLnNbABSxd5Jhhf1IbkMXv8Qux7hH1Ic1xvk/jBWy6gavumvtwx7ectwZXkKh7MA95XgObeOtpI2U4zl0kGbpxgiPvwQUcXLrKFchc82f6Ur0PK49azOnmOI4TBu84zm4SV38DeIVYkrYJyNbAAAAAElFTkSuQmCC';
}
$title = 'First Quarter';
$title = t('First Quarter');
$alt = '1st';
} elsif ($phase == 2) {
if ($Options{pngs}) {
@@ -676,7 +707,7 @@ sub draw_day_cell
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADlSURBVDiNrdNBUsJAEAXQlyw4hq4hwWPqTixET6ELkZ16CcAq7oFLqXExjaYgQVNlV/Viev7/6XT/4TjGuME7PiLXUatb8N8xwB12SFjiIXIZtU/MAntEfgvQE4YtHxhiHpjXQ5H7uLhEcaLLAleBvd0Xx9Ha/BdyU+Q5OBV5OKmj7a4YBWdSyNPe4aKHAHkzqcQZNj3JgnNexqE8heyIAulffuFF3kTfIVbBVeu/xoXGGsn2TLJJ/mqkafNiINszySYZdbS90GHlvcgsWktY4TFy7ecxTdvIzahxHQLbyFXUqkPwF2ASRNYgB/PXAAAAAElFTkSuQmCC';
}
$alt = 'full';
$title = 'Full Moon';
$title = t('Full Moon');
} else {
if ($Options{pngs}) {
$img = smoosh($Options{imgbase}, 'lastquarter.png');
@@ -684,7 +715,7 @@ sub draw_day_cell
$img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADmSURBVDiNndMxTsNAEIXhzy5yCyQ6FAgcE7oQheQWUAAl5BIkREoZrgB0GFNkHBl7bURGsryaee/3jHeXdpxjghU+8InXyI0S+n0MMEeBEi+4jfV3vAvMQtsyL0J0j2GtViaeRRMyj8IlsgY8BSijE2Kur/hy09wHKMJrEolhwtwHKDHOsI4OLnoAXfl1jiNsOkR9keE4P8D4q4scbzg5xIxtjie709f1E7siC+9+Gx/8fxvPKtEsklcJSBdgWhcN8ByFR5z+AWgd5QpyE+OUWOJO+zJNU+Z6jHAdgHe7K73CuD5zFT9nCmRDIssCaAAAAABJRU5ErkJggg==';
}
$alt = 'last';
$title = 'Last Quarter';
$title = t('Last Quarter');
}
if ($Options{nostyle}) {
print("<div style=\"float: left\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");

View File

@@ -3668,14 +3668,14 @@ proc UpdateForChanges {} {
RestartBackgroundRemindDaemon
}
# Schedule an update for 100ms in the future.
# Schedule an update for 250ms in the future.
# That way, if we get a rapid succession of
# change notifications, we (probably) only
# end up doing one call to UpdateForChanges
proc ScheduleUpdateForChanges {} {
global TimerUpdateForChanges
catch { after cancel $TimerUpdateForChanges }
set TimerUpdateForChanges [after 100 UpdateForChanges]
set TimerUpdateForChanges [after 250 UpdateForChanges]
}
#***********************************************************************

View File

@@ -965,6 +965,18 @@ static void DoCalendarOneWeek(int nleft)
}
}
static void
SendTranslationTable(int pslevel)
{
if (pslevel < PSCAL_LEVEL3) {
printf("# translations\n");
}
DumpTranslationTable(stdout, 1);
if (pslevel < PSCAL_LEVEL3) {
printf("\n");
}
}
/***************************************************************/
/* */
/* DoSimpleCalendarOneMonth */
@@ -984,14 +996,19 @@ static void DoSimpleCalendarOneMonth(void)
if (PsCal) {
FromDSE(DSEToday, &y, &m, &d);
if (PsCal == PSCAL_LEVEL1) {
SendTranslationTable(PsCal);
printf("%s\n", PSBEGIN);
} else if (PsCal == PSCAL_LEVEL2) {
SendTranslationTable(PsCal);
printf("%s\n", PSBEGIN2);
} else {
if (DidAMonth) {
printf(",\n");
}
printf("{\n");
printf("\"translations\":");
SendTranslationTable(PsCal);
printf(",");
}
if (PsCal < PSCAL_LEVEL3) {
printf("%s %d %d %d %d\n",

View File

@@ -13,31 +13,35 @@
/* Note that not all of the "errors" are really errors - some are just
messages for information purposes. Constants beginning with M_ should
never be returned as error indicators - they should only be used to
index the ErrMsg array. */
index the ErrMsg array.
Some #defines are commented out; these are former error codes that are
no longer used. They are left as placeholders because renumbering
everything wouild be too tedious */
#define OK 0
#define E_MISS_END 1
#define E_MISS_QUOTE 2
#define E_OP_STK_OVER 3
#define E_VA_STK_OVER 4
/* #define E_VA_STK_OVER 4 */
#define E_MISS_RIGHT_PAREN 5
#define E_UNDEF_FUNC 6
#define E_ILLEGAL_CHAR 7
#define E_EXPECTING_BINOP 8
/* #define E_EXPECTING_BINOP 8 */
#define E_NO_MEM 9
#define E_BAD_NUMBER 10
#define E_OP_STK_UNDER 11
#define E_VA_STK_UNDER 12
/* #define E_OP_STK_UNDER 11 */
/* #define E_VA_STK_UNDER 12 */
#define E_CANT_COERCE 13
#define E_BAD_TYPE 14
#define E_DATE_OVER 15
#define E_STACK_ERR 16
/* #define E_STACK_ERR 16 */
#define E_DIV_ZERO 17
#define E_NOSUCH_VAR 18
#define E_EOLN 19
#define E_EOF 20
#define E_IO_ERR 21
#define E_LINE_2_LONG 22
/* #define E_LINE_2_LONG 22 */
#define E_SWERR 23
#define E_BAD_DATE 24
#define E_2FEW_ARGS 25
@@ -72,7 +76,7 @@
#define E_DAY_TWICE 52
#define E_UNKNOWN_TOKEN 53
#define E_SPEC_MON 54
#define E_2MANY_PART 55
/* #define E_2MANY_PART 55 */
#define E_2MANY_FULL 56
#define E_PUSH_NOPOP 57
#define E_ERR_READING 58
@@ -110,7 +114,7 @@
#define E_MISS_EQ 90
#define E_MISS_VAR 91
#define E_MISS_EXPR 92
#define M_CANTSET_ACCESS 93
/* #define M_CANTSET_ACCESS 93 */
#define M_I_OPTION 94
#define E_NOREMINDERS 95
#define M_QUEUED 96
@@ -147,25 +151,25 @@ EXTERN char *ErrMsg[]
/* E_MISS_END */ "Missing ']'",
/* E_MISS_QUOTE */ "Missing quote",
/* E_OP_STK_OVER */ "Expression too complex",
/* E_VA_STK_OVER */ "Expression too complex - too many operands",
/* E_VA_STK_OVER */ "",
/* E_MISS_RIGHT_PAREN */ "Missing ')'",
/* E_UNDEF_FUNC */ "Undefined function",
/* E_ILLEGAL_CHAR */ "Illegal character",
/* E_EXPECTING_BINOP */ "Expecting binary operator",
/* E_NO_MEM */ "Out of memory",
/* E_BAD_NUMBER */ "Ill-formed number",
/* E_OP_STK_UNDER */ "Op stack underflow - internal error",
/* E_VA_STK_UNDER */ "Va stack underflow - internal error",
/* E_OP_STK_UNDER */ "",
/* E_VA_STK_UNDER */ "",
/* E_CANT_COERCE */ "Can't coerce",
/* E_BAD_TYPE */ "Type mismatch",
/* E_DATE_OVER */ "Date overflow",
/* E_STACK_ERR */ "Stack error - internal error",
/* E_STACK_ERR */ "",
/* E_DIV_ZERO */ "Division by zero",
/* E_NOSUCH_VAR */ "Undefined variable",
/* E_EOLN */ "Unexpected end of line",
/* E_EOF */ "Unexpected end of file",
/* E_IO_ERR */ "I/O error",
/* E_LINE_2_LONG */ "Line too long",
/* E_LINE_2_LONG */ "",
/* E_SWERR */ "Internal error",
/* E_BAD_DATE */ "Bad date specification",
/* E_2FEW_ARGS */ "Not enough arguments",
@@ -198,7 +202,7 @@ EXTERN char *ErrMsg[]
/* E_DAY_TWICE */ "Day specified twice",
/* E_UNKNOWN_TOKEN */ "Unknown token",
/* E_SPEC_MON */ "Must specify month in OMIT command",
/* E_2MANY_PART */ "Too many partial OMITs (max. " STR(MAX_PARTIAL_OMITS) ")",
/* E_2MANY_PART */ "",
/* E_2MANY_FULL */ "Too many full OMITs (max. " STR(MAX_FULL_OMITS) ")",
/* E_PUSH_NOPOP */ "Warning: PUSH-OMIT-CONTEXT without matching POP-OMIT-CONTEXT",
/* E_ERR_READING */ "Error reading",
@@ -236,7 +240,7 @@ EXTERN char *ErrMsg[]
/* E_MISS_EQ */ "Missing '=' sign",
/* E_MISS_VAR */ "Missing variable name",
/* E_MISS_EXPR */ "Missing expression",
/* M_CANTSET_ACCESS */ "Can't reset access date of %s\n",
/* M_CANTSET_ACCESS */ "",
/* M_I_OPTION */ "Remind: '-i' option: %s\n",
/* E_NOREMINDERS */ "No reminders.",
/* M_QUEUED */ "%d reminder(s) queued for later today.\n",

View File

@@ -2030,10 +2030,52 @@ int GetOnceDate(void)
return OnceDate;
}
static void
get_printf_escapes(char const *str, DynamicBuffer *out)
{
char const *s = str;
while(*s) {
if (*s == '%' && *(s+1) != 0) {
s++;
DBufPutc(out, *s);
}
s++;
}
}
char const *GetErr(int r)
{
char const *msg;
DynamicBuffer origEscapes;
DynamicBuffer translatedEscapes;
int dangerous;
if (r < 0 || r >= NumErrs) {
r = E_SWERR;
}
return t(ErrMsg[r]);
msg = GetTranslatedString(ErrMsg[r]);
if (!msg) {
return ErrMsg[r];
}
/* We need to make sure both the original and translated version
have the *SAME* printf-style escapes to avoid a malicious
translation file doing a format-string attack */
DBufInit(&origEscapes);
DBufInit(&translatedEscapes);
get_printf_escapes(ErrMsg[r], &origEscapes);
get_printf_escapes(msg, &translatedEscapes);
dangerous = strcmp(DBufValue(&origEscapes), DBufValue(&translatedEscapes));
DBufFree(&origEscapes);
DBufFree(&translatedEscapes);
if (dangerous) {
return ErrMsg[r];
} else {
return msg;
}
}

View File

@@ -357,6 +357,7 @@ int main(int argc, char *argv[])
validfile++;
DoPsCal();
}
DBufFree(&buf);
}
if (!validfile) {
fprintf(stderr, "Rem2PS: Couldn't find any calendar data - are you\n");

View File

@@ -16117,6 +16117,8 @@ Expression nodes high-water: 300073
Test 2
# translations
{"LANGID":"en"}
# rem2ps begin
August 2007 31 3 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
@@ -17580,6 +17582,8 @@ Test 4
2007/08/31 * * * * 2007/09/07
Test 5
# translations
{"LANGID":"en"}
# rem2ps begin
August 2007 31 3 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
@@ -17664,6 +17668,8 @@ September 30
# rem2ps end
Test 6
# translations
{"LANGID":"en"}
# rem2ps begin
August 2007 31 3 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
@@ -17748,6 +17754,8 @@ September 30
# rem2ps end
Test 7
# translations
{"LANGID":"en"}
# rem2ps begin
August 2007 31 3 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
@@ -18060,6 +18068,8 @@ Reading `../tests/include_dir/subdir/04.rem': Found in cache
Reading `subdir/04.rem': Opening file on disk
../tests/include_dir/02.rem(3): Can't open file: subdir/04.rem
Reading `../tests/include_dir/04cantread.rem': Opening file on disk
# translations
{"LANGID":"en"}
# rem2ps begin
August 2007 31 3 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
@@ -18469,6 +18479,8 @@ Found cached directory listing for `include_dir_no_rems'
../tests/include_test.rem(2): include_dir_no_rems: No files matching *.rem
Reading `nonexistent_include_dir': Opening file on disk
../tests/include_test.rem(3): Can't open file: nonexistent_include_dir
# translations
{"LANGID":"en"}
# rem2ps begin
August 2007 31 3 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
@@ -22203,6 +22215,8 @@ Reminders for Sunday, 1st January, 2012:
-stdin-(1): Undefined OMITFUNC function: `foo'
-stdin-(1): Undefined OMITFUNC function: `foo'
-stdin-(1): Undefined OMITFUNC function: `foo'
# translations
{"LANGID":"en"}
# rem2ps2 begin
January 2012 31 0 0
Sunday Monday Tuesday Wednesday Thursday Friday Saturday
@@ -22248,7 +22262,7 @@ February 29
-stdin-(7): Number too high
[
{
"monthname":"January","year":2012,"daysinmonth":31,"firstwkday":0,"mondayfirst":0,"daynames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"prevmonthname":"December","daysinprevmonth":31,"prevmonthyear":2011,"nextmonthname":"February","daysinnextmonth":29,"nextmonthyear":2012,"entries":[
"translations":{"LANGID":"en"},"monthname":"January","year":2012,"daysinmonth":31,"firstwkday":0,"mondayfirst":0,"daynames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"prevmonthname":"December","daysinprevmonth":31,"prevmonthyear":2011,"nextmonthname":"February","daysinnextmonth":29,"nextmonthyear":2012,"entries":[
{"date":"2012-01-02","filename":"-","lineno":1,"d":2,"priority":5000,"body":"Normal"},
{"date":"2012-01-03","filename":"-","lineno":3,"passthru":"COLOR","d":3,"priority":5000,"r":255,"g":0,"b":0,"rawbody":"%\"Red%\" on the calendar!","calendar_body":"Red","plain_body":"Red on the calendar!","body":"255 0 0 %\"Red%\" on the calendar!"},
{"date":"2012-01-04","filename":"-","lineno":5,"d":4,"priority":5000,"body":"Normal"}