Queremos pasar parámetros de entrada y cargar un archivo desde un navegador web a un programa Fortran en un servidor web Apache, pero no hemos podido encontrar mucha información útil sobre cómo hacerlo. Nuestro objetivo es no utilizar bibliotecas, ni Perl, ni nada más que el estándar f77 tal como viene con FreeBSD. Existen algunas limitaciones debido a la falta de generalidad en f77 I / O, pero hace lo que necesitamos de manera bastante simple y en unas pocas líneas de código.
Aquí hay un ejemplo de una página que pide dos valores, pasándolos a un programa fortran que escribe una respuesta HTML:
<html>
Por favor llena cada casilla con 4 caracteres ..
<Método de formulario = “POST” acción = “./ test1.cgi”>
<Nombre de entrada = “val1” tipo = “texto” maxlength = 20>
<Nombre de entrada = “val2” tipo = “texto” maxlength = 20>
<Tipo de entrada = “enviar” valor = “Enviar”>
</ html>
El método “POST” de paso de parámetros se elige porque transmite datos al archivo ejecutable a través de la entrada estándar. El método alternativo “GET” usa variables de entorno, que no son accesibles desde Fortran-77 estándar. El texto pasado a test1.cgi está en una cadena decididamente fortán no amistosa como:
& val1 = abcd & val2 = 1234
Esto no es fácil de analizar en fortran ya que las ubicaciones de columna de los valores se desplazarán por la cadena de acuerdo con la longitud de los nombres y valores, pero como usted controla la longitud de los nombres de las variables en la página HTML, puede controlar la columna ubicaciones de los datos en el caso especial de que los contenidos variables sean de longitud fija, que es el caso de las selecciones, casillas de verificación y botones de opción. En esos casos, una lectura simple de formato fijo puede extraer los datos variables. Para mi ejemplo, debe ingresar 4 caracteres en cada cuadro para obtener el resultado correcto, pero no lo propongo como una solución general. Eso se describe más adelante.
Aquí está test1.for, que supone un usuario cooperativo :.
personaje * 19 a
escribir (*, 100)
Formato 100 (‘Tipo de contenido: text / html’ //)
leer un
write (*, *) ‘<html>’
write (*, *) ‘Esto es lo que test1.cgi ve: <br>’
write (*, ‘(a72)’) a
write (*, *) ‘<p>’
write (*, *) ‘Primer cuadro:’, a (6: 9), ‘<br>’
write (*, *) ‘Segunda caja:’, a (16:19), ‘</ html>’
detener
Fin
Necesita ser compilado:
f77 test1.for -o test1.cgi
en test1.cgi (el tipo de archivo .cgi es requerido por Apache) pero no necesita ninguna biblioteca especial: no puede usar escrituras de formato libre para el tipo de contenido porque eso debe comenzar en la columna 1. La barra doble es requerido, de lo contrario solo obtendrá un error del servidor (“Fin de encabezados prematuros” en el registro), como lo hará si no proporciona ningún encabezado. Inconvenientemente, los mensajes de error van a error_log.
Como usamos cuadros de texto en el ejemplo, el programa es bastante especializado. Discutiré un método mejor para pasar las picaduras de longitud variable a continuación. Existe la posibilidad de que el navegador presente los valores en algún otro orden; hay una opción “tabindex” para evitar esto, pero aún no lo he necesitado con versiones recientes de Safari, MSIE y Firefox, los únicos navegadores que he probado.
También debemos permitir que los usuarios carguen un archivo de texto ASCII. Los archivos se pasan como archivos adjuntos MIME a la entrada estándar, pero aún así son bastante simples. Aquí está el html para un ejemplo
<html>
<Form method = “POST” action = “./ test2.cgi” ENCTYPE = “multipart / form-data”>
<input name = “userfile” type = “file” value = “”> <br>
<Tipo de entrada = “enviar” valor = “Enviar”>
</ html>
El navegador suministra el archivo al servidor como un archivo adjunto MIME. Aquí está el código fortran para el ejemplo, copia los encabezados y el archivo de vuelta al navegador para mostrar.:
carácter * 72 a
escribir (*, 100)
Formato 100 (“Tipo de contenido: texto / html” //)
write (*, *) ‘<html>’
hacer 10 i = 1,20
read (*, ‘(a72)’, end = 99) a
write (*, ‘(i2,1x, a72, a4)’) i, a, “<br>”
10 continuar
99 continuar
write (*, *) “</ html>”
detener
Fin
Preparé un archivo de prueba para subirlo que constaba de tres líneas “línea 1”, “línea 2” y “línea 3”. Aquí está el resultado devuelto, según lo preparado por el navegador para el programa CGI:
1 —————————– 6535751115256
2 Content-Disposition: form-data; name = “userfile”; filename = “Nueva Docu de Texto
3 Tipo de contenido: texto / normal
4
5 línea 1
6 línea 2
7 línea 3
8 —————————– 6535751115256–
La primera línea establece la cadena del separador de archivos, luego varias líneas de encabezado describen qué se está transmitiendo, luego una línea en blanco para señalar el final de los encabezados, luego el archivo en sí, y luego el separador de archivos nuevamente (más 2 guiones más). El búfer de entrada de 72 caracteres no fue lo suficientemente largo como para contener la segunda línea de encabezado con el nombre del archivo, por lo que se truncó y se reanudó la lectura después de la nueva línea.
Aquí hay un problema de nusisance que no es obvio al ejecutar el programa de prueba anterior. El navegador envía el archivo con una convención de final de línea crlf o (hex) 0d0a, mientras que nuestro servidor es Unix, que usa un solo carácter (0a). f77 no descarta el 0d al leer, por lo que cada línea terminará con 0d. Leer una línea nula en una variable de caracteres le otorga un derecho 0d lleno de espacios. En la práctica, he encontrado que el fragmento de código:
5 lectura (*, *) a
if (a (1: 1) .ge. ‘!’) goto 5
omitirá las líneas que no estén en blanco porque ASCII bang es más grande que cualquier espacio en blanco y menos que cualquier otro carácter imprimible. Con el f77 estándar no será posible leer archivos binarios, eso no nos molesta en este momento.
He probado esto en nuestros sistemas FreeBSD con MSIE y Firefox, con f77 y g95. Un corresponsal señala que fortran se ahogará cuando se le pida que lea un ítem de formato “a” que se extiende más allá del final de la línea. En lugar de copiar los caracteres disponibles hasta el final de la línea, continúa leyendo en la siguiente línea. Esto haría que el compilador no sea adecuado para este propósito.
Necesitamos leer campos de parámetros de longitud variable. El truco consiste en utilizar el tipo MIME “multipartes / datos de formulario” para separar el texto y los campos numéricos en líneas separadas, y luego utilizar una lectura fortrana de formato libre en las líneas de datos (omitiendo los encabezados). Este tipo de formulario también permite cargar archivos. Un ejemplo:
<html> Complete los espacios en blanco.
<Form method = “POST” action = “./ test2.cgi” ENCTYPE = “multipart / form-data”>
<Nombre de entrada = “val1” tipo = “texto” maxlength = 40>
<Nombre de entrada = “val2” tipo = “texto” maxlength = 40> <br>
<input name = “userfile”
type = “file” value = “”> <br>
<Tipo de entrada = “enviar” valor = “Enviar”>
</ html>
Con este método, cada parámetro se pasa como una parte MIME separada a la entrada estándar, al igual que el archivo para cargar. Aquí está lo que se pasa al fortran (con números de línea antepuestos):
1 ———— 0xKhTmLbOuNdArY
2 Content-Disposition: form-data; name = “val1”
3
4 123.999
5 ———— 0xKhTmLbOuNdArY
6 Content-Disposition: form-data; name = “val2”
7
8 abcd
9 ———— 0xKhTmLbOuNdArY
10 Content-Disposition: form-data; name = “userfile”; filename = “test.txt”
11 Tipo de contenido: texto / llanura
12
13 línea 1
14 línea 2
15 línea 3
dieciséis
17 ———— 0xKhTmLbOuNdArY–
Aquí está la fortaleza para responder a esa página web:
carácter * 72 a
datos x / -9999 ./, nrec / 0 /
escribir (*, 100)
Formato 100 (“Tipo de contenido: texto / html” //)
write (*, *) “<html> Aquí están los valores vistos por fortran: <br>”
5 lecturas (*, ‘(a72)’) a
if (a (1: 1) .gt. ‘!’) goto 5
leer (*, *, err = 6) x
6 lectura (*, *) a
if (a (1: 1) .gt. ‘!’) goto 6
leer (*, ‘(a20)’) a
write (*, *) ‘x =’, x, ‘<br>’
write (*, *) ‘a =’, a, ‘<br>’
write (*, *) ‘Aquí está el archivo con los números de línea agregados: <br>’
7 leído (*, *) a
if (a (1: 1) .gt. ‘!’) goto 7
8 continuar
read (*, ‘(a72)’, end = 99) a
nrec = nrec + 1
if (a (1:10) .ne .’———- ‘) goto 8
write (*, ‘(i4,1x, a72, a4)’) nrec, a, ‘<br>’
99 continuar
write (*, *) ‘</ html>’
detener
Fin
Hasta ahora, todos mis campos han sido numéricos, y la lectura de formato libre f77 considera 0d como un separador válido entre campos numéricos. Las lecturas de caracteres requerirán eliminar el último no en blanco, ya que siempre será 0d.
Russell Hyer ha enviado un ejemplo de lectura de variables del entorno Linux que, sin embargo, requiere una función de sistema “getenv” no estándar (pero común).
He escuchado de Clive Page que en su sistema la página web no se envía al navegador hasta que finaliza el programa Fortran:
He intentado todas esas cosas: cerrar la salida, enjuagarlo, etc. He probado 3 compiladores (g95, fortran y Nag) y todos pueden cerrar la salida estándar hasta donde yo sé. Estoy bastante seguro de que la salida CGI no está completa hasta que el proceso finalice. Por lo tanto, incluso si envía y puede esperar que la página finalice, el usuario ve que el navegador muestra una condición de ocupado, justo hasta que el proceso CGI (y cualquier subproceso) finalmente finalice. Esa puede ser una función de nuestro servidor web (Apache).
Esta no ha sido mi experiencia, y ninguno de nosotros puede entender cuál podría ser la diferencia en los sistemas.
Otro corresponsal informa que su declaración de lectura del compilador de Intel no puede leer la entrada estándar del servidor web de Microsoft. Sin embargo, la función getc funciona para él.
Recientemente he estado trabajando con esto y he encontrado que la línea de tipo de contenido ya no muestra el nombre del campo. No estoy seguro de por qué esto es así. Además, veo que las casillas de verificación no marcadas no aparecen en la entrada estándar, lo que hace que las casillas de verificación no se puedan utilizar. Las radiorreceptoras funcionan.
Una versión en línea de echo.for está disponible en http://www.nber.org/sys-admin/fortran-cgi/echo.cgi (no es un enlace activo) donde puede usarlo para realizar pruebas. Simplemente cambie el href en su página web para que apunte a esa página y nuestro servidor le responderá lo que el navegador le envíe. Algo así como una “fuente de muestra” inversa.
Daniel Feenberg
Oficina Nacional de Investigación Económica
617-588-0343
feenberg isat nber dotte org
Link to original source:http://www.nber.org/sys-admin/fortran-cgi/