Advertisement
Guest User

climbo

a guest
Jul 25th, 2009
390
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