- fixed directory browsing in BackupPC_Admin
authorcbarratt <cbarratt>
Sun, 30 Mar 2003 22:41:10 +0000 (22:41 +0000)
committercbarratt <cbarratt>
Sun, 30 Mar 2003 22:41:10 +0000 (22:41 +0000)
 - fixed PoolWrite.pm to handle incorrect initial file sizes.  If the
   file changes on the client after Rsync sends the file list, but before
   the deltas are sent, a different file size can get sent.

 - added binmode(STDIN) to BackupPC_tarExtract

 - added es.pm from Javier for Spanish translation.

ChangeLog
bin/BackupPC_tarExtract
cgi-bin/BackupPC_Admin
conf/config.pl
doc-src/BackupPC.pod
lib/BackupPC/Lang/es.pm [new file with mode: 0644]
lib/BackupPC/PoolWrite.pm
lib/BackupPC/Xfer/Rsync.pm
lib/BackupPC/Xfer/RsyncFileIO.pm

index 418ea8b..152b607 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -30,6 +30,8 @@
   now supports English and French, and adding more languages is
   now easy.  New config paramater $Conf{Language} sets the language.
 
+* Added Spanish translation es.pm from Javier.
+
 * Added optional user-defined pre/post dump/restore commands, allowing
   things like database shutdown/startup for dumps.
 
 * Added catching of SIG_PIPE to BackupPC_dump, and changed catch_signal
   to ignore multiple signals of the same type.
 
+* Added binmode(STDIN) to BackupPC_tarExtract, suggested by Pat LoPresti
+  to fix a problem a RedHat8 with perl 5.8.0.  It's unclear why this
+  helps, but it should be benign.  See:
+    http://sourceforge.net/mailarchive/forum.php?thread_id=1853018&forum_id=503
+
 * Added reporting of the largest number of hardlinks in the pool to the
   log file.
 
index db5ec22..d8f6311 100755 (executable)
@@ -27,7 +27,7 @@
 #
 #========================================================================
 #
-# Version 2.0.0_CVS, released 3 Feb 2003.
+# Version 2.0.0beta0, released 23 Feb 2003.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -374,6 +374,7 @@ sub processClose
 mkpath("$OutDir/$ShareName", 0, 0777);
 open(NEW_FILES, ">>", "$TopDir/pc/$host/NewFileList")
                  || die("can't open $TopDir/pc/$host/NewFileList");
+binmode(STDIN);
 1 while ( TarReadFile(*STDIN) );
 1 while ( sysread(STDIN, my $discard, 1024) );
 
index 5ad7c32..fc25b6e 100755 (executable)
@@ -39,7 +39,7 @@
 #
 #========================================================================
 #
-# Version 2.0.0_CVS, released 3 Feb 2003.
+# Version 2.0.0beta0, released 23 Feb 2003.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -579,6 +579,7 @@ sub Action_Browse
             ErrorExit(eval("qq{$Lang->{Directory___EscHTML}}"));
        }
     }
+    $dir = "/$dir" if ( $dir !~ /^\// );
     my $relDir  = $dir;
     my $currDir = undef;
 
@@ -605,12 +606,12 @@ sub Action_Browse
             my $fURI = $f;                             # URI escaped $f
             my $shareURI = $share;                     # URI escaped $share
            if ( $relDir eq "" ) {
-               $path = $f;
+               $path = "/$f";
            } else {
                ($path = "$relDir/$f") =~ s{//+}{/}g;
            }
            if ( $shareURI eq "" ) {
-               $shareURI = $path;
+               $shareURI = $f;
                $path  = "/";
            }
             $path =~ s{^/+}{/};
@@ -719,12 +720,12 @@ EOF
         # Prune the last directory off $relDir, or at the very end
        # do the top-level directory.
         #
-       if ( $relDir eq "" || $relDir eq "/" ) {
+       if ( $relDir eq "" || $relDir eq "/" || $relDir !~ /(.*)\/(.*)/ ) {
            $currDir = $share;
            $share = "";
            $relDir = "";
        } else {
-           $relDir =~ s/(.*)\/(.*)/$1/;
+           $relDir  = $1;
            $currDir = $2;
        }
     }
index f0fe2b4..8b0e00c 100644 (file)
@@ -429,7 +429,7 @@ $Conf{RestoreInfoKeepCnt} = 10;
 #    $Conf{BackupFilesOnly} = {
 #       'c' => ['/myFiles', '/important'],      # these are for 'c' share
 #       'd' => ['/moreFiles', '/archive'],      # these are for 'd' share
-#    }
+#    };
 #
 $Conf{BackupFilesOnly} = undef;
 
@@ -1179,9 +1179,9 @@ $Conf{CgiURL} = undef;
 
 #   
 # Language to use.  See lib/BackupPC/Lang for the list of supported
-# languages, which includes English (en) and French (fr).  Currently
-# this applies mainly to the CGI interface, but over time it might
-# also include log files and other text output.
+# languages, which include English (en), French (fr), and Spanish (es).
+# Currently the Language setting applies to the CGI interface and email
+# messages sent to users.  Log files and other text is still in English.
 #
 $Conf{Language} = 'en';
 
index ab9ca1e..4b6e640 100644 (file)
@@ -40,6 +40,11 @@ cancel backups and browse and restore files from backups.
 
 =item *
 
+The http/cgi user interface has internationalization (i18n) support,
+currently prodiving English, French and Spanish.
+
+=item *
+
 No client-side software is needed. On WinXX the standard smb
 protocol is used to extract backup data. On linux or unix clients,
 rsync or tar (over ssh/rsh/nfs) is used to extract backup data.
@@ -421,7 +426,7 @@ Rsync as a transport method.
 If you are using smb to backup WinXX machines you need smbclient and
 nmblookup from the samba package.  You will also need nmblookup if
 you are backing up linux/unix DHCP machines.  See L<http://www.samba.org>.
-Version >= 2.2.0 of Samba is required (smbclient's tar feature in
+Version 2.2.0 or later of Samba is required (smbclient's tar feature in
 2.0.8 and prior has bugs for file path lengths around 100 characters
 and generates bad output when file lengths change during the backup).
 
@@ -446,7 +451,7 @@ Use "rsync --version" to check your version.
 
 For BackupPC to use Rsync you will also need to install the perl
 File::RsyncP module, which is available from
-L<http://perlrsync.sourceforge.net>.  Version 0.31 is required.
+L<http://perlrsync.sourceforge.net>.  Version 0.31 or later is required.
 
 =item *
 
@@ -526,7 +531,7 @@ You can run "perldoc Archive::Zip" to see if this module is installed.
 To use rsync and rsyncd with BackupPC you will need to install File::RsyncP.
 You can run "perldoc File::RsyncP" to see if this module is installed.
 File::RsyncP is available from L<http://perlrsync.sourceforge.net>.
-Version 0.20 is required.
+Version 0.31 or later is required.
 
 =back
 
@@ -685,7 +690,7 @@ This is typically the host name or NetBios name of the client machine
 and should be in lower case.  The host name can contain spaces (escape
 with a backslash), but it is not recommended.
 
-Please read the second L<How BackupPC Finds Hosts|how backuppc finds hosts>.
+Please read the section L<How BackupPC Finds Hosts|how backuppc finds hosts>.
 
 In certain cases you might want several distinct clients to refer
 to the same physical machine.  For example, you might have a database
@@ -702,7 +707,7 @@ real host name of the machine.
 Starting with v2.0.0 the way hosts are discovered has changed and now
 in most cases you should specify 0 for the DHCP flag, even if the host
 has a dynamically assigned IP address.
-Please read the second L<How BackupPC Finds Hosts|how backuppc finds hosts>
+Please read the section L<How BackupPC Finds Hosts|how backuppc finds hosts>
 to understand whether you need to set the DHCP flag.
 
 You only need to set DHCP to 1 if your client machine doesn't
@@ -895,6 +900,10 @@ of SSH you have by typing "ssh" or "man ssh".)
 
 =item OpenSSH Instructions
 
+Depending upon your OpenSSH installation, many of these steps can be
+replaced by running the scripts ssh-user-config and ssh-host-config
+included with OpenSSH.  You still need to manually exchange the keys.
+
 =over 4
 
 =item Key generation
@@ -1248,6 +1257,7 @@ to Apache's httpd.conf file:
           SetHandler perl-script
           PerlHandler Apache::Registry
           Options ExecCGI
+          PerlSendHeader On
        </Location>
     </IfModule>
 
@@ -1813,7 +1823,7 @@ is always done to verify if two files are really the same.
 Identical files on multiples backups are represented by hard links.
 Hardlinks are used so that identical files all refer to the same
 physical file on the server's disk. Also, hard links maintain
-reference counts so that BackupPC knows when to deleted unused files
+reference counts so that BackupPC knows when to delete unused files
 from the pool.
 
 For the computer-science majors among you, you can think of the pooling
@@ -2882,6 +2892,8 @@ Copyright (C) 2001-2003 Craig Barratt
 
 Xavier Nicollet, with additions from Guillaume Filion, added the
 internationalization (i18n) support to the CGI interface for v2.0.0.
+Xavier provided the French translation fr.pm, with additions from
+Guillaume.
 
 Ryan Kucera contributed the directory navigation code and images
 for v1.5.0.  He also contributed the first skeleton of BackupPC_restore.
@@ -2889,6 +2901,8 @@ for v1.5.0.  He also contributed the first skeleton of BackupPC_restore.
 Guillaume Filion wrote BackupPC_zipCreate and added the CGI support
 for zip download, in addition to some CGI cleanup, for v1.5.0.
 
+Javier provided the Spanish translation, es.pm.
+
 Many people have reported bugs, made useful suggestions and helped
 with testing; see the ChangeLog and the mail lists.
 
diff --git a/lib/BackupPC/Lang/es.pm b/lib/BackupPC/Lang/es.pm
new file mode 100644 (file)
index 0000000..caa3f75
--- /dev/null
@@ -0,0 +1,1006 @@
+#!/bin/perl -T\r
+\r
+#my %lang;\r
+\r
+#use strict;\r
+\r
+# --------------------------------\r
+\r
+$Lang{Start_Full_Backup} = "Comenzar copia de seguridad completa";\r
+$Lang{Start_Incr_Backup} = "Comenzar copia de seguridad incremental";\r
+$Lang{Stop_Dequeue_Backup} = "Parar/anular copia de seguridad";\r
+$Lang{Restore} = "Restaurar";\r
+\r
+# -----\r
+\r
+$Lang{H_BackupPC_Server_Status} = "Estado del Servidor BackupPC";\r
+\r
+$Lang{BackupPC_Server_Status}= <<EOF;\r
+\${h1(qq{$Lang{H_BackupPC_Server_Status}})}\r
+\r
+\r
+<p>\r
+\${h2(\"Información General del servidor\")}\r
+\r
+<ul>\r
+<li> El PID del servidor es \$Info{pid}, en el host \$Conf{ServerHost},\r
+     version \$Info{Version}, iniciado el \$serverStartTime.\r
+<li> Esta información de estado se ha generado el \$now.\r
+<li> La cola de PC´s se activará de nuevo el \$nextWakeupTime.\r
+<li> Información adicional:\r
+    <ul>\r
+        <li>\$numBgQueue solicitudes pendientes de copia de seguridad desde la última activación programada,\r
+        <li>\$numUserQueue solicitudes pendientes de copia de seguridad de usuarios,\r
+        <li>\$numCmdQueue solicitudes de comandos pendientes ,\r
+        \$poolInfo\r
+        <li>El sistema de archivos estaba recientemente al \$Info{DUlastValue}%\r
+            (\$DUlastTime), el máximo de hoy es \$Info{DUDailyMax}% (\$DUmaxTime)\r
+            y el máximo de ayer era \$Info{DUDailyMaxPrev}%.\r
+    </ul>\r
+</ul>\r
+\r
+\${h2("Trabajos en Ejecución")}\r
+<p>\r
+<table border>\r
+<tr><td> Host </td>\r
+    <td> Tipo </td>\r
+    <td> Usuario </td>\r
+    <td> Hora de Inicio </td>\r
+    <td> Comando </td>\r
+    <td align="center"> PID </td>\r
+    <td> Transfer. PID </td>\r
+    \$tarPidHdr</tr>\r
+\$jobStr\r
+</table>\r
+<p>\r
+\r
+\${h2("Fallos que Precisan Atención")}\r
+<p>\r
+<table border>\r
+<tr><td align="center"> Host </td>\r
+    <td align="center"> Tipo </td>\r
+    <td align="center"> Usuario </td>\r
+    <td align="center"> Ultimo Intento </td>\r
+    <td align="center"> Detalles </td>\r
+    <td align="center"> Hora del error </td>\r
+    <td> Ultimo error (ping no incluido) </td></tr>\r
+\$statusStr\r
+</table>\r
+EOF\r
+\r
+# --------------------------------\r
+$Lang{BackupPC__Server_Summary} = "BackupPC: Resumen del Servidor";\r
+$Lang{BackupPC_Summary}=<<EOF;\r
+\r
+\${h1(qq{$Lang{BackupPC__Server_Summary}})}\r
+<p>\r
+Este status ha sido generado el \$now.\r
+<p>\r
+\r
+\${h2("Hosts con Buenas Copias de Seguridad")}\r
+<p>\r
+Il y a \$hostCntGood hosts tienen copia de seguridad, de un total de :\r
+<ul>\r
+<li> \$fullTot copias de seguridad completas con tamaño total de \${fullSizeTot} GB\r
+     (antes de agrupar y comprimir),\r
+<li> \$incrTot copias de seguridad incrementales con tamaño total de \${incrSizeTot} GB\r
+     (antes de agrupar y comprimir).\r
+</ul>\r
+<table border>\r
+<tr><td> Host </td>\r
+    <td align="center"> Usuario </td>\r
+    <td align="center"> #Completo </td>\r
+    <td align="center"> Completo Antig./Días </td>\r
+    <td align="center"> Completo Tamaño/GB </td>\r
+    <td align="center"> Velocidad MB/sec </td>\r
+    <td align="center"> #Incrementales </td>\r
+    <td align="center"> Incrementales Antig/Días </td>\r
+    <td align="center"> Estado </td>\r
+    <td align="center"> Ultimo Intento </td></tr>\r
+\$strGood\r
+</table>\r
+<p>\r
+\r
+\${h2("Hosts Sin Copias de Seguridad")}\r
+<p>\r
+Hay \$hostCntNone hosts sin copias de seguridad.\r
+<p>\r
+<table border>\r
+<tr><td> Host </td>\r
+    <td align="center"> Usuario </td>\r
+    <td align="center"> #Completo </td>\r
+    <td align="center"> Completo Antig./Días </td>\r
+    <td align="center"> Completo Tamaño/GB </td>\r
+    <td align="center"> Velocidad MB/sec </td>\r
+    <td align="center"> #Incrementales </td>\r
+    <td align="center"> Incrementales Antig/Días </td>\r
+    <td align="center"> Estado </td>\r
+    <td align="center"> Ultimo Intento </td></tr>\r
+\$strNone\r
+</table>\r
+EOF\r
+\r
+# -----------------------------------\r
+$Lang{Pool_Stat} = <<EOF;\r
+        <li>El grupo tiene \${poolSize}GB incluyendo \$info->{"\${name}FileCnt"} archivos\r
+            y \$info->{"\${name}DirCnt"} directorios (as of \$poolTime),\r
+        <li>El procesamiento del grupo da \$info->{"\${name}FileCntRep"} archivos\r
+            repetidos cuya cadena más larga es \$info->{"\${name}FileRepMax"},\r
+        <li>El proceso de limpieza nocturna ha eliminado \$info->{"\${name}FileCntRm"} archivos de\r
+            tamaño \${poolRmSize}GB (around \$poolTime),\r
+EOF\r
+\r
+# --------------------------------\r
+$Lang{BackupPC__Backup_Requested_on__host} = "BackupPC: Copia de Seguridad Solicitada en \$host";\r
+# --------------------------------\r
+$Lang{REPLY_FROM_SERVER} = <<EOF;\r
+\${h1(\$str)}\r
+<p>\r
+La respuesta del servidor fué: \$reply\r
+<p>\r
+Volver a <a href="\$MyURL?host=\$host">\$host home page</a>.\r
+EOF\r
+# --------------------------------\r
+$Lang{BackupPC__Start_Backup_Confirm_on__host} = "BackupPC: Confirme inicio de copia de seguridad en \$host";\r
+# --------------------------------\r
+$Lang{Are_you_sure_start} = <<EOF;\r
+\${h1("¿Está seguro?")}\r
+<p>\r
+Va a hacer comenzar una copia de seguridad \$type en \$host.\r
+\r
+<form action="\$MyURL" method="get">\r
+<input type="hidden" name="host" value="\$host">\r
+<input type="hidden" name="hostIP" value="\$ipAddr">\r
+<input type="hidden" name="doit" value="1">\r
+¿Realmente quiere hacer esto?\r
+<input type="submit" value="\$In{action}" name="action">\r
+<input type="submit" value="No" name="">\r
+</form>\r
+EOF\r
+# --------------------------------\r
+$Lang{BackupPC__Stop_Backup_Confirm_on__host} = "BackupPC: Confirmación de Parada de Copia de Seguridad en \$host";\r
+# --------------------------------\r
+$Lang{Are_you_sure_stop} = <<EOF;\r
+\r
+\${h1("¿Está seguro?")}\r
+\r
+<p>\r
+Está a punto de parar/quitar de la cola las copias de seguridad en \$host;\r
+\r
+<form action="\$MyURL" method="get">\r
+<input type="hidden" name="host" value="\$host">\r
+<input type="hidden" name="doit" value="1">\r
+Asimismo, por favor no empiece otra copia de seguridad durante\r
+<input type="text" name="backoff" size="10" value="\$backoff"> horas.\r
+<p>\r
+¿Realmente quiere hacer esto?\r
+<input type="submit" value="\$In{action}" name="action">\r
+<input type="submit" value="No" name="">\r
+</form>\r
+\r
+EOF\r
+# --------------------------------\r
+$Lang{Only_privileged_users_can_view_queues_} = "Sólo los administradores pueden ver las colas.";\r
+# --------------------------------\r
+$Lang{BackupPC__Queue_Summary} = "BackupPC: Resumen de la Cola";\r
+# --------------------------------\r
+$Lang{Backup_Queue_Summary} = <<EOF;\r
+\${h1("Resumen de la Cola de Copias de Seguridad")}\r
+<p>\r
+\${h2("Resumen de la Cola de Usuarios")}\r
+<p>\r
+Las siguientes solicitudes de usuarios están actualmente en cola:\r
+<table border>\r
+<tr><td> Host </td>\r
+    <td> Hora Sol. </td>\r
+    <td> Usuario </td></tr>\r
+\$strUser\r
+</table>\r
+<p>\r
+\r
+\${h2("Resumen de Cola en Segundo Plano")}\r
+<p>\r
+Las siguientes solicitudes en segundo plano están actualmente en cola:\r
+<table border>\r
+<tr><td> Host </td>\r
+    <td> Hora Sol. </td>\r
+    <td> Usuario </td></tr>\r
+\$strBg\r
+</table>\r
+<p>\r
+\r
+\${h2("Resumen de Cola de Comandos")}\r
+<p>\r
+Los siguientes comandos están actualmente en cola:\r
+<table border>\r
+<tr><td> Host </td>\r
+    <td> Hora Sol. </td>\r
+    <td> Usuario </td>\r
+    <td> Comando </td></tr>\r
+\$strCmd\r
+</table>\r
+EOF\r
+\r
+# --------------------------------\r
+$Lang{Backup_PC__Log_File__file} = "BackupPC: Archivo de Registro \$file";\r
+$Lang{Log_File__file__comment} = <<EOF;\r
+\${h1("Log File \$file \$comment")}\r
+<p>\r
+EOF\r
+# --------------------------------\r
+$Lang{Contents_of_log_file} = <<EOF;\r
+Contenido del archivo de registro <tt>\$file</tt>, modificado \$mtimeStr \$comment\r
+EOF\r
+\r
+# --------------------------------\r
+$Lang{skipped__skipped_lines} = "[ saltadas \$skipped lineas ]\n";\r
+# --------------------------------\r
+$Lang{_pre___Can_t_open_log_file__file} = "<pre>\nNo puedo abrir el archivo de registro \$file\n";\r
+\r
+# --------------------------------\r
+$Lang{BackupPC__Log_File_History} = "BackupPC: Historial de Archivo de Registro";\r
+$Lang{Log_File_History__hdr} = <<EOF;\r
+\${h1("Historial de Archivo de Registro \$hdr")}\r
+<p>\r
+<table border>\r
+<tr><td align="center"> File </td>\r
+    <td align="center"> Size </td>\r
+    <td align="center"> Hora Modificación </td></tr>\r
+\$str\r
+</table>\r
+EOF\r
+\r
+# -------------------------------\r
+$Lang{Recent_Email_Summary} = <<EOF;\r
+\${h1("Resumen de Mensajes Recientes (Orden de tiempo inverso)")}\r
+<p>\r
+<table border>\r
+<tr><td align="center"> Destinatario </td>\r
+    <td align="center"> Host </td>\r
+    <td align="center"> Hora </td>\r
+    <td align="center"> Asunto </td></tr>\r
+\$str\r
+</table>\r
+EOF\r
\r
+\r
+# ------------------------------\r
+$Lang{Browse_backup__num_for__host} = "BackupPC: Hojear copia de seguridad \$num de \$host";\r
+\r
+# ------------------------------\r
+$Lang{Restore_Options_for__host} = "BackupPC: Opciones de restauración para \$host";\r
+$Lang{Restore_Options_for__host2} = <<EOF;\r
+<p>\r
+Ha seleccionado los siguientes archivos/directorios de\r
+la unidad \$share, copia número #\$num:\r
+<ul>\r
+\$fileListStr\r
+</ul>\r
+<p>\r
+Tiene tres opciones para restaurar estos archivos/directorios.\r
+Por favor, seleccione una de las siguientes opciones.\r
+<p>\r
+\${h2("Opción 1: Restauración Directa")}\r
+<p>\r
+Puede empezar un proceso que restaurará estos archivos directamente en\r
+\$host.\r
+<p>\r
+<b>¡Atención!:</b> ¡Cualquier archivo existente con el mismo nombre que los que ha\r
+seleccionado será sobreescrito!\r
+\r
+<form action="\$MyURL" method="post">\r
+<input type="hidden" name="host" value="\${EscHTML(\$host)}">\r
+<input type="hidden" name="num" value="\$num">\r
+<input type="hidden" name="type" value="3">\r
+\$hiddenStr\r
+<input type="hidden" value="\$In{action}" name="action">\r
+<table border="0">\r
+<tr>\r
+    <td>Restaurar los archivos al host</td>\r
+    <td><input type="text" size="40" value="\${EscHTML(\$host)}"\r
+        name="hostDest"></td>\r
+</tr><tr>\r
+    <td>Restaurar los archivos a la unidad</td>\r
+    <td><input type="text" size="40" value="\${EscHTML(\$share)}"\r
+        name="shareDest"></td>\r
+</tr><tr>\r
+    <td>Restaurar los archivos bajo el directorio<br>(relativo a la unidad)</td>\r
+    <td valign="top"><input type="text" size="40" maxlength="256"\r
+       value="\${EscHTML(\$pathHdr)}" name="pathHdr"></td>\r
+</tr><tr>\r
+    <td><input type="submit" value="Start Restore" name=""></td>\r
+</table>\r
+</form>\r
+EOF\r
+\r
+# ------------------------------\r
+$Lang{Option_2__Download_Zip_archive} = <<EOF;\r
+\r
+\${h2("Opción 2: Descargar archivo Zip")}\r
+<p>\r
+Puede descargar un archivo comprimido (.zip) conteniendo todos los archivos y directorios que\r
+ha seleccionado.  Después puede hacer uso de una aplicación local, como WinZip,\r
+para ver o extraer cualquiera de los archivos.\r
+<p>\r
+<b>¡Atención!:</b> Dependiendo de que archivos/carpetas haya seleccionado,\r
+este archivo puede ser muy grande. Podría tardar muchos minutos\r
+crear y transferir el archivo. Además necesitará suficiente espacio el el disco\r
+local para almacenarlo.\r
+<p>\r
+<form action="\$MyURL" method="post">\r
+<input type="hidden" name="host" value="\${EscHTML(\$host)}">\r
+<input type="hidden" name="num" value="\$num">\r
+<input type="hidden" name="type" value="2">\r
+\$hiddenStr\r
+<input type="hidden" value="\$In{action}" name="action">\r
+<input type="checkbox" value="1" name="relative" checked> Hacer archivo relativo\r
+a \${EscHTML(\$pathHdr eq "" ? "/" : \$pathHdr)}\r
+(en caso contrario el archivo contendrá las rutas completas).\r
+<br>\r
+Compresión (0=desactivada, 1=rápida,...,9=máxima)\r
+<input type="text" size="6" value="5" name="compressLevel">\r
+<br>\r
+<input type="submit" value="Download Zip File" name="">\r
+</form>\r
+EOF\r
+\r
+# ------------------------------\r
+\r
+$Lang{Option_2__Download_Zip_archive2} = <<EOF;\r
+\${h2("Opción 2: Descargar archivo Zip")}\r
+<p>\r
+El programa Archive::Zip no está instalado, de modo que no podrá descargar un\r
+archivo comprimido zip.\r
+Por favor, solicite a su administrador de sistemas que instale Archive::Zip de\r
+<a href="http://www.cpan.org">www.cpan.org</a>.\r
+<p>\r
+EOF\r
+\r
+\r
+# ------------------------------\r
+$Lang{Option_3__Download_Zip_archive} = <<EOF;\r
+\${h2("Opción 3: Descargar archivo Tar")}\r
+<p>\r
+Puede descargar un archivo comprimido (.Tar) conteniendo todos los archivos y\r
+directorios que ha seleccionado. Después puede hacer uso de una aplicación\r
+local, como Tar o WinZip,para ver o extraer cualquiera de los archivos.\r
+<p>\r
+<b>¡Atención!:</b> Dependiendo de que archivos/carpetas haya seleccionado,\r
+este archivo puede ser muy grande. Podría tardar muchos minutos\r
+crear y transferir el archivo. Además necesitará suficiente espacio el el disco\r
+local para almacenarlo.\r
+<p>\r
+<form action="\$MyURL" method="post">\r
+<input type="hidden" name="host" value="\${EscHTML(\$host)}">\r
+<input type="hidden" name="num" value="\$num">\r
+<input type="hidden" name="type" value="1">\r
+\$hiddenStr\r
+<input type="hidden" value="\$In{action}" name="action">\r
+<input type="checkbox" value="1" name="relative" checked> Hacer el archivo\r
+relativo a \${EscHTML(\$pathHdr eq "" ? "/" : \$pathHdr)}\r
+(en caso contrario el archivo contendrá las rutas completas).\r
+<br>\r
+<input type="submit" value="Download Tar File" name="">\r
+</form>\r
+EOF\r
+\r
+\r
+# ------------------------------\r
+$Lang{Restore_Confirm_on__host} = "BackupPC: Restore Confirm on \$host";\r
+\r
+$Lang{Are_you_sure} = <<EOF;\r
+\${h1("¿Está seguro?")}\r
+<p>\r
+Está a punto de comenzar una restauración directamente a la máquina \$In{hostDest}.\r
+Los siguientes archivos serán restaurados en la unidad \$In{shareDest}, de\r
+la copia de seguridad número \$num:\r
+<p>\r
+<table border>\r
+<tr><td>Archivo/Dir Original </td><td>Será restaurado a</td></tr>\r
+\$fileListStr\r
+</table>\r
+\r
+<form action="\$MyURL" method="post">\r
+<input type="hidden" name="host" value="\${EscHTML(\$host)}">\r
+<input type="hidden" name="hostDest" value="\${EscHTML(\$In{hostDest})}">\r
+<input type="hidden" name="shareDest" value="\${EscHTML(\$In{shareDest})}">\r
+<input type="hidden" name="pathHdr" value="\${EscHTML(\$In{pathHdr})}">\r
+<input type="hidden" name="num" value="\$num">\r
+<input type="hidden" name="type" value="4">\r
+\$hiddenStr\r
+Do you really want to do this?\r
+<input type="submit" value="\$In{action}" name="action">\r
+<input type="submit" value="No" name="">\r
+</form>\r
+EOF\r
+\r
+\r
+# --------------------------\r
+$Lang{Restore_Requested_on__hostDest} = "BackupPC: Restauración solicitada en \$hostDest";\r
+$Lang{Reply_from_server_was___reply} = <<EOF;\r
+\${h1(\$str)}\r
+<p>\r
+La respuesta del servidor fué: \$reply\r
+<p>\r
+Go back to <a href="\$MyURL?host=\$hostDest">\$hostDest home page</a>.\r
+EOF\r
+\r
+# -------------------------\r
+$Lang{Host__host_Backup_Summary} = "BackupPC: Host \$host Resumen de Copia de Seguridad";\r
+\r
+$Lang{Host__host_Backup_Summary2} = <<EOF;\r
+\${h1("Host \$host Backup Summary")}\r
+<p>\r
+\$warnStr\r
+<ul>\r
+\$statusStr\r
+</ul>\r
+\r
+\${h2("Acciones del Usuario")}\r
+<p>\r
+<form action="\$MyURL" method="get">\r
+<input type="hidden" name="host" value="\$host">\r
+\$startIncrStr\r
+<input type="submit" value="$Lang{Start_Full_Backup}" name="action">\r
+<input type="submit" value="$Lang{Stop_Dequeue_Backup}" name="action">\r
+</form>\r
+\r
+\${h2("Resumen de Copia de Seguridad")}\r
+<p>\r
+Haga click en el número de copia de seguridad para revisar y restaurar archivos.\r
+<table border>\r
+<tr><td align="center"> Copia Nº </td>\r
+    <td align="center"> Tipo </td>\r
+    <td align="center"> Completo </td>\r
+    <td align="center"> Fecha Inicio </td>\r
+    <td align="center"> Duracion/mn </td>\r
+    <td align="center"> Antigüedad/dias </td>\r
+    <td align="center"> Ruta a la Copia en el Servidor </td>\r
+</tr>\r
+\$str\r
+</table>\r
+<p>\r
+\r
+\$restoreStr\r
+\r
+\${h2("Resumen de Errores de Transferencia")}\r
+<p>\r
+<table border>\r
+<tr><td align="center"> Copia Nº </td>\r
+    <td align="center"> Tipo </td>\r
+    <td align="center"> Ver </td>\r
+    <td align="center"> Nº Xfer errs </td>\r
+    <td align="center"> Nº err. archivos </td>\r
+    <td align="center"> Nº err. unidades </td>\r
+    <td align="center"> Nº err. tar </td>\r
+</tr>\r
+\$errStr\r
+</table>\r
+<p>\r
+\r
+\${h2("Resumen de Total/Tamaño de Archivos Reutilizados")}\r
+<p>\r
+Los archivos existentes son aquellos que ya están en el lote; los nuevos son\r
+aquellos que se han añadido al lote.\r
+Los archivos vacíos y los errores SMB no cuentan en las cifras de reutilizados\r
+ni en la de nuevos.\r
+<table border>\r
+<tr><td colspan="2"></td>\r
+    <td align="center" colspan="3"> Totales </td>\r
+    <td align="center" colspan="2"> Archivos Existentes </td>\r
+    <td align="center" colspan="2"> Archivos Nuevos </td>\r
+</tr>\r
+<tr>\r
+    <td align="center"> Copia Nº </td>\r
+    <td align="center"> Tipo </td>\r
+    <td align="center"> Nº Archivos </td>\r
+    <td align="center"> Tamaño/MB </td>\r
+    <td align="center"> MB/sg </td>\r
+    <td align="center"> Nº Archivos </td>\r
+    <td align="center"> Tamaño/MB </td>\r
+    <td align="center"> Nº Archivos </td>\r
+    <td align="center"> Tamaño/MB </td>\r
+</tr>\r
+\$sizeStr\r
+</table>\r
+<p>\r
+\r
+\${h2("Resumen de Compresión")}\r
+<p>\r
+Efectividad de compresión para los archivos ya existentes en el lote y los\r
+archivos nuevos comprimidos.\r
+<table border>\r
+<tr><td colspan="3"></td>\r
+    <td align="center" colspan="3"> Archivos Existentes </td>\r
+    <td align="center" colspan="3"> Archivos Nuevos </td>\r
+</tr>\r
+<tr><td align="center"> Copia Nº </td>\r
+    <td align="center"> Tipo </td>\r
+    <td align="center"> Nivel Comp </td>\r
+    <td align="center"> Tamaño/MB </td>\r
+    <td align="center"> Comp/MB </td>\r
+    <td align="center"> Comp </td>\r
+    <td align="center"> Tamaño/MB </td>\r
+    <td align="center"> Comp/MB </td>\r
+    <td align="center"> Comp </td>\r
+</tr>\r
+\$compStr\r
+</table>\r
+<p>\r
+EOF\r
+\r
+# -------------------------\r
+$Lang{Error} = "BackupPC: Error";\r
+$Lang{Error____head} = <<EOF;\r
+\${h1("Error: \$head")}\r
+<p>\$mesg</p>\r
+EOF\r
+\r
+# -------------------------\r
+$Lang{NavSectionTitle_} = "Servidor";\r
+\r
+# -------------------------\r
+$Lang{Backup_browse_for__host} = <<EOF;\r
+\${h1("Revisar Copia de seguridad de \$host")}\r
+\r
+<script language="javascript" type="text/javascript">\r
+<!--\r
+\r
+    function checkAll(location)\r
+    {\r
+      for (var i=0;i<document.form1.elements.length;i++)\r
+      {\r
+        var e = document.form1.elements[i];\r
+        if ((e.checked || !e.checked) && e.name != \'all\') {\r
+            if (eval("document.form1."+location+".checked")) {\r
+               e.checked = true;\r
+            } else {\r
+               e.checked = false;\r
+            }\r
+        }\r
+      }\r
+    }\r
+    \r
+    function toggleThis(checkbox)\r
+    {\r
+       var cb = eval("document.form1."+checkbox);\r
+       cb.checked = !cb.checked;       \r
+    }\r
+\r
+//-->\r
+</script>\r
+\r
+<ul>\r
+<li> Está revisando la copia de seguridad Nº\$num, que comenzó hacia las \$backupTime\r
+        (hace \$backupAge dias),\r
+\$filledBackup\r
+<li> Haga click en uno de los directorios de abajo para revisar sus contenidos,\r
+<li> Haga click en un archivo para restaurarlo.\r
+</ul>\r
+\r
+\${h2("Contenido de \${EscHTML(\$dirDisplay)}")}\r
+<form name="form1" method="post" action="\$MyURL">\r
+<input type="hidden" name="num" value="\$num">\r
+<input type="hidden" name="host" value="\$host">\r
+<input type="hidden" name="share" value="\${EscHTML(\$share)}">\r
+<input type="hidden" name="fcbMax" value="\$checkBoxCnt">\r
+<input type="hidden" name="action" value="$Lang{Restore}">\r
+<br>\r
+<table>\r
+<tr><td valign="top">\r
+    <!--Navigate here:-->\r
+    <br><table align="center" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff">\r
+    \$dirStr\r
+    </table>\r
+</td><td width="3%">\r
+</td><td valign="top">\r
+    <!--Restore files here:-->\r
+    <br>\r
+    <table cellpadding="0" cellspacing="0" bgcolor="#333333"><tr><td>\r
+        <table border="0" width="100%" align="left" cellpadding="2" cellspacing="1">\r
+        \$fileHeader\r
+        \$topCheckAll\r
+        \$fileStr\r
+        \$checkAll\r
+        </table>\r
+    </td></tr></table>\r
+<br>\r
+<!--\r
+This is now in the checkAll row\r
+<input type="submit" name="Submit" value="Restore selected files">\r
+-->\r
+</td></tr></table>\r
+</form>\r
+EOF\r
+\r
+# ------------------------------\r
+$Lang{Restore___num_details_for__host} = "BackupPC: Detalles de la restauración Nº\$num de \$host";\r
+\r
+$Lang{Restore___num_details_for__host2 } = <<EOF;\r
+\${h1("Detalles de la restauración Nº\$num de \$host")}\r
+<p>\r
+<table border>\r
+<tr><td> Número </td><td> \$Restores[\$i]{num} </td></tr>\r
+<tr><td> Solicitado por </td><td> \$RestoreReq{user} </td></tr>\r
+<tr><td> Hora Petición </td><td> \$reqTime </td></tr>\r
+<tr><td> Resultado </td><td> \$Restores[\$i]{result} </td></tr>\r
+<tr><td> Mensaje de Error </td><td> \$Restores[\$i]{errorMsg} </td></tr>\r
+<tr><td> Host Origen </td><td> \$RestoreReq{hostSrc} </td></tr>\r
+<tr><td> Nº copia origen </td><td> \$RestoreReq{num} </td></tr>\r
+<tr><td> Unidad origen </td><td> \$RestoreReq{shareSrc} </td></tr>\r
+<tr><td> Host destino </td><td> \$RestoreReq{hostDest} </td></tr>\r
+<tr><td> Unidad destino </td><td> \$RestoreReq{shareDest} </td></tr>\r
+<tr><td> Hora comienzo </td><td> \$startTime </td></tr>\r
+<tr><td> Duración </td><td> \$duration min </td></tr>\r
+<tr><td> Número de archivos </td><td> \$Restores[\$i]{nFiles} </td></tr>\r
+<tr><td> Tamaño total </td><td> \${MB} MB </td></tr>\r
+<tr><td> Tasa de transferencia </td><td> \$MBperSec MB/sec </td></tr>\r
+<tr><td> Errores creación Tar </td><td> \$Restores[\$i]{tarCreateErrs} </td></tr>\r
+<tr><td> Errores de transferencia </td><td> \$Restores[\$i]{xferErrs} </td></tr>\r
+<tr><td> Archivo registro de transferencia </td><td>\r
+<a href="\$MyURL?action=view&type=RestoreLOG&num=\$Restores[\$i]{num}&host=\$host">View</a>,\r
+<a href="\$MyURL?action=view&type=RestoreErr&num=\$Restores[\$i]{num}&host=\$host">Errors</a>\r
+</tr></tr>\r
+</table>\r
+<p>\r
+\${h1("Lista de Archivos/Directorios")}\r
+<p>\r
+<table border>\r
+<tr><td>Dir/archivo original</td><td>Restaurado a</td></tr>\r
+\$fileListStr\r
+</table>\r
+EOF\r
+\r
+# -----------------------------------\r
+$Lang{Email_Summary} = "BackupPC: Resumen de Correos";\r
+\r
+# -----------------------------------\r
+#  !! ERROR messages !!\r
+# -----------------------------------\r
+$Lang{BackupPC__Lib__new_failed__check_apache_error_log} = "BackupPC::Lib->nuevo ha fallado: revise el error_log de apache\n";\r
+$Lang{Wrong_user__my_userid_is___} =  \r
+              "Usuario erróneo: mi userid es \$>, en lugar de \$uid"\r
+            . "(\$Conf{BackupPCUser})\n";\r
+$Lang{Only_privileged_users_can_view_PC_summaries} = "Sólo los usuarios autorizados pueden ver los resúmenes de PC´s.";\r
+$Lang{Only_privileged_users_can_stop_or_start_backups} = \r
+                  "Sólo los usuarios autorizados pueden comenzar a detener las copias"\r
+               . " \${EscHTML(\$host)}.";\r
+$Lang{Invalid_number__num} = "Número no válido \$num";\r
+$Lang{Unable_to_open__file__configuration_problem} = "No puedo abrir \$file: ¿problema de configuración?";\r
+$Lang{Only_privileged_users_can_view_log_or_config_files} = "Sólo los usuarios autorizados pueden ver registros o archivos de configuración.";\r
+$Lang{Only_privileged_users_can_view_log_files} = "Sólo los usuarios autorizados pueden ver archivos de registro.";\r
+$Lang{Only_privileged_users_can_view_email_summaries} = "Sólo los usuarios autorizados pueden ver resúmenes de correo.";\r
+$Lang{Only_privileged_users_can_browse_backup_files} = "Sólo los usuarios autorizados pueden revisar los archivos de las copias de seguridad"\r
+                . " for host \${EscHTML(\$In{host})}.";\r
+$Lang{Empty_host_name} = "Número de host vacío.";\r
+$Lang{Directory___EscHTML} = "El directorio \${EscHTML(\"\$TopDir/pc/\$host/\$num\")}"\r
+                   . " está vacío";\r
+$Lang{Can_t_browse_bad_directory_name2} = "No puedo mostrar un nombre de directorio erróneo"\r
+                   . " \${EscHTML(\$relDir)}";\r
+$Lang{Only_privileged_users_can_restore_backup_files} = "Sólo los usuarios autorizados pueden restaurar copias de seguridad"\r
+                . " para el host \${EscHTML(\$In{host})}.";\r
+$Lang{Bad_host_name} = "Nombre de host erróneo \${EscHTML(\$host)}";\r
+$Lang{You_haven_t_selected_any_files__please_go_Back_to} = "No ha seleccionado nigún archivo; por favor, vuelva a"\r
+                . " seleccione algunos archivos.";\r
+$Lang{Nice_try__but_you_can_t_put} = "Buen intento, pero no puede usar \'..\' en los nombres de archivo";\r
+$Lang{Host__doesn_t_exist} = "El Host \${EscHTML(\$In{hostDest})} no existe";\r
+$Lang{You_don_t_have_permission_to_restore_onto_host} = "No tiene autorización para restaurar en el host"\r
+                   . " \${EscHTML(\$In{hostDest})}";\r
+$Lang{Can_t_open_create} = "No puedo abrir/crear "\r
+                    . "\${EscHTML(\"\$TopDir/pc/\$hostDest/\$reqFileName\")}";\r
+$Lang{Only_privileged_users_can_restore_backup_files2} = "Sólo los usuarios autorizados pueden restaurar copias de seguridad"\r
+                . " del host \${EscHTML(\$host)}.";\r
+$Lang{Empty_host_name} = "Nombre de host vacío";\r
+$Lang{Unknown_host_or_user} = "Unknown host or user \${EscHTML(\$host)}";\r
+$Lang{Only_privileged_users_can_view_information_about} = "Sólo los usuarios autorizados pueden ver información del"\r
+                . " host \${EscHTML(\$host)}." ;\r
+$Lang{Only_privileged_users_can_view_restore_information} = "Sólo los usuarios autorizados pueden ver información de restauración.";\r
+$Lang{Restore_number__num_for_host__does_not_exist} = "El número de restauración \$num del host \${EscHTML(\$host)} "\r
+               . " no existe.";\r
+\r
+$Lang{Unable_to_connect_to_BackupPC_server} = "Imposible conectar al servidor BackupPC",\r
+            "Este script CGI (\$MyURL) no puede conectar al servidor BackupPC"\r
+          . " en \$Conf{ServerHost} puerto \$Conf{ServerPort}.  El error"\r
+          . " fué: \$err.",\r
+            "Quizá el servidor BackupPC no está activo o hay un "\r
+          . " error de configuración. Por favor informe a su administrador de sistemas.";\r
+\r
+$Lang{Can_t_find_IP_address_for} = "No puedo encontrar la dirección IP de \${EscHTML(\$host)}";\r
+$Lang{host_is_a_DHCP_host} = <<EOF;\r
+\$host es un host DHCP y yo no conozco su dirección IP. He comprobado el\r
+nombre netbios de \$ENV{REMOTE_ADDR}\$tryIP, y he verificado que esa máquina\r
+no es \$host.\r
+<p>\r
+Hasta que vea \$host en una dirección DHCP concreta, sólo puede\r
+comenzar este proceso desde la propia máquina cliente.\r
+EOF\r
+\r
+########################\r
+# ok you can do it then\r
+########################\r
+\r
+$Lang{Backup_requested_on_DHCP__host} = "Copia de seguridad solicitada en DHCP \$host (\$In{hostIP}) por"\r
+                                     . " \$User desde \$ENV{REMOTE_ADDR}";\r
+\r
+$Lang{Backup_requested_on__host_by__User} = "Copia de seguridad solicitada en \$host por \$User";\r
+$Lang{Backup_stopped_dequeued_on__host_by__User} = "Copia de seguridad detenida/desprogramada en \$host por \$User";\r
+$Lang{log_User__User_downloaded_tar_archive_for__host} = "El usuario del registro \$User ha descargado un archivo Tar para \$host,"\r
+                           . " copia de seguridad \$num; los archivos eran: "\r
+                          . " \${join(\", \", \@fileListTrim)}";\r
+\r
+$Lang{log_User__User_downloaded_zip_archive_for__host}= "El usuario del registro \$User ha descargado un archivo Zip para \$host,"\r
+                           . " copia de seguridad \$num; los archivos eran: "\r
+                           . "\${join(\", \", \@fileListTrim)}";\r
+\r
+$Lang{Restore_requested_to_host__hostDest__backup___num} = "Restauración solicitada para el host \$hostDest, copia de seguridad #\$num,"\r
+            . " por \$User desde \$ENV{REMOTE_ADDR}";\r
+\r
+# -------------------------------------------------\r
+# ------- Stuff that was forgotten ----------------\r
+# -------------------------------------------------\r
+\r
+$Lang{Status} = "Estado";\r
+$Lang{PC_Summary} = "Resumen PC";\r
+$Lang{LOG_file} = "Archivo Registro";\r
+$Lang{Old_LOGs} = "Registros antiguos";\r
+$Lang{Email_summary} = "Resumen correo";\r
+$Lang{Config_file} = "Archivo configuración";\r
+$Lang{Hosts_file} = "Archivo Hosts";\r
+$Lang{Current_queues} = "Colas actuales";\r
+$Lang{Documentation} = "Documentación";\r
+\r
+$Lang{Host_or_User_name} = "<small>Host o usuario:</small>";\r
+$Lang{Go} = "Aceptar";\r
+$Lang{Hosts} = "Hosts";\r
+\r
+$Lang{This_PC_has_never_been_backed_up} = "<h2> !Nunca se ha hecho copia de seguridad de este PC! </h2>\n";\r
+$Lang{This_PC_is_used_by} = "<li>This PC es utilizado por \${UserLink(\$user)}";\r
+\r
+# ------------\r
+$Lang{Last_email_sent_to__was_at___subject} = <<EOF;\r
+<li>El último mensaje enviado a  \${UserLink(\$user)} fué a las \$mailTime, asunto "\$subj".\r
+EOF\r
+# ------------\r
+$Lang{The_command_cmd_is_currently_running_for_started} = <<EOF;\r
+<li>El comando \$cmd está ejecutandose para \$host, comenzado a \$startTime.\r
+EOF\r
+\r
+# -----------\r
+$Lang{Host_host_is_queued_on_the_background_queue_will_be_backed_up_soon} = <<EOF;\r
+<li>El host \$host está en cola en la cola en segundo plano (pronto tendrá copia de seguridad).\r
+EOF\r
+\r
+# ----------\r
+$Lang{Host_host_is_queued_on_the_user_queue__will_be_backed_up_soon} = <<EOF;\r
+<li>Host \$host está en cola en la cola de usuarios (pronto tendrá copia de seguridad).\r
+EOF\r
+\r
+# ---------\r
+$Lang{A_command_for_host_is_on_the_command_queue_will_run_soon} = <<EOF;\r
+<li>Un comando para \$host está en la cola de comandos (se ejecutará pronto).\r
+EOF\r
+\r
+# --------\r
+$Lang{Last_status_is_state_StatusHost_state_reason_as_of_startTime} = <<EOF;\r
+<li>El último estado fué \"\$Lang->{\$StatusHost{state}}\"\$reason a las \$startTime.\r
+EOF\r
+\r
+# --------\r
+$Lang{Last_error_is____EscHTML_StatusHost_error} = <<EOF;\r
+<li>El último error fué \"\${EscHTML(\$StatusHost{error})}\"\r
+EOF\r
+\r
+# ------\r
+$Lang{Pings_to_host_have_failed_StatusHost_deadCnt__consecutive_times} = <<EOF;\r
+<li>Los pings a \$host han fallado \$StatusHost{deadCnt} veces consecutivas.\r
+EOF\r
+\r
+# -----\r
+$Lang{Prior_to_that__pings} = "Antes de eso, pings";\r
+\r
+# -----\r
+$Lang{priorStr_to_host_have_succeeded_StatusHostaliveCnt_consecutive_times} = <<EOF;\r
+<li>\$priorStr a \$host han tenido éxito \$StatusHost{aliveCnt}\r
+        veces consecutivas.\r
+EOF\r
+\r
+$Lang{Because__host_has_been_on_the_network_at_least__Conf_BlackoutGoodCnt_consecutive_times___} = <<EOF;\r
+<li>Dado que \$host ha estado en la red al menos \$Conf{BlackoutGoodCnt}\r
+veces consecutivas, no se le realizará copia de seguridad desde \$t0 hasta \$t1 en \$days.\r
+EOF\r
+\r
+$Lang{Backups_are_deferred_for_hours_hours_change_this_number} = <<EOF;\r
+<li>Las copias de seguridad se retrasarán durante \$hours hours\r
+(<a href=\"\$MyURL?action=Stop/Dequeue%20Backup&host=\$host\">Cambie este número</a>).\r
+EOF\r
+\r
+$Lang{tryIP} = " y \$StatusHost{dhcpHostIP}";\r
+\r
+$Lang{Host_Inhost} = "Host \$In{host}";\r
+\r
+$Lang{checkAll} = <<EOF;\r
+<tr bgcolor="#ffffcc"><td>\r
+<input type="checkbox" name="allFiles" onClick="return checkAll('allFiles');">&nbsp;Seleccionar todo\r
+</td><td colspan="5" align="center">\r
+<input type="submit" name="Submit" value="Restaurar los archivos seleccionados">\r
+</td></tr>\r
+EOF\r
+\r
+$Lang{fileHeader} = <<EOF;\r
+    <tr bgcolor="\$Conf{CgiHeaderBgColor}"><td align=center> Nombre</td>\r
+       <td align="center"> Tipo</td>\r
+       <td align="center"> Modo</td>\r
+       <td align="center"> Nº</td>\r
+       <td align="center"> Tamaño</td>\r
+       <td align="center"> Hora Mod.</td>\r
+    </tr>\r
+EOF\r
+\r
+$Lang{Home} = "Principal";\r
+$Lang{Last_bad_XferLOG} = "Ultimo error en registro de transferencia";\r
+$Lang{Last_bad_XferLOG_errors_only} = "Ultimo error en registro de transferencia (errores&nbsp;sólo)";\r
+\r
+$Lang{This_display_is_merged_with_backup} = <<EOF;\r
+<li> Esta pantalla está unida a la copia de seguridad Nº\$numF.\r
+EOF\r
+\r
+$Lang{Visit_this_directory_in_backup} = <<EOF;\r
+<li> Explorar este directorio en copia de seguridad Nº\$otherDirs.\r
+EOF\r
+\r
+$Lang{Restore_Summary} = <<EOF;\r
+\${h2("Resumen de Restauración")}\r
+<p>\r
+Haga click en el número de restauración para ver sus detalles.\r
+<table border>\r
+<tr><td align="center"> Restauración Nº </td>\r
+    <td align="center"> Resultado </td>\r
+    <td align="right"> Fecha Inicio</td>\r
+    <td align="right"> Dur/mins</td>\r
+    <td align="right"> Nº Archivos </td>\r
+    <td align="right"> MB </td>\r
+    <td align="right"> Nº Err. Tar </td>\r
+    <td align="right"> Nº Err. Transf.#xferErrs </td>\r
+</tr>\r
+\$restoreStr\r
+</table>\r
+<p>\r
+EOF\r
+\r
+$Lang{BackupPC__Documentation} = "BackupPC: Documentacion";\r
+\r
+$Lang{No} = "no";\r
+$Lang{Yes} = "si";\r
+\r
+$Lang{The_directory_is_empty} = <<EOF;\r
+<tr><td bgcolor="#ffffff">El directorio \${EscHTML(\$dirDisplay)} está vacio\r
+</td></tr>\r
+EOF\r
+\r
+#$Lang{on} = "activo";\r
+$Lang{off} = "inactivo";\r
+\r
+$Lang{full} = "completo";\r
+$Lang{incremental} = "incremental";\r
+\r
+$Lang{failed} = "fallido";\r
+$Lang{success} = "éxito";\r
+$Lang{and} = "y";\r
+\r
+# ------\r
+# Hosts states and reasons\r
+$Lang{Status_idle} = "inactivo";\r
+$Lang{Status_backup_starting} = "comenzando copia de seguridad";\r
+$Lang{Status_backup_in_progress} = "copia de seguridad ejecutándose";\r
+$Lang{Status_restore_starting} = "comenzando restauración";\r
+$Lang{Status_restore_in_progress} = "restauración ejecutándose";\r
+$Lang{Status_link_pending} = "conexión pendiente";\r
+$Lang{Status_link_running} = "conexión en curso";\r
+\r
+$Lang{Reason_backup_done} = "copia de seguridad realizada";\r
+$Lang{Reason_restore_done} = "restauración realizada";\r
+$Lang{Reason_nothing_to_do} = "nada por hacer";\r
+$Lang{Reason_backup_failed} = "copia de seguridad fallida";\r
+$Lang{Reason_no_ping} = "no hay ping";\r
+$Lang{Reason_backup_canceled_by_user} = "copia cancelada por el usuario";\r
+\r
+# ---------\r
+# Email messages\r
+\r
+# No backup ever\r
+$Lang{EMailNoBackupEverSubj} = "BackupPC: ningúna copia de \$host ha tenido éxito";\r
+$Lang{EMailNoBackupEverMesg} = <<'EOF';\r
+To: $user$domain\r
+cc:\r
+Subject: $subj\r
+\r
+Estimado $userName,\r
+\r
+Su PC ($host) nunca ha completado una copia de seguridad mediante nuestro\r
+programa de copias de seguridad. Las copias de seguridad deberían ejecutarse\r
+automáticamente cuando su PC se conecta a la red. Debería contactar con su\r
+soporte técnico si:\r
+\r
+  - Su ordenador ha estado conectado a la red con regularidad. Esto implicaría\r
+    que existe algún problema de instalación o configuración que impide que se\r
+    realicen las copias de seguridad.\r
+\r
+  - No desea realizar copias de seguridad y no quiere recibir más mensajes\r
+    como éste.\r
+\r
+De no ser así, asegúrese de que su PC está conectado a la red la próxima vez\r
+que esté en la oficina.\r
+\r
+Saludos:\r
+Agente BackupPC\r
+http://backuppc.sourceforge.net\r
+EOF\r
+\r
+# No recent backup\r
+$Lang{EMailNoBackupRecentSubj} = "BackupPC: no hay copias de seguridad recientes de \$host";\r
+$Lang{EMailNoBackupRecentMesg} = <<'EOF';\r
+To: $user$domain\r
+cc:\r
+Subject: $subj\r
+\r
+Estimado $userName,\r
+\r
+No se ha podido completar ninguna copia de seguridad de su PC ($host) durante\r
+$days días.\r
+Su PC ha realizado copias de seguridad correctas $numBackups veces desde\r
+$firstTime hasta hace $days días.\r
+Las copias de seguridad deberían efectuarse automáticamente cuando su PC está\r
+conectado a la red.\r
+\r
+Si su PC ha estado conectado durante algunas horas a la red durante los últimos\r
+$days días debería contactar con su soporte técnico para ver porqué las copias\r
+de seguridad no funcionan adecuadamente.\r
+\r
+Por otro lado, si está fuera de la oficina, no hay mucho que se pueda hacer al\r
+respecto salvo copiar manualmente los archivos especialmente críticos a otro\r
+soporte físico. Debería estar al corriente de que cualquier archivo que haya\r
+creado o modificado en los últimos $days días (incluyendo todo el correo nuevo\r
+y archivos adjuntos) no pueden ser restaurados si su disco se avería.\r
+\r
+Saludos:\r
+Agente BackupPC\r
+http://backuppc.sourceforge.net\r
+EOF\r
+\r
+# Old Outlook files\r
+$Lang{EMailOutlookBackupSubj} = "BackupPC: Los archivos de Outlook de \$host necesitan ser copiados";\r
+$Lang{EMailOutlookBackupMesg} = <<'EOF';\r
+To: $user$domain\r
+cc:\r
+Subject: $subj\r
+\r
+Estimado $userName,\r
+\r
+Los archivos de Outlook de su PC tienen $howLong.\r
+Estos archivos contienen todo su correo, adjuntos, contactos e información de\r
+su agenda. Su PC ha sido correctamente salvaguardado $numBackups veces desde\r
+$firstTime hasta hace $lastTime días.  Sin embargo, Outlook bloquea todos sus\r
+archivos mientras funciona, impidiendo que pueda hacerse copia de seguridad de\r
+los mismos.\r
+\r
+Se le recomienda hacer copia de seguridad de los archivos de Outlook cuando esté\r
+conectado a la red cerrando Outlook y el resto de aplicaciones y utilizando su\r
+navegador de internet. Haga click en este vínculo:\r
+\r
+    $CgiURL?host=$host               \r
+\r
+Seleccione "Comenzar copia de seguridad incremental" dos veces para comenzar\r
+una neva copia de seguridad incremental.\r
+Puede seleccionar "Volver a la página de $host " y hacer click en "refrescar"\r
+para ver el estado del proceso de copia de seguridad. Debería llevarle sólo\r
+unos minutos completar el proceso.\r
+\r
+Saludos:\r
+Agente BackupPC\r
+http://backuppc.sourceforge.net\r
+EOF\r
+\r
+$Lang{howLong_not_been_backed_up} = "no se le ha realizado una copia de seguridad con éxito";\r
+$Lang{howLong_not_been_backed_up_for_days_days} = "no se le ha realizado una copia de seguridad durante \$days días";\r
+\r
+#end of lang_en.pm\r
index fde4f5d..8ec9fd2 100644 (file)
@@ -56,7 +56,7 @@
 #
 #========================================================================
 #
-# Version 2.0.0_CVS, released 3 Feb 2003.
+# Version 2.0.0beta0, released 23 Feb 2003.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -108,11 +108,27 @@ sub write
     return if ( $a->{eof} );
     $a->{data} .= $$dataRef if ( defined($dataRef) );
     return if ( length($a->{data}) < $BufSize && defined($dataRef) );
-    if ( !defined($a->{digest}) && $a->{fileSize} > 0 ) {
+
+    #
+    # Correct the fileSize if it is wrong (rsync might transfer
+    # a file whose length is different to the length sent with the
+    # file list if the file changes between the file list sending
+    # and the file sending).  Here we only catch the case where
+    # we haven't computed the digest (ie: we have written no more
+    # than $BufSize.  We catch the big file case below.
+    #
+    if ( !defined($dataRef) && !defined($a->{digest})
+               && $a->{fileSize} != length($a->{data}) ) {
+       $a->{fileSize} = length($a->{data});
+    }
+
+    if ( !defined($a->{digest}) && length($a->{data}) > 0 ) {
         #
         # build a list of all the candidate matching files
         #
         my $md5 = Digest::MD5->new;
+       $a->{fileSize} = length($a->{data})
+                           if ( $a->{fileSize} < length($a->{data}) );
         $a->{digest} = $a->{bpc}->Buffer2MD5($md5, $a->{fileSize}, \$a->{data});
         if ( !defined($a->{base} = $a->{bpc}->MD52Path($a->{digest},
                                                        $a->{compress})) ) {
@@ -151,7 +167,7 @@ sub write
         }
     }
     my $dataLen = length($a->{data});
-    if ( !defined($a->{fhOut}) && $a->{fileSize} > 0 ) {
+    if ( !defined($a->{fhOut}) && length($a->{data}) > 0 ) {
         #
         # See if the new chunk of data continues to match the
         # candidate files.
@@ -257,6 +273,74 @@ sub write
     foreach my $f ( @{$a->{files}} ) {
         $f->{fh}->close();
     }
+
+    #
+    # Make sure the fileSize was correct.  See above for comments about
+    # rsync.
+    #
+    if ( $a->{nWrite} != $a->{fileSize} ) {
+       #
+       # Oops, fileSize was wrong, so our MD5 digest was wrong and our
+       # effort to match files likely failed.  This is ugly, but our
+       # only choice at this point is to re-write the entire file with
+       # the correct length.  We need to rename the file, open it for
+       # reading, and then re-write the file with the correct length.
+       #
+
+       #print("Doing big file fixup ($a->{fileSize} != $a->{nWrite})\n");
+
+       my($fh, $fileName);
+       $a->{fileSize} = $a->{nWrite};
+       if ( $a->{fileName} =~ /(.*)\// ) {
+           $fileName = $1;
+       } else {
+           $fileName = ".";
+       }
+
+       #
+       # Find a unique target temporary file name
+       #
+       my $i = 0;
+       while ( -f "$fileName/t$$.$i" ) {
+           $i++;
+       }
+       $fileName = "$fileName/t$$.$i";
+        $a->{fhOut}->close();
+       if ( !rename($a->{fileName}, $fileName)
+         || !defined($fh = BackupPC::FileZIO->open($fileName, 0,
+                                            $a->{compress})) ) {
+            push(@{$a->{errors}}, "Can't rename $a->{fileName} -> $fileName"
+                               . " or open during size fixup\n");
+       } else {
+           my $poolWrite = BackupPC::PoolWrite->new($a->{bpc}, $a->{fileName},
+                                       $a->{fileSize}, $a->{compress});
+           my $nRead = 0;
+
+           while ( $nRead < $a->{fileSize} ) {
+               my $thisRead = $a->{fileSize} - $nRead < $BufSize
+                            ? $a->{fileSize} - $nRead : $BufSize;
+               my $data;
+               my $n = $fh->read(\$data, $thisRead);
+               if ( $n != $thisRead ) {
+                   push(@{$a->{errors}},
+                               "Unable to read $thisRead bytes during resize"
+                              . " from temp $fileName (got $n)\n");
+                   last;
+               }
+               $poolWrite->write(\$data);
+               $nRead += $thisRead;
+           }
+           $fh->close;
+           unlink($fileName);
+           if ( @{$a->{errors}} ) {
+               $poolWrite->close;
+               return (0, $a->{digest}, -s $a->{fileName}, $a->{errors});
+           } else {
+               return $poolWrite->close;
+           }
+       }
+    }
+
     if ( $a->{fileSize} == 0 ) {
         #
         # Simply create an empty file
index f6ad740..1d647ac 100644 (file)
@@ -29,7 +29,7 @@
 #
 #========================================================================
 #
-# Version 2.0.0_CVS, released 3 Feb 2003.
+# Version 2.0.0beta0, released 23 Feb 2003.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -369,7 +369,9 @@ sub run
     } else {
        $t->{xferOK} = 0;
     }
-    $t->{xferErrCnt} = $stats->{remoteErrCnt};
+    $t->{xferErrCnt} = $stats->{remoteErrCnt}
+                    + $stats->{childStats}{errorCnt}
+                    + $stats->{parentStats}{errorCnt};
     $t->{byteCnt}    = $stats->{childStats}{TotalFileSize}
                     + $stats->{parentStats}{TotalFileSize};
     $t->{fileCnt}    = $stats->{childStats}{TotalFileCnt}
index f75fbbb..fdc3625 100644 (file)
@@ -12,7 +12,7 @@
 #
 #========================================================================
 #
-# Version 2.0.0_CVS, released 3 Feb 2003.
+# Version 2.0.0beta0, released 23 Feb 2003.
 #
 # See http://backuppc.sourceforge.net.
 #
@@ -65,6 +65,7 @@ sub new
        attrib       => {},
        logHandler   => \&logHandler,
        stats        => {
+           errorCnt          => 0,
            TotalFileCnt      => 0,
            TotalFileSize     => 0,
            ExistFileCnt      => 0,
@@ -113,6 +114,7 @@ sub csumStart
                                                       0,
                                                       $attr->{compress})) ) {
         $fio->log("Can't open $attr->{fullPath} (name=$f->{name})");
+       $fio->{stats}{errorCnt}++;
         return -1;
     }
     if ( $needMD4) {
@@ -133,14 +135,16 @@ sub csumGet
 
     return if ( !defined($fio->{fh}) );
     if ( $fio->{fh}->read(\$fileData, $blockSize * $num) <= 0 ) {
-        return;
+       $fio->log("$fio->{file}{name}: csumGet is at EOF - zero padding\n");
+       $fio->{stats}{errorCnt}++;
+       $fileData = pack("c", 0) x ($blockSize * $num);
     }
     $fio->{csumDigest}->add($fileData) if ( defined($fio->{csumDigest}) );
     $fio->log(sprintf("%s: getting csum ($num,$csumLen,%d,0x%x)\n",
                             $fio->{file}{name},
                             length($fileData),
                             $fio->{checksumSeed}))
-                if ( $fio->{logLevel} >= 10 );
+                if ( $fio->{logLevel} >= 9 );
     return $fio->{digest}->blockDigest($fileData, $blockSize,
                                          $csumLen, $fio->{checksumSeed});
 }
@@ -175,6 +179,7 @@ sub readStart
                                            0,
                                            $attr->{compress})) ) {
         $fio->log("Can't open $attr->{fullPath} (name=$f->{name})");
+       $fio->{stats}{errorCnt}++;
         return;
     }
     $fio->log("$f->{name}: opened for read") if ( $fio->{logLevel} >= 4 );
@@ -489,6 +494,7 @@ sub makePath
     File::Path::mkpath($path, 0, 0777) if ( !-d $path );
     return $fio->attribSet($f) if ( -d $path );
     $fio->log("Can't create directory $path");
+    $fio->{stats}{errorCnt}++;
     return -1;
 }
 
@@ -678,7 +684,7 @@ sub fileDeltaRxNext
                                           $rxOutFile, $fio->{rxFile}{size},
                                            $fio->{xfer}{compress});
         $fio->log("$fio->{rxFile}{name}: opening output file $rxOutFile")
-                        if ( $fio->{logLevel} >= 10 );
+                        if ( $fio->{logLevel} >= 9 );
         $fio->{rxOutFile} = $rxOutFile;
         $fio->{rxOutFileRel} = $rxOutFileRel;
         $fio->{rxDigest} = File::RsyncP::Digest->new;
@@ -704,6 +710,7 @@ sub fileDeltaRxNext
                                                    0,
                                                    $attr->{compress})) ) {
                     $fio->log("Can't open $attr->{fullPath}");
+                   $fio->{stats}{errorCnt}++;
                     return -1;
                 }
                 if ( $attr->{size} < 10 * 1024 * 1024 ) {
@@ -715,6 +722,9 @@ sub fileDeltaRxNext
                     while ( $fh->read(\$data, 10 * 1024 * 1024) > 0 ) {
                         $fio->{rxInData} .= $data;
                     }
+                   $fio->log("$attr->{fullPath}: cached all $attr->{size}"
+                           . " bytes")
+                                   if ( $fio->{logLevel} >= 9 );
                 } else {
                     #
                     # Create and write a temporary output file
@@ -723,20 +733,27 @@ sub fileDeltaRxNext
                                     if  ( -f "$fio->{outDirSh}RStmp" );
                     if ( open(F, "+>", "$fio->{outDirSh}RStmp") ) {
                         my $data;
+                       my $byteCnt = 0;
                         while ( $fh->read(\$data, 1024 * 1024) > 0 ) {
                             if ( syswrite(F, $data) != length($data) ) {
                                 $fio->log(sprintf("Can't write len=%d to %s",
                                      length($data) , "$fio->{outDirSh}RStmp"));
                                 $fh->close;
+                               $fio->{stats}{errorCnt}++;
                                 return -1;
                             }
+                           $byteCnt += length($data);
                         }
                         $fio->{rxInFd} = *F;
                         $fio->{rxInName} = "$fio->{outDirSh}RStmp";
                         seek($fio->{rxInFd}, 0, 0);
+                       $fio->log("$attr->{fullPath}: copied $byteCnt,"
+                               . "$attr->{size} bytes to $fio->{rxInName}")
+                                       if ( $fio->{logLevel} >= 9 );
                     } else {
                         $fio->log("Unable to open $fio->{outDirSh}RStmp");
                         $fh->close;
+                       $fio->{stats}{errorCnt}++;
                         return -1;
                     }
                 }
@@ -747,6 +764,7 @@ sub fileDeltaRxNext
                     $fio->{rxInName} = $attr->{fullPath};
                 } else {
                     $fio->log("Unable to open $attr->{fullPath}");
+                   $fio->{stats}{errorCnt}++;
                     return -1;
                 }
             }
@@ -757,7 +775,8 @@ sub fileDeltaRxNext
                         if ( $fio->{logLevel} >= 9 );
         my $seekPosn = $fio->{rxMatchBlk} * $fio->{rxBlkSize};
         if ( defined($fio->{rxInFd}) && !seek($fio->{rxInFd}, $seekPosn, 0) ) {
-            $fio->log("Unable to seek $attr->{fullPath} to $seekPosn");
+            $fio->log("Unable to seek $attr->{rxInName} to $seekPosn");
+           $fio->{stats}{errorCnt}++;
             return -1;
         }
         my $cnt = $fio->{rxMatchNext} - $fio->{rxMatchBlk};
@@ -774,10 +793,14 @@ sub fileDeltaRxNext
                 $data = substr($fio->{rxInData}, $seekPosn, $len);
                $seekPosn += $len;
             } else {
-                if ( sysread($fio->{rxInFd}, $data, $len) != $len ) {
-                    $fio->log("Unable to read $len bytes from"
-                              . " $fio->{rxInName} "
-                              . "($i,$thisCnt,$fio->{rxBlkCnt})");
+               my $got = sysread($fio->{rxInFd}, $data, $len);
+                if ( $got != $len ) {
+                   my $inFileSize = -s $fio->{rxInName};
+                    $fio->log("Unable to read $len bytes from $fio->{rxInName}"
+                            . " got=$got, seekPosn=$seekPosn"
+                            . " ($i,$thisCnt,$fio->{rxBlkCnt},$inFileSize"
+                           . ",$attr->{size})");
+                   $fio->{stats}{errorCnt}++;
                     return -1;
                 }
             }
@@ -835,7 +858,8 @@ sub fileDeltaRxDone
            }
             $fh->close;
         } else {
-           # ERROR
+           $fio->log("cannot open $attr->{fullPath} for MD4 check");
+           $fio->{stats}{errorCnt}++;
        }
         $fio->log("$name got exact match")
                         if ( $fio->{logLevel} >= 5 );
@@ -893,6 +917,7 @@ sub fileDeltaRxDone
                             . $fio->{bpc}->fileNameMangle($name);
             if ( !link($attr->{fullPath}, $rxOutFile) ) {
                 $fio->log("Unable to link $attr->{fullPath} to $rxOutFile");
+               $fio->{stats}{errorCnt}++;
                 return -1;
             }
            #
@@ -953,17 +978,19 @@ sub fileListEltSend
                    #
                    $extraAttribs = { rdev => $1 * 256 + $2 };
                } else {
-                   # ERROR
-                   $fio->log("$name: unexpected file contents $str");
+                   $fio->log("$name: unexpected special file contents $str");
+                   $fio->{stats}{errorCnt}++;
                }
            } else {
                # ERROR
                $fio->log("$name: can't read exactly $a->{size} bytes");
+               $fio->{stats}{errorCnt}++;
            }
            $fh->close;
        } else {
            # ERROR
            $fio->log("$name: can't open");
+           $fio->{stats}{errorCnt}++;
        }
     }
     my $f = {