Advertisement
Guest User

climbo

a guest
Jul 25th, 2009
371
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 12.66 KB | None | 0 0
  1. #!/usr/bin/perl -T
  2.  
  3. ##################################################################
  4. # enviaform.cgi     PROCESAMIENTO DE FORMULARIOS
  5. #
  6. # (c) Ivan Nieto Perez
  7. # Este CGI puede descargarse de El Codigo:
  8. # http://www.elcodigo.com
  9. #
  10. # Puede usarse libremente y modificarse siempre que se conserve
  11. # esta cabecera intacta
  12. #
  13. ##################################################################
  14.  
  15. ############## SPECIAL FORM VARIABLES ############################
  16. # asunto        Asunto del mensaje de correo. Si no se indica, quedará en blanco.
  17. # remitente     Direccion de correo del remitente (campo from). Si no se indica, se usa $DIRECCION_FROM.
  18. # obligatorios      Lista de campos obligatorios, separados por comas. Si no se indica, ninguno es obligatorio.
  19. # enviables     [OBLIGATORIO] Lista (y orden) de los campos a enviar en el mensaje de correo, separados por comas.
  20. # url_exito     URL a la que redirigir si exito en el envio. Si no se indica, se muestra pagina por defecto.
  21. # formato_fecha     Formato para la fecha. Si no se indica, formato 2
  22. #           1 >> Jueves, 2 de Enero de 2000, a las 20:30:12
  23. #           2 >> 2 de Enero de 2000, a las 20:30:12
  24. #           3 >> 02/01/2000 - 20:30:12
  25. # responder     A 1 se enviara un mensaje de agradecimiento a la direccion remitente. Si no se especifica, a 0.
  26. ##################################################################
  27.  
  28. use Socket;
  29.  
  30. #####################################################################
  31. # CONFIGURACION
  32.  
  33. # Direcciones de correo de los destinatarios (campo to), separadas por comas sin espacios en blanco
  34. $DIRECCIONES_TO = 'formulario@mi_dominio.com';
  35.  
  36. # Direccion del remitente (campo from) a usar cuando no existe campo remitente en el formulario
  37. $DIRECCION_FROM = 'webmaster@mi_dominio.com';
  38.  
  39. # Ruta y nombre del fichero con el texto del mensaje de respuesta (si el campo responder del formulario vale 1)
  40. $RESPUESTA = 'respuesta.txt';
  41.  
  42. # Dominios desde los que puede ejecutarse el CGI separados por comas sin espacios en blanco
  43. $DOMINIOS_VALIDOS = 'elcodigo.net,elcodigo.com';
  44.  
  45. # Indica si se desea crear fichero de log de accesos: a 1, crea log
  46. $LOG_ACCESOS = 0;
  47.  
  48. # Ruta y nombre del fichero de log de accesos (a usar solo si $LOG_ACCESOS = 1)
  49. $FICHERO_LOG = 'log_accesos.txt';
  50.  
  51. # Ruta y nombre de sendmail (el valor de ejemplo es el mas habitual, dejar asi si no se sabe cual es)
  52. $PROGRAMA_SENDMAIL = '/usr/sbin/sendmail -t';
  53.  
  54. # FIN CONFIGURACION
  55. #####################################################################
  56.  
  57. #####################################################################
  58. # DEFINICIONES
  59. # Tipos de error
  60. @TipoError = (
  61.       "Error abriendo fichero para lectura.",
  62.       "Error abriendo fichero para escritura.",
  63.       "Este CGI no puede ser invocado directamente en la barra de direcciones del navegador.",
  64.       "Faltan parámetros en la llamada al CGI.",
  65.       "Algunos campos obligatorios no han sido cumplimentados. Pulse RETROCEDER para volver a intentarlo.",
  66.       "Este CGI no puede ejecutarse desde este dominio o pagina.",
  67.       "Hay caracteres no permitidos en alguno de los parametros enviados al CGI.",
  68.       "La direccion de correo electronico introducida no es valida. Pulse RETROCEDER para volver a intentarlo.",
  69.       "Error en el envio del mensaje."
  70. );
  71.  
  72. $LOCK_EX = 2;
  73. $LOCK_UN = 8;
  74.  
  75. #lista de destinatarios
  76. @lista_destinatarios = split(/,/, $DIRECCIONES_TO);
  77.  
  78. # A 1 si se desea que escriba en un fichero en vez de enviar un mensaje (para correccion errores)
  79. $debug = 0;
  80. $MAIL_FILE = 'mail.txt';
  81.  
  82. #####################################################################
  83.  
  84. #MAIN
  85.  
  86. #guarda datos de cada acceso en el log si necesario
  87. &guarda_log if ( $LOG_ACCESOS == 1);  
  88.  
  89. #recibe los datos del formulario via POST y los decodifica
  90. &obtiene_datos_formulario;
  91.  
  92. #comprueba si el dominio es valido para ejecutar el script
  93. &comprueba_dominio;
  94.  
  95. #valida los datos obtenidos del formulario
  96. &valida_datos_formulario;
  97.  
  98. #obtiene la fecha actual
  99. $fecha_actual = &obtiene_fecha( $CAMPOS{'formato_fecha'} );
  100.  
  101. #escribe o envia los datos del formulario
  102. &construye_mensaje;
  103.  
  104. #respuesta confirmacion al usuario que envia los datos
  105. &envia_respuesta;
  106.    
  107. #pagina HTML a mostrar tras el envio del formulario
  108. if ( $CAMPOS{'url_exito'} ne '' ){
  109.     print "Location: $CAMPOS{'url_exito'}\n\n";
  110. } else {
  111.     &pagina_despues_envio;
  112. }
  113.  
  114. exit;
  115.  
  116.  
  117. ##################################################################
  118. sub construye_mensaje {
  119.  
  120.     my $mensaje = '';
  121.     $mensaje .= "El $fecha_actual,\n";
  122.     $mensaje .= "desde la dirección IP $ENV{'REMOTE_ADDR'}\n";
  123.     $mensaje .= "ha sido enviada la siguiente información:\n";
  124.  
  125.     foreach $campo_a_mostrar (@lista_enviables) {
  126.         $mensaje .= "$campo_a_mostrar = $CAMPOS{$campo_a_mostrar}\n";
  127.     }
  128.  
  129.     foreach $email (@lista_destinatarios) {
  130.         #invoca la funcion de envio
  131.         &envia_mensaje( $CAMPOS{'asunto'}, $CAMPOS{'remitente'}, $email, '', '', $mensaje);
  132.     }
  133. }
  134.  
  135. ##################################################################
  136. sub obtiene_datos_formulario {
  137.    
  138.     my $temp = '';
  139.     my $a, $b;
  140.  
  141.     #lee estandar imput
  142.     read(STDIN, $temp, $ENV{'CONTENT_LENGTH'});
  143.  
  144.     for (split(/\&/, $temp)) {
  145.         next if (!$_);
  146.         tr/+/ /;
  147.         s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
  148.         s/\r//g;
  149.         $b =~ s/<!--(.|\n)*-->//g;
  150.         ($a, $b) = split(/=/);
  151.         $CAMPOS{$a} = $b;
  152.     }
  153.  
  154. }
  155.  
  156. ##################################################################
  157. sub valida_datos_formulario {
  158.  
  159.     # obtiene la lista de campos a enviar
  160.     if ( $CAMPOS{'enviables'} ne '' ) {
  161.         $CAMPOS{'enviables'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g;
  162.         $CAMPOS{'enviables'} =~ s/(\s+)?\n+(\s+)?//g;
  163.         if ( $CAMPOS{'enviables'} =~ /[^a-zA-Z0-9_\-\,]+/ ) { &muestra_error(7, 'enviables'); }
  164.         @lista_enviables = split(/,/, $CAMPOS{'enviables'});
  165.     } else {
  166.         # unico campo obligatorio para el CGI
  167.         &muestra_error(4);
  168.     }
  169.    
  170.     # validacion de los campos obligatorios definidos por el usuario
  171.     if ( $CAMPOS{'obligatorios'} ne '' ) {
  172.         $CAMPOS{'obligatorios'} =~ s/(\s+|\n)?,(\s+|\n)?/,/g;
  173.         $CAMPOS{'obligatorios'} =~ s/(\s+)?\n+(\s+)?//g;
  174.         if ( $CAMPOS{'obligatorios'} =~ /[^a-zA-Z0-9_\-\,]+/ ) { &muestra_error(7, 'obligatorios'); }
  175.         @lista_obligatorios = split(/,/,$CAMPOS{'obligatorios'});
  176.         #comprueba lista de campos requeridos
  177.         foreach $campo_obligatorio (@lista_obligatorios) {
  178.             if ( $CAMPOS{$campo_obligatorio} eq '' ) {
  179.                 &muestra_error(5, $campo_obligatorio );
  180.             }
  181.         }
  182.     }
  183.    
  184.     # formato por defecto para la fecha, si no especificado: 2 de Enero de 2000, a las 20:30:12
  185.     if ( $CAMPOS{'formato_fecha'} eq '' ) {
  186.         $CAMPOS{'formato_fecha'} = '2';
  187.     } else {
  188.         if ( $CAMPOS{'formato_fecha'} =~ /[^0-9]+/ ) { &muestra_error(7, 'formato_fecha'); }
  189.     }
  190.    
  191.     # si no se especifica el campo responder, no se responde
  192.     if ( $CAMPOS{'responder'} eq '' ) {
  193.         $CAMPOS{'responder'} = 0;
  194.     } else {
  195.         if ( $CAMPOS{'responder'} =~ /[^0-9]+/ ) { &muestra_error(7, 'responder'); }
  196.     }
  197.  
  198.     # si no existe remitente, se asigna por defecto, y no se envia respuesta
  199.     if ($CAMPOS{'remitente'} eq '') {
  200.         $CAMPOS{'remitente'} = $DIRECCION_FROM;
  201.         $CAMPOS{'responder'} = 0;
  202.     } else {
  203.         &muestra_error(8) if (&valida_email == 0);
  204.     }
  205.    
  206.     if ( $CAMPOS{'url_exito'} ne '' ) {
  207.         if ( $CAMPOS{'url_exito'} =~ /[^a-zA-Z0-9_\-\:\/\.]+/ ) { &muestra_error(7, 'url_exito'); }
  208.     }
  209.  
  210.     if ( $CAMPOS{'asunto'} ne '' ) {
  211.         if ( $CAMPOS{'asunto'} =~ /[^a-zA-Z0-9_\-\:\/\.\!\?\$\#\%\@\|\&\/\(\)\=\,\*\+\;\'\"\s\[\]]+/ ) { &muestra_error(7, 'asunto'); }
  212.     }  
  213. }
  214.  
  215. ##################################################################
  216. sub pagina_despues_envio {
  217.    
  218.     print "Content-type: text/html\n\n";
  219.     print <<__W2__;
  220. <html>
  221. <head>
  222. <title>Gracias por cumplimentar nuestro formulario</title>
  223. </head>
  224. <body>
  225. <h1>¡Gracias!</h1>
  226. <p>Su información ha sido enviada con éxito.</p>
  227. <p>Esta es la información enviada:</p>
  228. <p>
  229. __W2__
  230.  
  231.     foreach $itm (@lista_enviables) {
  232.     print <<__W2A__;
  233. $itm: $CAMPOS{$itm}
  234. <br>
  235. __W2A__
  236.     }
  237.  
  238. }
  239.  
  240.  
  241. ##################################################################
  242. sub envia_respuesta  {
  243.  
  244.     #solo envia mensaje de agradecimiento si el campo responder vale 1 y existe campo remitente
  245.     if ( ($CAMPOS{'remitente'} ne '') && ($CAMPOS{'responder'} eq '1') ) {
  246.        
  247.         my $asunto = 'Gracias por cumplimentar nuestro formulario';
  248.         my $mensaje_respuesta = '';
  249.         if ( ($RESPUESTA ne '') && ( open (AM,"< $RESPUESTA") ) ) {
  250.             while (<AM>) {
  251.                 chop $_;
  252.                 $mensaje_respuesta .= "$_\n";
  253.             }
  254.             close(AM);
  255.         } else {
  256.                 $mensaje_respuesta = "Gracias por cumplimentar nuestro formulario.\nEsperamos que vuelva a visitar nuestra página pronto.\n";
  257.         }
  258.  
  259.         $direccion_retorno = $lista_destinatarios[0];
  260.         &envia_mensaje($asunto, $direccion_retorno, $CAMPOS{'remitente'}, '', '', $mensaje_respuesta);
  261.     }
  262. }
  263.  
  264.  
  265. ##################################################################
  266. sub valida_email {
  267.     $testmail = $CAMPOS{'remitente'};
  268.     if ($testmail =~ / /) {
  269.         return 0;
  270.     }
  271.    
  272.     if (    $testmail =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/ ||
  273.         $testmail !~ /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/ ) {
  274.         return 0;
  275.     } else {
  276.         return 1;
  277.     }
  278. }
  279.  
  280.  
  281. ##################################################################
  282. sub envia_mensaje {
  283.  
  284.   local($subject, $from, $to, $cc, $bcc, $body) = @_;
  285.  
  286.   local($error) = '';
  287.  
  288.   # abre sendmail
  289.   if ( $debug ) {
  290.     open(MAIL, ">>$MAIL_FILE") or &muestra_error(2);
  291.   } else {
  292.     open (MAIL, "|$PROGRAMA_SENDMAIL") or &muestra_error(9);
  293.   }
  294.  
  295.   # construye cabecera del mensaje
  296.   print MAIL "To: <$to>\n";
  297.   print MAIL "From: <$from>\n";
  298.   print MAIL "Cc: <$cc>\n" if $cc;
  299.   print MAIL "Bcc: <$bcc>\n" if $bcc;
  300.   print MAIL "Subject: $subject\n";
  301.   print MAIL "\n";
  302.  
  303.   if ($body) {
  304.     print MAIL $body;
  305.   }
  306.  
  307.   print MAIL "\n";
  308.   close MAIL;
  309.  
  310. }
  311.  
  312.  
  313.  
  314. ##################################################################
  315. sub obtiene_fecha {
  316.  
  317.     local($formato) = @_;
  318.  
  319.         my @dias = ('Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado');
  320.         my @meses = ('Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre');
  321.     my $fecha = '';
  322.     my ($seg, $min, $hor, $diam, $mes, $ano,$wday, $dano, $isdst) = localtime(time);
  323.  
  324.     my $num_mes = $mes + 1;
  325.     my $copia_ano = ($ano % 100);
  326.    
  327.     $hor = "0$hor" if ($hor < 10);
  328.     $min = "0$min" if ($min < 10);
  329.     $seg = "0$seg" if ($seg < 10);
  330.     $ano = 1900 + $ano;
  331.    
  332.     if ($formato eq '1') {
  333.         # Ej.: Jueves, 2 de Enero de 2000, a las 20:30:12
  334.         $fecha = "$dias[$wday], $diam de $meses[$mes] de $ano a las $hor\:$min\:$seg";
  335.     } elsif ($formato eq '2') {
  336.         # Ej.: 2 de Enero de 2000, a las 20:30:12
  337.         $fecha = "$diam de $meses[$mes] de $ano a las $hor\:$min\:$seg";
  338.     } else {
  339.         # Ej.: 02/01/2000 - 20:30:12
  340.         $num_mes = "0$num_mes" if ($num_mes < 10);
  341.         $diam = "0$diam" if ($diam < 10);
  342.         $copia_ano = "0$copia_ano" if ($copia_ano < 10);
  343.         $fecha = "$diam/$num_mes/$copia_ano - $hor\:$min\:$seg";
  344.     }
  345.    
  346.     return $fecha;
  347. }
  348.  
  349.  
  350. ##################################################################
  351. sub comprueba_dominio {
  352.  
  353.   # Obtencion de la pagina desde la que se llama al CGI
  354.   my $pagina = "$ENV{'HTTP_REFERER'}";
  355.   if ( $pagina eq '' ) { &muestra_error(3); }
  356.   my ($http, $dominioypagina) = split(/\/\//,$pagina);  # Separa por //
  357.   my ($dominio, @resto) = split(/\//, $dominioypagina); # Separa por /
  358.  
  359.   # Correccion obtencion ruta - 19/7/2000
  360.   $resto = join("/", @resto);
  361.   $resto =~ s/[\w-_\.]*\.s{0,1}html{0,1}$//i;       # Elimina nombre pagina
  362.   $resto =~ s/\/{1,2}$//;                   # Elimina caracteres "/" al final
  363.  
  364.   # Comprobacion de dominio - 25/7/2000
  365.   my $domvalido = 0;
  366.   my (@lista_dominios_validos) = split(/,/, $DOMINIOS_VALIDOS); # Lista de dominios validos
  367.   foreach $dom (@lista_dominios_validos) {
  368.      if ( $dominio =~ /$dom/ ) { $domvalido = 1; last; }
  369.   }
  370.  
  371.   # Si el dominio no esta en la lista de validos, ERROR!
  372.   if ( $domvalido == 0 ) { &muestra_error(6); }
  373.  
  374. }
  375.  
  376.  
  377. ##################################################################
  378. sub muestra_error {
  379.     local($errn, $extrainfo) = @_;
  380.     print "Content-type: text/html\n\n";
  381.     print "<h2>¡Error!</h2>\n";
  382.     print "<p>Se ha producido el error $errn</p>\n";
  383.     print "<p>$TipoError[$errn - 1]</p>";
  384.     print "<p>$extrainfo</p>";
  385.     exit(0);
  386. }
  387.  
  388.  
  389. ##################################################################
  390. # Guarda datos en el log
  391. sub guarda_log {
  392.     my $fecha = &obtiene_fecha('3');   
  393.     open (LOGS, ">>$FICHERO_LOG") || &muestra_error(2);
  394.     &lock;
  395.     print LOGS "$ENV{HTTP_REFERER}|$ENV{REMOTE_ADDR}|$fecha\n";
  396.     &unlock;
  397.     close (LOGS);
  398. }
  399.  
  400. ##################################################################
  401. sub lock {
  402.   local($file)=@_;
  403.   flock($file, $LOCK_EX);
  404. }
  405.  
  406.  
  407. ##################################################################
  408. sub unlock {
  409.   local($file)=@_;
  410.   flock($file, $LOCK_UN);
  411. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement