martes, 6 de junio de 2017

El Mítico Hombre-Mes (The Mythical Man-Month) capítulo 4 en español

¡Hola! Ya que muchos me han pedido seguir con la traducción del libro The Mythical Man-Month: Essays on Software Engineering, me he dado el tiempo y he avanzado con la traducción del Capítulo 4. Sin más blah-blah, aquí les va.

NOTA: En este capítulo se habla mucho de implementador, considérenlo como el rol de un desarrollador (.Net, Java, Mobile, PHP, etc.) en la actualidad.

The Mythical Man-Month : Essays on Software Engineering.

Capítulo 4: Aristocracia, Democracia y Diseño de Sistemas


Esta gran iglesia es una obra de arte incomparable. No existe confusión ni ambigüedad en los principios que establece.
Es el cenit de un estilo, el trabajo de artistas que entendieron y asimilaron todos los éxitos de sus predecesores, en plena posesión de las técnicas de su tiempo, pero fueron usados sin exhibición indiscreta ni hazañas gratuitas de habilidad.
Jean d'Orbais fue sin duda quien concibió el plan general del edificio, un plan que fue respetado, al menos en sus elementos esenciales, por sus sucesores. Esto es una de las razones de la extrema coherencia y unidad que posee la estructura.

Guía de la Catedral de Reims

Fotografía de Emmanuel Boudot-Lamotte


Integridad Conceptual

La mayoría de las catedrales europeas muestran diferencias en el plan o el estilo arquitectónico si hablamos de piezas construidas en diferentes generaciones por diferentes constructores. Los constructores posteriores fueron tentados a "mejorar" los diseños de los primeros, para reflejar tanto los cambios en la moda como las diferencias en su gusto individual. Así, la pacífica arquitectura normanda contradice al estilo gótico, y el resultado proclama tanto la soberbia de los constructores como la gloria de Dios.

Frente a éstos, la unidad arquitectónica de Reims se encuentra en el glorioso contraste. La alegría que despierta al espectador proviene tanto de la integridad del diseño como de cualquier otra excelencia en particular. Como dice la guía, esta integridad se logró con la abnegación de ocho generaciones de constructores, cada uno de los cuales sacrificó algunas de sus ideas para que el conjunto pudiera tener un único diseño. El resultado proclama no sólo la gloria de Dios, sino también SU poder para salvar a los hombres orgullosos.

Ahora si hablamos de los sistemas de programación, a pesar de que no han tardado siglos en construirse, reflejan una desunión conceptual mucho peor que la de las catedrales. Por lo general, esto no surge de una sucesión en serie de diseñadores maestros con "diferente mano", sino de la separación del diseño con las muchas tareas hechas por muchos hombres diferentes.
Afirmaré que la integridad conceptual es la consideración más importante en el diseño de sistemas. Es mejor que un sistema omita ciertas características y mejoras anómalas, con tal que refleje un conjunto de ideas de diseño, a tener una que contenga muchas ideas buenas pero independientes y no coordinadas.

En este capítulo y en los dos siguientes, examinaremos las consecuencias de este tema en la programación de un diseño de sistema:
  • ¿Cómo se puede lograr la integridad conceptual?
  • ¿No implica esto tener una élite o aristocracia de arquitectos y por otro lado una horda de ejecutores plebeyos cuyos talentos creativos e ideas son suprimidas?
  • ¿Cómo se mantiene a los arquitectos a la deriva en el mar de especificaciones imposibles de implementar o que son muy costosas?
  • ¿Cómo se asegura que cada detalle insignificante de una especificación de arquitectura se comunique al ejecutor, correctamente entendido por este, y que se incorpore con precisión en el producto final?

Lograr la integridad conceptual

El propósito final de un sistema de programación es hacer que una computadora sea fácil de usar (para el punto de vista del usuario). Para ello, proporciona lenguajes y diversos servicios que en realidad son programas invocados y controlados por características del lenguaje.
Pero estos servicios tienen un precio: las descripciones externas de un sistema de programación es de diez a veinte veces mayor que la descripción externa de ese mismo sistema de computación. El usuario encuentra muy fácil especificar alguna nueva función en particular, pero hay mucho más para elegir, y muchas más opciones y formatos que se deben recordar.
La facilidad de uso se mejora sólo si el tiempo ganado en la especificación funcional es mayor al tiempo perdido en el aprendizaje, en el recordar algo y el uso de manuales. Con los sistemas de programación modernos esta ganancia supera el costo de que el usuario aprenda más, pero en los últimos años parece haber disminuido la proporción entre la ganancia y el costo de aprender por parte del usuario (Nota del traductor: esto hay que verlo desde el punto de vista del año en que se publicó el libro, 1975, ahora sabemos que existen las aplicaciones minimalistas como Google, Facebook o Apps Mobile, donde todo es más simple para el usuario) a medida que se agregan funciones cada vez más complejas. Por ejemplo, me asombra la facilidad de uso de la IBM 650, incluso dejando afuera ensamblador u otro software que posea.

Debido a que la facilidad de uso es el propósito, esta relación entre la función y la complejidad conceptual es la última prueba del diseño del sistema. Ni la función o simplicidad por sí solas, definen un buen diseño.
Este punto es ampliamente mal entendido. El SO/360 es aclamado por sus constructores como el mejor jamás construido, porque indiscutiblemente tiene muchas funciones. La función y no la simplicidad, ha sido la unidad de medida por excelencia de sus creadores. Por otro lado, el Sistema de Compartición del Tiempo del PDP-10 es aclamado por sus creadores como el más fino, debido a su simplicidad y la escasez de sus conceptos. Sin embargo, en cualquier caso, su función no está ni siquiera al nivel de la de OS/360. Si hablamos que la facilidad de uso sea el criterio, cada uno de ellos se ve desequilibrado, alcanzando sólo la mitad de la meta real.

Para un nivel dado de función, sin embargo, ese sistema es el mejor en el cual uno puede especificar las cosas con la mayor sencillez y facilidad que se puede. En todo caso, la simplicidad no es suficiente. El lenguaje TRAC de Mooers y Algol 68 alcanza una sencillez dada por conceptos distintos. Sin embargo, no son sencillos de manejar. La expresión de las cosas que uno quiere hacer a menudo requiere combinaciones no evolucionadas e inesperadas de una función base. No basta con aprender los elementos y las reglas de la combinación, uno debe también aprender el uso idiomático, toda una sabiduría de cómo los elementos se combinan en la práctica. La simplicidad y la franqueza proceden de la integridad conceptual. Cada parte debe reflejar las mismas filosofías y el mismo equilibrio de desiderata. Cada parte debe incluso utilizar las mismas técnicas en sintaxis y nociones de la semántica. La facilidad de uso, entonces, dicta una unidad de diseño, dicta la integridad conceptual.

Aristocracia y democracia

La integridad conceptual a su vez dice que el diseño debe proceder de una mente, o de un número muy pequeño de mentes concordantes.
En el mundo de la programación, sin embargo, dice que la construcción del sistema necesita muchas manos. Hay dos técnicas disponibles para resolver este dilema. La primera es una cuidadosa división del trabajo entre arquitectura e implementación. La segunda es la nueva forma de estructurar los equipos de implementación de programación discutidos en el capítulo anterior. La separación entre el esfuerzo arquitectónico y la implementación es una forma muy poderosa de conseguir integridad conceptual en proyectos muy grandes. Yo mismo he visto que se usó con gran éxito en la computadora Stretch de IBM y en la línea de productos de computadoras System/360. Pero la he visto fallar con las aplicaciones del SO/360.

Por la arquitectura de un sistema, me refiero a la especificación completa y detallada de la interfaz de usuario. Para una computadora este es el manual de programación. Para un compilador es el manual del lenguaje. Para un programa de control son los manuales para el idioma o lenguajes usados para invocar sus funciones. Para todo el sistema es la unión de los manuales que el usuario debe consultar para hacer todo su trabajo. El arquitecto de un sistema, como el arquitecto de un edificio, es el agente del usuario. Su trabajo consiste en llevar el conocimiento profesional y técnico al más puro interés del usuario, en contraposición a los intereses del vendedor, del fabricante, etc. La arquitectura debe ser cuidadosamente diferenciada de la implementación.

Como Gerrit Blaauw dijo: "la arquitectura dice lo que sucede, la implementación dice cómo se hace que suceda". Él da como ejemplo simple un reloj, cuya arquitectura consiste en la cara, la correa y la perilla. Cuando un niño ha aprendido esta arquitectura, puede decir el tiempo tan fácilmente de un reloj de pulsera como de una torre de iglesia. La implementación, sin embargo y su realización, describen lo que sucede en el interior de los muchos mecanismos y controles que el reloj tiene.

En un computador System/360, por ejemplo, una arquitectura de computadora única se implementa de manera muy diferente en cada uno de los nueve modelos. Por el contrario, una única implementación, el flujo de datos del Modelo 30, la memoria y el microcódigo, sirve en diferentes momentos para cuatro arquitecturas diferentes: un System/360, un canal multiplex con hasta 224 subcanales lógicamente independientes, un canal selector y un ordenador 1401.
La misma distinción es igualmente aplicable a los sistemas de programación. Existió un estándar estadounidense para el Fortran IV. Era una arquitectura para muchos compiladores. Dentro de esta arquitectura era posibles muchas implementaciones como text-in-core o compiler-in-core, fast-compile, compilación rápida u optimización, sintaxis directa o ad-hoc. Del mismo modo cualquier lenguaje ensamblador o lenguaje de control admitía muchas implementaciones del ensamblador o scheduler.

Ahora podemos hablar de la cuestión profundamente emocional que es la aristocracia versus la democracia. ¿No son los arquitectos una nueva aristocracia, una élite intelectual, preparada para decir a los pobres ejecutores mudos qué deben hacer?, ¿no ha sido todo el trabajo creativo secuestrado para esta élite, dejando a los implementadores sólo como engranajes en la maquinaria?, ¿no se conseguirá un mejor producto obteniendo las buenas ideas de todo el equipo, siguiendo una filosofía democrática, en lugar de restringir el desarrollo de especificaciones a unos pocos?
En cuanto a la última pregunta, que es la más fácil. Ciertamente no afirmaré que sólo los arquitectos tendrán buenas ideas arquitectónicas. A menudo una idea fresca proviene de un implementador o de un usuario. Sin embargo, estoy convencido según mi experiencia y también lo he intentado demostrar, que la integridad conceptual de un sistema determina su facilidad de uso.

Las características o ideas que no se integren con los conceptos básicos de un sistema es mejor dejarlas de lado. Si aparecen varias ideas importantes pero incompatibles, se desecha todo el sistema y se empieza de nuevo en un sistema integrado, pero con diferentes conceptos básicos.

En cuanto a la carga aristocrática, la respuesta debe ser sí y no.

Sí, en el sentido de que debe haber pocos arquitectos, su producto debe durar más tiempo que el de un ejecutor, y el arquitecto se encuentra en el centro de las fuerzas que debe resolver en última instancia en interés del usuario. Si un sistema debe tener integridad conceptual, alguien debe controlar los conceptos. Es una aristocracia que no necesita disculpas.
No, porque la creación de especificaciones externas no es un trabajo más creativo que el diseñar las implementaciones. Es sólo un trabajo creativo diferente. El diseño de una implementación, dada una arquitectura, requiere y permite tanto la creatividad de diseño, como de ideas nuevas y de brillantez técnica, tanto como el diseño de las especificaciones externas. De hecho, la relación costo-rendimiento del producto dependerá en gran medida del implementador, así como la facilidad de uso depende en gran medida del arquitecto.

Hay muchos ejemplos en otras artes y oficios que indican que la disciplina es buena para el arte. De hecho, el aforismo de un artista afirma: "la forma es liberadora". Los edificios peores son aquellos cuyo presupuesto era demasiado grande para los propósitos que se usarán.
La producción creativa de Bach apenas parece haber sido sofocada por la necesidad de producir una cantata de forma limitada cada semana. Estoy seguro de que la computadora Stretch habría tenido una mejor arquitectura si hubiera sido más restringida; las restricciones impuestas por el presupuesto del System/360 Modelo 30 eran en mi opinión totalmente beneficiosas para la arquitectura del Modelo 75.
Del mismo modo, observo que si la arquitectura la entrega un proveedor externo, esta mejora sin obstáculos el estilo creativo del grupo de implementación. Se centran de inmediato en la parte del problema que nadie ha tratado y las invenciones comienzan a fluir. En un grupo de implementación sin restricciones, la mayor parte del pensamiento y el debate van hacia las decisiones arquitectónicas y la implementación correcta se hace corta.
Este efecto, que he visto muchas veces, es confirmado por R. W. Conway, cuyo grupo en Cornell construyó el compilador PL/C para el lenguaje PL/I. Él dijo: "finalmente decidimos implementar el lenguaje sin cambios y sin mejoras, porque los debates sobre el lenguaje habrían tomado todo nuestro esfuerzo".

¿Qué hace el Implementador mientras espera?

Es una experiencia muy humillante el cometer un error multimillonario, pero a la vez es memorable. Recuerdo claro la noche que decidimos cómo organizar la escritura real de especificaciones externas para el OS/360. El gerente de arquitectura, el gerente de implementación y yo estábamos debatiendo el plan, el cronograma y la división de responsabilidades. El director de arquitectura tenía 10 hombres buenos. Afirmó que podrían escribir las especificaciones y hacerlo bien. Tomaría diez meses, tres más que el tiempo comprometido. El gerente de implementación tenía 150 hombres. Afirmó que podría preparar las especificaciones, con la coordinación del equipo de arquitectura; sería bien hecho y de forma práctica, y él podría hacerlo en el los tiempos establecidos. Ahora, si el equipo de arquitectura lo hiciera como dijimos, sus 150 hombres estarían girando en sus asientos durante diez meses.

A esto el director de arquitectura dijo que si yo le daba toda la responsabilidad al equipo de implementación, el resultado no sería de hecho a tiempo, sino que también estaría tres meses atrasado y de calidad mucho menor. Lo hice, y así fue. Tenía razón en ambos aspectos.
Además, la falta de integridad conceptual hizo que el sistema fuera mucho más costoso de construir y cambiar, y yo estimaría un año más al tiempo de depuración.
Muchos factores, por supuesto, entraron en esa decisión equivocada, pero era abrumador el tiempo de no hacer nada con los 150 hombres.
Cuando se propone que un pequeño equipo de arquitectura escriba todas las especificaciones externas para una computadora o un sistema de programación, los implementadores plantean tres objeciones:
  • Las especificaciones serán demasiado ricas en función y no reflejarán consideraciones prácticas de costo.
  • Los arquitectos tendrán toda la diversión creativa y excluirán la ideas de los ejecutores.
  • Los implementadores tendrán que sentarse ociosamente a esperar que las especificaciones vengan desde un embudo estrecho que es el equipo de arquitectura.
El primero de los puntos anteriores es un peligro real y será tratado en el próximo capítulo. Las otras dos son ilusiones, así de simple. Como hemos visto anteriormente, la implementación es también una actividad creativa de primer orden. La oportunidad de ser creativo en la implementación no disminuye significativamente al trabajar cuando se entrega una especificación externa y la creatividad puede incluso ser mejorada por esa disciplina y el producto total seguramente será mejor. La última objeción es una que tiene que ver con tiempos y ajuste de fase. Una respuesta rápida es abstenerse de contratar implementadores hasta que las especificaciones estén completas. Esto es lo que se hace cuando se construye un edificio. En el negocio de sistemas informáticos, sin embargo, el ritmo es más rápido y uno quiere comprimir el calendario tanto como sea posible. ¿Cuánto puede superponerse la especificación y la construcción?

Como señala Blaauw, el esfuerzo creativo total implica tres fases distintas: arquitectura, implementación y realización. Resulta que estos pueden de hecho ser comenzados en paralelo y proceder simultáneamente.

En el diseño de computadoras, por ejemplo, el implementador puede comenzar tan pronto como tenga suposiciones relativamente vagas acerca del manual, ideas algo claras sobre la tecnología y objetivos bien definidos de costo y desempeño. Puede comenzar a diseñar flujos de datos, secuencias de control, conceptos de deploy, etc. El implementador diseña o adapta las herramientas que necesitará, especialmente el sistema de mantenimiento de registros o sistema de automatización.
Mientras tanto, en el nivel de realización (N. del T: en el caso de un nuevo sistema IBM): los circuitos, tarjetas, cables, marcos, fuentes de alimentación y memorias deben ser diseñadas, refinadas y documentadas. Este trabajo se desarrolla en paralelo con la arquitectura y la implementación.

Lo mismo ocurre en la programación del sistema. Mucho antes de que las especificaciones externas estén completas, el implementador tiene mucho que hacer. Con algunas aproximaciones en cuanto a la función del sistema que se incorporará finalmente en las especificaciones, él puede proceder. Debe tener objetivos bien definidos de espacio y tiempo. Debe conocer la configuración del sistema en la que debe funcionar su producto. Luego puede comenzar a diseñar límites de módulos, estructuras de tablas, desgloses de paso o fase, algoritmos y todo tipo de herramientas. Igualmente, a veces debe comunicarse con el arquitecto.

Mientras tanto, a nivel de realización hay mucho que hacer también. La programación también tiene una tecnología. Si la máquina es nueva, se debe hacer mucho trabajo en convenciones de subrutinas, técnicas de supervisión, algoritmos de búsqueda y clasificación.

La integridad conceptual requiere que un sistema refleje una sola filosofía y que la especificación vista por el usuario fluya de unas pocas mentes. Sin embargo, debido a la división real del trabajo en arquitectura, implementación y realización, esto no implica que un sistema lleve más tiempo construir. La experiencia demuestra lo contrario, que el sistema integral va más rápido y toma menos tiempo para probar. En efecto, una amplia división horizontal del trabajo se ha reducido drásticamente al usar una división vertical del trabajo y el resultado es una comunicación radicalmente simplificada y una mejor integridad conceptual.

miércoles, 5 de abril de 2017

Diccionario Chileno WPA/WPA2 con más de 500 millones de combinaciones de palabras

Hola a todos, hoy les traigo algo distinto. Algo que no encontré en la WEB, así que lo creé yo mismo: un Diccionario WPA y WPA2 chileno, actualizado al 11/04/2017 con más de 540 millones de combinaciones (exactamente 543.056.781) de palabras con números y símbolos básicos. Descomprimido pesa más de 8 GB. Bajar aquí (aprox. 300 MB).
En mi equipo el programa estima que demorará 20 hrs en probar todo el diccionario. Esto depende de su CPU, RAM y calidad de su Tarjeta de Video.

Generador de diccionario (Binario)

DicGenerator.exe: bajar aquí.

Diccionario base "MiDic.dic" para usar con el programa DicGenerator.exe

El diccionario base en primera instancia lo encontré en este sitio y pesa apenas 4 MB. Lo mejoré, le puse números y otras combinaciones.
Bajar desde aquí nuevo diccionario mejorado, con muchas más palabras y que puedes ampliar si quieres para usar con el programa. Modo de uso: Lo descomprimes y dejas MiDic.dic en la misma carpeta que DicGenerator.exe, luego ejecutas el programa.

Código fuente del programa para generarlo o ampliarlo

Usar Visual Studio 2013 o superior. Está escrito en C#. Bajar desde aquí código fuente por si quieren agregarle más palabras, letras, símbolos o lógica (ojo no es una maravilla de código, lo hice en 3 hrs).

miércoles, 8 de marzo de 2017

HTTP versus HTTPS versus HTTP/2

Hola gente informática, llevo mucho tiempo sin postear algo. Este es la traducción del excelente post original y comentado en algunos puntos por mi: https://www.tunetheweb.com/blog/http-versus-https-versus-http2, espero les guste.

Introducción

Todos sabemos que rendimiento de HTTPS ya no es una barrera para su implementación en los sitios web. Incluso hay sitios como https://www.httpvshttps.com que muestran que HTTPS es mucho más rápido que HTTP.

Esto es contra intuitivo ya que sin duda hay cargas extras sobre HTTPS que normalmente se aplican encima de la capa HTTP. Así que cada vez que alguien pasa por este sitio, se pregunta cómo puede ser. Bueno, la razón no es debido al mismo HTTPS, sino que ese HTTPS usa HTTP/2.

De hecho, en el sitio, se menciona en la parte inferior, "el texto en HTTP/1.1 se compara con HTTPS HTTP/2 encriptado", pero no es tan obvio. El objetivo de la página (supongo) es mostrar las mejores condiciones de HTTP en comparación con las mejores condiciones para HTTPS y como HTTP/2 es sólo compatible con los navegadores que usan HTTPS, ahí tienen el argumento de la comparación.

Ahora estoy seguro que esto es falso por varias razones:
  • No está claro que sean pruebas similares ya que la única diferencia es que una sección solo son HTTPS. Se muestra que el hecho implícito de ser HTTPS es la razón por la que es más rápido cuando no lo es.
  • Es un ejemplo extremo que un sitio web HTTP/2 sea muy bueno cargando 360 imágenes casi idénticas. Cuando los sitios web siempre van creciendo en cantidad de imágenes y ninguno carga 360 imágenes casi idénticas desde mismo dominio. De modo que el único problema serían las latencias en el cual HTTP/2 tiene mejoras sustanciales. La mayoría de los sitios web cargan una cantidad de recursos de varios dominios y algunos de esos recursos (especialmente CSS y Javascript) toman tiempo en procesarse, mientras que las imágenes pequeñas tienen un tiempo de procesamiento insignificante.
  • HTTP/2 incluye compresión del header así los request se ven más pequeños en HTTP/2. De nuevo, la mejora aquí se ve ya que carga un montón de pequeños recursos todos casi iguales.
  • HTTPS no significa de forma automática HTTP/2 incluso lo contrario es así. De hecho, hace poco se retrocedió un paso en la disponibilidad de HTTP/2. Tomará un tiempo hasta que HTTP/2 esté disponible en todos los SO clásicos y servidores web comunes, por lo tanto decir que HTTPS es lo mismo que HTTP/2 no me calza mucho. Decir que CDN como CloudFlare ofrece su servicio con HTTP/2 es cierto pero no quiere decir que le sirva todo el mundo.
  • Esta ignora el pequeño impacto en el rendimiento en la conexión inicial de un sitio con HTTPS como si fuera el mismo rendimiento cuando se carga un HTML. Ahora bien, esto es difícil de medir con precisión, sobre todo porque sólo se puede medir una vez por sesión, y es pequeño (unos pocos cientos de milisegundos), pero es algo que la gente nota al pasar de HTTP a HTTPS.
  • ¡No hay razones para hacer trucos como estos! HTTPS y HTTP/2 son grandes tecnologías que tienen muy buenos beneficios, lo que nos invita a utilizarse en todo lo posible. Meter trucos falsos como estos, sólo nubla la visión y te pone en duda sus ventajas.
Ahora, no piensen que es un ataque personal a dicho sitio web ya que es un ejemplo inteligente y bien ejecutado de cómo HTTPS puede ser más rápido que HTTP, pero sólo quiero un poco más de transparencia y me gustaría saber el verdadero impacto de HTTPS con y sin HTTP/2 (el que creo debería ser un poquito más lento, casi imperceptible).

Así que en un intento de hacer un test real, he hecho una prueba similar para comparar HTTPv1.1 con HTTPS (sobre HTTPv1.1) y luego con HTTP/2 (que utiliza HTTPS). Puedes ejecutar esta versión de esta prueba con 36 imágenes más reales. También he creado una versión con 360 imágenes aquí. Le sugiero es que repitas las pruebas varias veces para tener una idea de cuánto tiempo se tarda, y probablemente verás algo como esto para la prueba de 36 imágenes:
Y similarmente sucede con el test de 360 imágenes:
Nota del traductor, agregué abajo la imagen de HTTP VS HTTPS y vs HTTP2:

Lo que inmediatamente se ve es que HTTP es bastante similar a HTTPS. Ocasionalmente es más rápido y ocasionalmente es más lento. Extrañamente se ve más a menudo que HTTPS es ligeramente más rápido que HTTP. No estoy seguro si esto es sólo suerte o algún efecto de almacenamiento en caché. Tal vez mi navegador web, red o servidor web maneja mejor el HTTPS, o tal vez es sólo una coincidencia. De cualquier manera, los números están separados sólo unos pocos puntos porcentuales. O tal vez HTTPS es realmente es más rápido que HTTP :-)

Lo que podemos ver es que HTTPS no causa ningún impacto al rendimiento en sitios web pequeños, como ha sido declarado por la mayoría de los expertos desde hace algún tiempo. Esto podría variar, por supuesto, si usted está ejecutando el sitio en un hardware realmente viejo (me refiero en el cliente o en el lado del servidor) o tiene un sitio web que usa mucho tráfico (por ejemplo, streaming de vídeo), pero para la mayoría de nosotros sería difícil notar el impacto de rendimiento con HTTPS. Hay un pequeño impacto al momento de redirigir a HTTPS (que se puede remediar con HSTS), y otro pequeño impacto al tratar con la sesión HTTPS (que se puede corregir con una buena configuración de HTTPS y podría incluso mejor cuando TLSv1.3 sea más popular). Estos factores son medibles si se utilizan herramientas como http://www.webpagetest.org, pero a la mayoría de los usuarios no le importa medir esta latencia inicial ya que luego no se ven retrasos. Si hay malas conexiones de red (por ejemplo, una mala señal móvil) estos viajes de ida y vuelta causarán más problemas, pero cuando pase eso, tendrás un desempeño malo a nivel general de todos modos.

El otro punto obvio es que HTTP/2 es mucho más rápido que HTTP o HTTPS, aunque sólo está disponible usando HTTPS. Este fue el punto engañoso que sentí de https://www.httpvshttps.com, ya que no fue HTTPS el que causó el buen desempeño, sino que fue HTTP/2, incluso en un sitio más pequeño de 36 imágenes. Por supuesto, el sitio de 360 imágenes sigue siendo un ejemplo extremo y no vas a ver un 91% de mejora simplemente encendiendo HTTPS, incluso usando HTTP/2 para la mayoría de los sitios. Sin embargo incluso el sitio más pequeño de la imagen 36 ve una mejora enorme del 70% en HTTP/2, mucho más de lo que habría esperado.

También es impresionante ver las mejoras de descarga de HTTP/2 debido a la compresión del header. En la página de 360 imágenes el tamaño total de la página es 382kb, es idéntico en HTTP y HTTPS, pero cae a un impresionante 265kb en HTTP/2 ¡una mejora del 30%!:
Ahora, estas imágenes son pequeñas y la mayoría de los recursos que carga un sitio web probablemente son mayores, por lo que la mejora de la compresión de header puede ser menor al 30%, pero sigue siendo buena.

Conclusión

HTTPS y HTTP/2 son dos grandes tecnologías y todos los sitios web corrientes deberían ser conscientes de ellos y buscar implementarlos si no se utilizan todavía. Mi intención de este artículo no fue para probar que HTTPS todavía tiene problemas de rendimiento, ni para soplar sitios web de otros, nada más fue para obtener algunos números tras pruebas de rendimiento que no se explican allí.

HTTPS en particular es una tecnología bien establecida ahora y con iniciativas como Let's Encrypt nunca ha sido más fácil ni más barato obtener un certificado HTTPS para su sitio web. Hay muchas razones para usar HTTPS y se va a hacer cada vez más difícil mantener un sitio HTTP con navegadores web que están apuntando sus características para sitios que usan HTTPS. Si no estás usando HTTPS, entonces debes mirar de qué se trata ahora ahora. Estas pruebas demuestran que el impacto en el rendimiento no es ni siquiera algo notable en la mayoría de los sitios. El movimiento puede ser tedioso, especialmente para los sitios más grandes con un montón de código y páginas legadas, pero esto se hace una sola vez y cuanto antes se inicia mejor será.

HTTP/2 no está listo al 100% los SO y servidores web, pero en poco tiempo lo estará. La especificación HTTP/2 sólo se publicó oficialmente en mayo de 2015, y ya pasado un año casi todos los navegadores web soportan HTTP/2 y muchos servidores web también lo soportan. HTTP/2 será el futuro de la web y si usted tiene la oportunidad de usarlo, entonces juegue, estas pruebas demuestran lo mucho más rápido que puede ser, sin ningún cambio en el propio sitio web. Puedes consultar el post sobre cómo configurar HTTP/2 para Apache si quieres más información sobre eso.

¿Estás de acuerdo? ¿No mucho? Escribe abajo tus comentarios.

jueves, 25 de agosto de 2016

Battlevoid: Harbinger - Tips para completar el juego

Objetivos

Hola amigos, en esta ocasión les daré algunos tips para pasar el juego Battlevoid: Harbinger (antes llamado Battlestation: Harbinger pero como dice en su cuenta de Twitter @BattlestationPC, por problemas legales se le debió cambiar el nombre). Lo compré para Android cuesta $2.900 (pesos Chilenos), unos 4.5 USD. Para PC lo encuentras en Steam a 9,99 €, unos 11 USD. Este juego es un Roguelike espacial con elementos de batalla y estrategia, muy adictivo y entretenido. Me ha tenido una y otra vea intentado pasarlo, aún no puedo pero estoy a punto. Al ser roguelike dejo en claro que es que si mueres, comienzas todo de nuevo, pero de igual forma ganas experiencia para desbloquear otras naves. Son mapas random, por lo que una partida nunca es igual a otra. Permite jugarlo offline.
Tiene una comunidad (en inglés) activa: http://bugbyte.fi/forums/forumdisplay.php?fid=10, así que les animo a que lo jueguen.

Parte con algo fácil

  • Empieza en fácil, con un mapa autogenerado pero limitado (presionando el dado de abajo a la izquierda), y no infinito.
  • Parte con una nave potente de las pocas que hay al comienzo. Ve las características de cada una (presionando en el triangulo de arriba a la derecha) y quédate con la mejor.

Dinero

  • Chatarra espacial o tuercas: reúne esa chatarra que parecen tuercas (o engranajes) para comprar módulos de naves o naves amigas, las tuercas son tu dinero. La obtienes al ganar batallas o completar misiones. Al eliminar una nave grande obtienes más que un pequeña, pero al completar una misión ganas mucho más.
  • Cubos: a veces recogerás cubos grises que son parte de alguna misión, no debes venderlos, sino llevarlos alguna estación que lo necesite, según los objetivos de dicha misión.
  • Materiales verdes: reúne estos ítems para hacerle upgrade a tus armas, drones o naves ayudantes.
  • Vende lo que no necesites: pero ojo que si lo vendes, obtienes una parte muy pequeña de lo que lo compras, así que úsalo como último recurso.
  • Vende equipo alien pero sólo si encuentras uno mejor: equipo alien se vende bien, pero primero úsalo ya que en general tiene mejoras. Véndelo sólo si encuentras uno mejor.
  • Vende tus armas sólo en caso muy necesario: por ejemplo quieres un cañón de largo alcance, y te faltan 150 tuercas, vende una de tus armas chicas ya que vale la pena, lo mismo para comprar un cañón nuclear.

Equipo

  • Al comienzo tienes 3 naves para seleccionar y cada uno con slots diferentes. Hay 3 tipos de slots:
    • Slot rojos: permite incorporar artillería de ataque como un cañón láser o cañón nuclear. Son los más útiles.
    • Slot azules (o calipso): armas de defensa, que son de menor calibre y rango como el bolter, que es el más barato.
    • Slot verdes: el hangar, donde puedes construir bolters, láser, reparar, naves no tripuladas o drones. Los bolters son los más baratos y más efectivos por el precio, o los drones son la mejor opción.
    • Naves extras: Existe una variedad con diferentes precios. Ve bien tu estrategia para decidirte por una nave cargador (carrie) o una de asalto ya que podrás actualizar estas naves luego. Puedes comprar hasta dos naves ayudantes, si te alcanzan las tuercas claro.
  • Las naves que compres vienen vacías: Si tienes suficientes tuercas y compras una nave, esta viene sin armas, así que no compres a menos que tengas unas 300 tuercas extras para comprar la nave más un arma básica.
  • Mejora tu equipo: cada equipo que compres tiene características para ser mejorado. Una buena idea es mejorar la característica de número de naves para el equipo Drones para poder sacar más drones y de forma rápida.
  • Bolter drones, baratos y eficientes: son la mejor opción para ahorrar, hasta que te alcance para un cañón de asalto. Con 3 bolter drones y un bolter de defensa puedes eliminar una nave grande, lo que te dará buen dinero. Si eres bueno, en poco tiempo puedes eliminar varias naves grandes y te alcanza para el cañón nuclear que es una de las mejores armas del juego.

Estación

  • Reparar es gratis: si estás en la misma pantalla de una Estación, basta tocar tu nave cuando esta dañada para que aparezca el ícono de reparar, si aceptas reparará gratis tu nave. En cambio, si estás en una pantalla donde no está la estación y no quieres volver a la zona de la Estación, te sale dinero reparar. Vuelve a la estación cada vez que puedas, dando saltos espaciales (si estás muy lejos de una, mira primero en el mapa que no hayan enemigos en el camino. Mira las flechas rojas como se mueven, indican la dirección donde se moverán de las naves enemigas)
  • La estación te defiende: una gran ventaja es que si naves enemigas te siguen acá, la estación tiene una muy buena defensa que te ayudará a defenderte. Un truco es atraer las naves enemigas a la Estación con el radar SOS que dejan los enemigos a veces, así las destruyes más rápido.
  • La estación vende buen equipo: la estación tiene un muy buen equipo para vender en general, sobretodo armas aliens poderosas. Con solo tocar la Estación sale el ícono de comprar (un ícono parecido a un carro de compra).

Mapa

  • Los símbolos azules son aliados: Las tuercas azules son Estaciones, las flechas azules naves o drones aliados.
  • Cuando saltes, escoge bien el cuadrante donde caerás: Al moverte a una nueva ubicación, puedes seleccionar en los 9 cuadros donde caerás, si arriba, al centro, abajo-derecha, etc. Ve bien ya que si hay muchos enemigos y no tienes poder de ataque, mejor ataca de lejos y eliges una posición lejana a ellos.
  • Los símbolos rojos son enemigos: algunos tienen forma de flecha, donde apunta la flecha es donde se están moviendo o donde se moverán, por lo que puedes ver por ejemplo si uno se te acercará en el siguiente turno.
  • Salta un turno a veces: en el mapa verás un ícono de un reloj de arena verde, si lo presionas pasará un turno. Es útil para cuando veas que algunas naves enemigas se mueven a lo lejos y quieres pasar por un área donde justo ellas acaban de dejar.
  • Usa la antena SOS: ese icono como radar que se ve en el mapa, a la izquierda del reloj, te la entregan los enemigos, y sirve para llamar la atención de los mismos (como que tu eres un enemigo y estás pidiendo apoyo) y si están a un turno de ti, lo más seguro vendrán a ayudar, y ahí es cuando es bueno para tenderles una emboscada. Sólo úsala cuando estés en una pantalla junto a la Estación, así llamas la atención de los enemigos, se acercarán y la Estación te dará un buen apoyo para destruirlas. Esta antena, solo atrae a cierto tipo de razas, no todas. En inglés a este ícono le llaman Distress Beacons.
  • Recoge tecnología alien verde: luego de terminar una batalla, aparecerá a veces un ícono de exclamación abajo, si lo tocas saldrá la tecnología alien que dejó alguna nave, esta la puedes equipar en tus slot azules o rojos. Muchas veces es la misma que tu ya tienes equipada, pero con mejores upgrades.

Naves

Las Naves jugables, son de dos tipos: Fighters (ataque) o Carriers (cargadores) y estas a la vez, son de dos tipos, cargadores livianos o de asalto:
  • Nightingale: nave tipo cargador y de asalto liviano, es la primera del juego que puedes usar.
  • Raven: nave de asalto, tiene un casco más duro.
  • Guardian: nave cargadora y de asalto liviano, es un poco mejor que Nightingale, pero más lenta, se desbloquea al nivel 4.
  • Zephyr: destructor, se desbloquea al nivel 4.
  • Hurricane – nave de asalto, se desbloquea al nivel 5.
  • Resolution – nave cargadora y de asalto grande, la nave más cara, se desbloquea al nivel 6.
  • Memphis – destructor, se desbloquea al nivel 7.
  • Avalon – nave cargadora y destructor liviano, se desbloquea al nivel 8.
  • Valhalla – nave cargador y destructora grande, se desbloquea al nivel 9.
  • Achilles – nave crucero, se desbloquea al nivel 10.
  • Liberator – nave cargador y crucero liviano, la nave con mejor escudo, se desbloquea al nivel 11.
  • Armada: la mejor, se desbloquea en el nivel 12.
Naves extras que te pueden ayudar:
  • Chimera – nave cargadora chica, una de las más rápidas, con un nivel de 24 de velocidad.
  • Genesis – nave exploradora y cargadora chica.
  • Viper – nave exploradora, la más rápida con los mejores propulsores.
  • Falcon – nave de asalto, tiene uno de los mejores cascos y velocidad.
  • Ravager – nave de asalto.
Define tu estrategia con las naves
  • Naves de asalto no tienen slot verdes: esto afecta a que por ejemplo el destructor Zephyr no podría llevar drones. Tiene varias ranuras para armas, y tres rojas para cañones de grueso calibre.
  • Usa dos light carrier (cargador liviano) con drones: una alternativa es tener una nave de asalto y a la vez naves extras cargadoras ya que es una forma económica de tener una pequeña escuadra, ya que los Drones Luchadores parten de las 250 tuercas, luego puedes mejorar y comprar Drones Bolter por 600 tuercas.
  • Usa una nave principal carrier con drones: otra alternativa es tener un cargador que tienen menos slots de armas pero tienen slot para drones.
  • Las naves ayudantes tienen espacio para ítems: si tienes items que no quieres vender, puedes dejarla en la sección azul de items de las naves ayudantes, así vez si te sirven en un futuro.
  • Mi escuadra favorita: Una BSE Zephyr que tiene tres slot rojos, lo equipo con dos Torrente de Partículas (4600 tuercas) y un Cañón Nuclear (2500 tuercas) y dos naves Nightingale con un dron de misiles, un Torrent de Partículas y un Cañón Nuclear.

Armas

  • Armas Celestial o armas aliens: ve bien los estatus de cada arma si tienes que decidir entre una y otra
  • Las Estaciones venden muy buenas armas: no olvidar que las armas de las estaciones están mejoradas.
  • Los bolter son los más baratos y efectivos.
  • Teleport es para cobardes: si estás a punto de morir y quieres huir, cómpralo, pero personalmente si muero, muero con mi nave y no como un cobarde jaj, además si mueres ganas experiencia para desbloquear mejores naves :P

Nunca te distraigas, y arranca a veces

  • Nunca, pero nunca te distraigas: Me pasó más de una vez, que por estar mirando la barra de salud de una de mis naves amigas, me atacaron la nave principal y morí. Esto luego de horas de juego :(
  • Si tu energía está al 25%, ¡corre!: No te las des de confiado, si ves el marco rojo de la pantalla, es que debes arrancar a un sitio seguro, ojalá a una Estación.

Anexo a los tips: Libro de ilustraciones

Fuera de los tips y estrategias, quería comentarles que me gustó mucho que el juego tiene una historia de fondo, de razas y conquistas. En el foro se puede leer de ella: http://bugbyte.fi/forums/forumdisplay.php?fid=7
También los fans hacen ilustraciones del universo del juego. Entre las más interesantes son las de las razas, colocaré aquí algunas traducciones:

Los Wanderers
Hemos viajado a través de las galaxias durante mucho tiempo. Nuestro planeta nos fue arrebatado por lo que hemos estado obligados a vivir en nuestras naves. Todos nos llaman Los Wanderers, nosotros nos hacemos llamar sobrevivientes. El tiempo nos ha dado fama de despiadados, y ya no vamos a esperar a ser atacados, sino que vamos a atacar primero. Una sombra infinita y eternamente creciente ha surgido en la vida, sin embargo, no vamos a ser los que se detienen a orar. Estamos aquí, queremos tus naves.

Los Trolgars
La historia trata de la esclavitud que ha pasado de generación en generación en este pueblo en el pasado. Los Trolgars quieren defender su planeta con más fuerza que nunca lo que les pertenece. Ahora son libres, y ahora también quieren reclamar más espacio para su pueblo. Nunca volverán a dejar que nadie se acerca a sus tesoros. Los Trolgars mezclan y combinan cada pieza de tecnología que encuentran y son buenos carroñeros en esa área. En las ciudades de los Trolgars el pasado está presente sólo en las chimeneas negras que se elevan a los cielos, y las historias que se cuentan sobre Haik-u, el Trolgar cuyos pies fueron atados con grilletes metálicos.

Las Schillae
Alguna vez fue una raza pacífica, pero ahora está en busca de la guerra, y lo cantan. La canción es sobre el amor, la traición y la esperanza, pero en su mayoría, trata de venganza. Estas mujeres, sirenas abominables, han sido traicionadas de una manera horrible. Les han arrebatado su amor y esperanza y las han empujado al infierno. Les quitaron los machos de su propia raza y rezan a los machos de otras razas, especialmente a los machos humanos. Ahora que quieren venganza, necesitan un plan. Ellas necesitan ayuda, y necesitan la tecnología. Por encima de todo, ellas tienen que saber quién les ha hecho esto. Hasta que sepan, ellas dudarán de todos.

Los Celestials
Estos seres de energía una vez que se unificaron en una sola luz madre. Esta luz fue infectada por la oscuridad, y necesitaba una manera de detener la pérdida de color por completo. Los hijos de la luz, unas diminutas esferas radiantes, vagaron por el espacio. Su única esperanza era chocar con algo que podría ayudarles. Cuando descubrieron a los seres humanos, encontraron una respuesta, no fue una cura, sino una manera de sobrevivir.

Los Unknown (Los Desconocidos)
Desde el principio, los Unknown ya vivían. Acababa de empezar una evolución larga y sinuosa, pero desde la primera fracción de segundo se sentían que estaban vivos. Su morada se expandió a la misma velocidad que el universo. Las galaxias se arremolinaron y condensaron, nacieron de las estrellas. En cada estrella, los Unknown estaban viviendo una vida silenciosa y sin pretensiones. Con curiosidad, ellos mantienen un seguimiento de la evolución del universo, pero sin intervenir. Ellos ven todo lo que pasa, y cada estrella o planeta recién nacido, ya les pertenece por herencia.

Link útil

lunes, 30 de mayo de 2016

Tutorial de uso de la librería Winnovative HTML to PDF con C# y MVC

Hola, hace rato que no publicaba nada...Bueno hoy veremos como usar la librería Winnovative HTML to PDF Converter Library usando C# y MVC .Net. El tema nació en que buscamos una forma buena y elegante de imprimir un PDF a partir de un sitio web hecho en MVC .Net, pudiendo personalizar el PDF, tipo de hoja, orientación, que permita imprimir un sitio que haga request Ajax y tenga imágenes.

Personalmente conozco 3 herramientas que permiten generar PDF desde C# y me quedo con Winnovative por lo anterior dicho:


El tutorial fue probado con IE 11, Chrome 50.0.2661.102, FireFox 37.0.1.

Requisitos


  • Tener la librería Winnovative HTML to PDF Converter Library v12.16, descargarla de http://www.winnovative-software.com/download.aspx. En mi caso bajé Winnovative HTML to PDF Converter Library Optimized for 64-bit ya que tanto los PC de los desarrolladores como servidores son de 64 bit.
  • En mi caso usaré una versión comprada HTML to PDF Converter Redistributable License cuyo valor es de 1200 USD ya que permite instalarlo en N Servidores, incluyendo en PC de desarrolladores y en servidores de clientes. No es obligación tener la licencia para el ejemplo, lo que sí, saldrán tus PDF con la frase Winnovative PDF Tools Demo en la parte inferior:
  • Para el ejemplo usaré Visual Studio 2013 con C#, MVC 4 y Framework 4.0
NOTA: la librería no es compatible con el Framework .Net 3.5, si con las versiones 2.0, 4.0 y 4.5.

Paso a paso


Pasos generales

  • Crear un proyecto MVC 4 usando C# con Framework 4.0.
  • Vamos a instalar la librería Winnovative "a la antigua", es decir manualmente, ya que se puede instalar por NuGet. Descomprimir el archivo descargado WnvHtmlToPdf-v12.16-x64.zip, en la raíz del zip estarán estos tres archivos que son compatibles si usas al Framework 4.0: wnvhtmltopdf.dll, wnvinternal.dat y Help.chm.
  • Si usas el Framework 2.0 debes copiar los 3 archivos de la carpeta NET_2.0 (wnvhtmltopdf.dll, wnvhtmltopdf.xml y wnvinternal.dat) al directorio bin de tu proyecto web. El XML contiene sólo la documentación de los fuentes.
  • Si están con Framework 4.0. debes copiarlos a una nueva carpeta LIB. Preocúpate los archivos que no estén chequeados como "solo lectura".
  • El archivo wnvhtmltopdf.dll dentro de LIB debes referenciarlo desde tu proyecto MVC .NET.
  • Agregar en el HomeController el using:
    //HomeController.cs
    using Winnovative;
    
  • Si usas la Key, y la agregas en el código, no se verá el mensaje "Winnovative PDF Tools Demo":
    //HomeController.cs
    htmlToPdfConverter.LicenseKey = "keyComprada";
    

Imprimir a pdf una vista o página externa

  • Crear el vista principal con un botón dentro de un Form que llamará a la impresión, por ejemplo:
    
    @using (Html.BeginForm("ImprimeVistaExterna", "Home", FormMethod.Post))
    {
        
    }
    
  • Creas el Action y la Vista Externa a ser llamada. Esta vista puede tener imágenes, o un llamado Ajax a otra Vista ¡y todo eso se verá impreso!. Esa es la gracia de la librería ya que mucha no hacen eso, esta ejecuta el request con todo lo que conlleva, llamados Ajax, JS, estilos, imágenes y todo el resultado del HTML final, es el que imprime. En mi caso incluso uso la librería Kendo MVC para mostrar un TreView y esta igual se imprime:
    
    @{
        ViewBag.Title = "Impresion ejemplo";
    }
    
    

    Vista demo de impresión

    @(Html.Kendo().TreeView() .Name("LinksTreeView") .Items(items => { items.Add() .Text("Home") .Action("Index", "Home"); items.Add() .Text("About") .Action("About", "Home"); items.Add() .Text("Contact") .Action("Contact", "Home"); }) )
  • Por último creamos la vista externa (la más externa) que es llamada desde al Ajax anterior:
    
    

    Otra Vista externa invocada por ajax

    holaaa

  • Si abrimos la Vista externa en el navegador se verá así:
  • Creas el Action ImprimeVistaExterna dentro del controlador Home:
    //HomeController.cs
            [HttpPost]
            public ActionResult ImprimeVistaExterna()
            {
                // Create a HTML to PDF converter object with default settings
                HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();
    
                // Set HTML Viewer width in pixels which is the equivalent in converter of the browser window width
                htmlToPdfConverter.HtmlViewerWidth = 1024;
                
                htmlToPdfConverter.LicenseKey = "tuKey"; //propiedad opcional
                
                htmlToPdfConverter.HtmlViewerHeight = 768;
    
                // Set PDF page size which can be a predefined size like A4 or a custom size in points 
                // Leave it not set to have a default A4 PDF page
                htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.Letter;
    
                // Set PDF page orientation to Portrait or Landscape
                // Leave it not set to have a default Portrait orientation for PDF page
                htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
    
                // Set the maximum time in seconds to wait for HTML page to be loaded 
                // Leave it not set for a default 60 seconds maximum wait time
                htmlToPdfConverter.NavigationTimeout = 4;
    
                // Set an adddional delay in seconds to wait for JavaScript or AJAX calls after page load completed
                // Set this property to 0 if you don't need to wait for such asynchcronous operations to finish
                htmlToPdfConverter.ConversionDelay = 1;
    
                string url = "http://localhost:50422/Home/VistaExterna";
    
                // Convert the HTML page given by an URL to a PDF document in a memory buffer
                byte[] outPdfBuffer = htmlToPdfConverter.ConvertUrl(url);
    
                // Send the PDF file to browser
                FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
                fileResult.FileDownloadName = "ImpresionVistaExterna.pdf";
    
                return fileResult;
            }
    
  • Notar que en url defines la ruta que se imprimirá. Se le hará un request a dicha ruta. Puede ser cualquier URL, incluso una externa como www.google.com
  • Con htmlToPdfConverter.NavigationTimeout se define el tiempo máximo de espera a dicho request. Yo usaré 4 segundos.
  • Con fileResult.FileDownloadName le defines el nombre del archivo PDF de salida.
  • Con htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.Letter defines el tipo de papel, en este caso tipo Carta.
  • Con htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait defines la orientación del documento.
  • Al hacer clic en "Imprimir página Externa", se bajará el PDF resultante y su lo abres es el mismo contenido HTML que tiene la vista externa:


Imprimir a pdf una sección de la página actual

  • La sección debe ser una Vista Parcial, así que creas la vista Seccion.cshtml:
    
    
    @{
        ViewBag.Title = "Seccion ejemplo";
        var nombre = ViewBag.Nombre;    
    }
    
    
    @using (Html.BeginForm("ImpresionSeccionVistaActual", "Home", FormMethod.Post)) {

    Sección: @nombre


    }
    Este texto está rotado 90 grados
  • El ejemplo contiene un texto rotado en 90 grados que se verá impreso de igual forma, por lo tanto debes agregar en la sección de estilos el siguiente código:
    
    
    
  • Creamos en la vista principal un botón Imprimir que llame al Action que haremos luego. Notar que agregamos dos bloques de texto antes y después para que se vea que solo se imprimirá la vista Seccion.cshtml:
    
    

    Texto anterior

    @{ Html.RenderAction("Seccion", "Home", new { nombre = nombre }); } @using (Html.BeginForm("ImpresionSeccionVistaActual", "Home", FormMethod.Post)) { @Html.Hidden("nombre", (object)nombre) }

    Texto posterior

  • En el HomeController crear el Action ImpresionSeccionVistaActual que procesa la sección:
    //HomeController.cs
            [HttpPost]
            public ActionResult ImpresionSeccionVistaActual(FormCollection collection)
            {
                object model = null;
                ViewDataDictionary viewData = new ViewDataDictionary(model);
    
                // transmit the posted data to view
                viewData.Add("nombre", collection["nombre"]);
    
                // The string writer where to render the HTML code of the view
                StringWriter stringWriter = new StringWriter();
    
                // Render the Index view in a HTML string
                ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, "Seccion", null);
                ViewContext viewContext = new ViewContext(
                        ControllerContext,
                        viewResult.View,
                        viewData,
                        new TempDataDictionary(),
                        stringWriter
                        );
                viewResult.View.Render(viewContext, stringWriter);
    
                // Get the view HTML string
                string htmlToConvert = stringWriter.ToString();
    
                // Get the base URL
                String currentPageUrl = this.ControllerContext.HttpContext.Request.Url.AbsoluteUri;
                String baseUrl = currentPageUrl.Substring(0, currentPageUrl.Length - "Home/Seccion".Length);
    
                // Create a HTML to PDF converter object with default settings
                HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();
    
                // Set license key received after purchase to use the converter in licensed mode
                // Leave it not set to use the converter in demo mode
                htmlToPdfConverter.LicenseKey = key;
    
                // Set an adddional delay in seconds to wait for JavaScript or AJAX calls after page load completed
                // Set this property to 0 if you don't need to wait for such asynchcronous operations to finish
                htmlToPdfConverter.ConversionDelay = 2;
    
                // Convert the HTML string to a PDF document in a memory buffer
                byte[] outPdfBuffer = htmlToPdfConverter.ConvertHtml(htmlToConvert, baseUrl);
    
                // Send the PDF file to browser
                FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
                fileResult.FileDownloadName = "ImpresionSeccionVistaActual.pdf";
    
                return fileResult;
            }
    
  • Si haces clic en "Imprimir solo sección", se verá el PDF:
  • La imagen de la aplicación final ejecutándose en el navegador con dos botones, Imprimir Sección o Imprimir página externa, se ve así:

Mostrar PDF en una nueva pestaña del navegador al hacer clic en imprimir (y no en la barra de descargas)


Cambiar la clase Controller:
//HomeController.cs
// Convert the HTML page given by an URL to a PDF document in a memory buffer
byte[] outPdfBuffer = htmlToPdfConverter.ConvertUrl(url);            

// Send the PDF file to browser
//FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");            
//fileResult.FileDownloadName = "ImpresionVistaExterna.pdf";
//return fileResult;

MemoryStream stream = new MemoryStream(outPdfBuffer);
Response.AppendHeader("content-disposition", "inline; filename=file.pdf");
return new FileStreamResult(stream, "application/pdf");
Cambiar la vista para que abra en una nueva pestaña con target _black:

@using (Html.BeginForm("ImprimeVistaExterna", "Home", FormMethod.Post, new { target= "_blank" }))
{
    
}


Mostrar PDF en una nueva pestaña del navegador al hacer clic en imprimir y se abra automáticamente el cuadro de diálogos de las impresoras


Esto es útil si el usuario quiere hacer la menor cantidad posible de clic para imprimir un documento PDF. Se le debe asignar el key (si tienes) de nuevo al Document. Recordar igual lo del target _blank en la vista que tiene el botón.
//HomeController.cs
            string url = "http://localhost:50422/Home/VistaExterna";

            // Convert the HTML page given by an URL to a PDF document in a memory buffer
            byte[] outPdfBuffer = htmlToPdfConverter.ConvertUrl(url);                       

            //mergeResultPdfDocument.OpenAction.Action = New PdfActionJavaScript("print()")

            // Send the PDF file to browser
            //FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");            
            //fileResult.FileDownloadName = "ImpresionVistaExterna.pdf";
            //return fileResult;

            MemoryStream stream = new MemoryStream(outPdfBuffer);

            Document document = new Document(stream);
            document.LicenseKey = key;
            document.OpenAction.Action = new PdfActionJavaScript("print()");
            byte[] b = document.Save();
            Stream strm = new MemoryStream(b);
           
            Response.AppendHeader("content-disposition", "inline; filename=file.pdf");
            return new FileStreamResult(strm, "application/pdf");


Links útiles

miércoles, 18 de noviembre de 2015

Entender la Compilación Dinámica de ASP.NET

Entendiendo la compilación dinámica de ASP.NET


Cuando se hace un request a un sitio web, ASP.NET primero parsea y luego compila el código de la aplicación Web para convertirlo en uno o más assemblies. Cuando se compila el código, es traducido a una representación que es independiente del lenguaje y del CPU llamada Microsoft Intermediate Language (MSIL). En tiempo de ejecución, MSIL corre en el contexto del .NET Framework, el cual traduce MSIL en instrucciones específicas para ese CPU y para el procesador que corre la aplicación en dicho computador.



Compilación en el primer request


Por defecto, las páginas web de ASP.NET y el código embebido se compilan dinámicamente cuando los usuarios hacen el primer request a un recurso, como una página web ASP.NET (un .aspx). Luego que las páginas y el código embebido se compila por primera vez, se dejan estos recursos en un caché, así los subsecuentes request a esa misma página son extremadamente eficientes.
ASP.NET soporta Compilación dinámica de las páginas ASP.NET (.aspx), ASP.NET Web services (.asmx), ASP.NET HTTP handlers (.ashx) y ASP.NET application files (Global.asax), pero también otros archivos de código fuente como (*.aspx.vb) y clases (*.aspx.cs). Para más información de los tipos de archivo de ASP.NET, ver Web Site File Types. Para más información del proceso de compilación de ASP.NET, ver la sección "Compilation Life Cycle" de ASP.NET Application Life Cycle Overview.

Recompilación cuando hay cambios


Cualquier cambio de un archivo dinámicamente compilado invalida el assembly que está en caché y gatilla una recompilación de todos los recursos afectados. La próxima vez que se haga un request, ASP.NET reconoce que el código cambió y recompila los recursos afectados de la aplicación web. Este sistema permite desarrollar aplicaciones con un mínimo de sobrecarga en el proceso de compilación. (Notar que dependiendo del cambio que hay sobre un recurso, ASP.NET recompilará una sola página o todo el sitio Web.)

Dependencias de la compilación


Cuando se hace el primer request a la aplicación, ASP.NET compila los archivos en un orden específico. Los primero ítems en ser compilados son los llamados ítems de primer nivel.
Luego del primer request, los ítems de primero nivel se recompilan sólo si cambian las dependencias.
Los ítems de primer nivel incluyen las carpetas App_GlobalResources, App_WebResources, propiedades del perfil, carpeta App_Code y archivo Global.asax. Luego que los ítems de primer nivel se compilan, ASP.NET compila los ítems adicionales. Estos ítems incluyen la carpeta App_LocalResources, páginas ASP.NET (.aspx files), ASP.NET user controls (.ascx), ASP.NET HTTP Handlers (.ashx) y módulos ASP.NET HTTP (.asmx files), themes, master pages y otros archivos fuente. Para más información ver ASP.NET Web Site Layout y ASP.NET Application Life Cycle Overview.

Salida de la compilación


Cuando el código es compilado, los assemblys resultantes son "cacheados" en una carpeta en el servidor. Esta carpeta requiere los permisos apropiados para que tu código compilado se ejecute correctamente. Puedes configurar tanto la ubicación de la carpeta de compilación como los permisos con los que opera tu código compilado.

En producción, la primera vez que se accede al sitio, se compila y genera una carpeta dentro de Temporary ASP.NET Files de forma automática y se copian las DLL desde el \Bin a esta nueva carpeta dentro de Temporary ASP.NET Files.
Dejemos claro que no se genera una nueva carpeta aquí cada vez que se reinicia el IIS, a menos que esté bloqueado la carpeta \Bin y no deja copiarse a Temporary ASP.NET Files (problema conocido como "Copias Sombras/Shadow Copy". El error No se puede crear ni realizar copias sombra de 'dll' si el archivo ya existe/Cannot create/shadow copy 'dll' when that file already exists. Este error se resuelve desinstalando Windows Search del servidor, expluyendo la carpeta Temporary ASP.NET Files del escaneo del Antivirus, en el IIS moviendo la WebApp que da problemas a una AppPool propio cuando comparte el AppPool con más sitios), entonces al hacer un IIS reset verás la DLL copiada aquí.

Ubicación de la carpeta de compilación

Por defecto, cuando compilas una aplicación web, el código compilado queda en la conocida carpeta Temporary ASP.NET Files. Esta carpeta está dentro de la carpeta donde tienes instalado el Framework .Net. La ruta típica es:
%SystemRoot%\Microsoft.NET\Framework\versionNumber\Temporary ASP.NET Files
Por ejemplo, en una máquina de 64 bits, si está instalado el Framework 2.0 tendrías la carpeta:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files

Permisos requeridos para la carpeta de compilación

El proceso de instalación del Framework .NET crea la carpeta Temporary ASP.NET Files y le asigna permisos de acceso a la cuenta local de ASP.NET, el cual tiene los permisos necesarios para acceder al código compilado. Si modificas la configuración u opciones de la cuenta de usuario, asegúrate que la cuenta tenga suficientes permisos a la carpeta de Temporary ASP.NET Files. Para más detalles, ve How to: Run aspnet_wp.exe Under a User Account.

Configuración de la carpeta de compilación

ASP.NET crea una subcarpeta dentro de la carpeta Temporary ASP.NET File para cada aplicación. Puedes configurar la ubicación raíz usando el atributo tempDirectory de la sección compilación del archivo de configuración. Este atributo opcional permite especificar el directorio para almacenar los archivos temporales durante la compilación. Por defecto es un string vacío (""). En caso de ser un string vacío y si el proceso actual tiene los permisos de acceso necesario, los archivos son guardados en el siguiente directorio:
%FrameworkInstallLocation%\Temporary ASP.NET Files
Para más información, ver el Elemento compilación (ASP.NET Settings Schema) y la propiedad TempDirectory de la sección CompilationSection.

Soporte multilenguaje


ASP.NET 2.0 soporta múltiples lenguajes de programación en una misma aplicación web. En la carpeta App_Code, puedes especificar una subcarpeta para cada lenguaje, como C# y Visual Basic. ASP.NET creará un assembly separado para cada subcarpeta. Para más información ver Shared Code Folders in ASP.NET Web Sites y Walkthrough: Developing Web Sites Using Multiple Programming Languages.

Optimizando la compilación dinámica


A partir de un HotFix del Framework 3.5 se puede usar el atributo optimizeCompilations del web.config. Más info aquí.

Ventajas y desventajas de las compilación dinámica


La compilación dinámica de ASP.NET permite modificar el código fuente sin tener que explícitamente tener que compilar el código ni hacer un deploy en un servidor (Nota del traductor: como ejemplo práctico, permite que tengas un sitio web en un ambiente pre-productivo por ejemplo, donde tienes las dll tanto como los fuentes *.aspx.cs, y poder cambiar estos fuentes en "caliente", le das F5 al navegador y listo, el código se verá reflejado en el sitio. sirve para probar más rápidamente un cambio de un sitio en la capa web. Ahora si el proyecto web, usa un dll de otro proyecto, aunque tengas los fuentes de ese otro proyecto, si los cambias, no tomará el cambio en el proyecto web ya que ahí si requiere compilar dicha dll). Si modificas un código fuente, ASP.NET automáticamente recompila el archivo y actualiza todos los recursos que usan dicho archivo. No es necesario restetear el IIS para que tome el cambio a menos que la sección del web.config haya cambiado. Adicionalmente, puedes extender el sistema de compilación de ASP.NET al crear proveedores para que nuevos tipos de archivos sean llamados durante la compilación. La compilación dinámica beneficia al sistema de compilación de ASP.NET y es compatible con las estructuras y tipos de aplicación antiguas.

Hay ciertos aspectos que la compilación dinámica no ofrece. La Compilación dinámica puede hacer más lento el tiempo de respuesta de la carga inicial de un sitio por parte del usuario, ya que las páginas y archivos de código deben ser compilados la primera vez que son solicitados. Esto podría ser un problema si es un sitio muy grande y es cambiado frecuentemente.
La Compilación dinámica no identifica errores de compilación antes que los usuarios accedan al sitio.
También, la compilación dinámica no provee la funcionalidad de crear una versión compilada de un sitio que ya ha sido deployado en producción sin tener el código fuente.
Si alguno de esos problemas te afecta, lo mejor es precompilar el sitio y deployarlo a producción sólo con los elementos necesarios (sin todos los fuentes), un ejemplo clásico es la opción Publicar de Visual Studio. Para más información, ver ASP.NET Web Site Precompilation Overview.

Fuente


lunes, 16 de noviembre de 2015

Testeando UrlScan 3.1 para IIS 7.5

Instalación


El otro día estaba viendo algo UrlScan, es una herramienta free de Microsoft para analizar requests así protegerte de ataques SQL Injection o Script Injection de forma simple, definiendo parámetros y opciones en un archivo ini.

Bajé la versión de 64 bits de https://www.microsoft.com/en-us/download/details.aspx?id=5728

Leí la documentación de: https://support.microsoft.com/es-es/kb/326444

El .ini queda instalado por defecto en: C:\Windows\System32\inetsrv\urlscan\UrlScan.ini

(Mi .ini que usé lo dejé al final)

La carpeta con los Logs: C:\Windows\System32\inetsrv\urlscan\logs\ le dí permiso de escritura al usuario IIS. En IIS 6 darle permiso de escritura al usuario IIS_WPG, y para IIS 7 u superior dale permisos a IIS_IUSRS.

En mi caso sólo usaré un filtro global, pero si quieres aplicar el filtro sólo para un sitio web, debes registrar la DLL como filtro en Web Sites -> Properties -> ISAPI Filters como dice aquí.

Al final de la instalación, reinicié el IIS con la línea de comandos iisreset.

Pruebas


NOTA: Por cada cambio en el .ini recomiendan Reciclar el Pool del sitio probado para que tome el cambio, si embargo a veces me tomaba sin necesidad de esto.

Error tilde IIS

Para corregir este conocido error de IIS 7 y 8: Microsoft IIS tilde directory enumeration, debes ir a Inicio -> Ejecutar:

%windir%\system32\inetsrv\urlscan

Agregar en UrlScan.ini (no requiere reiniciar el servidor, si aplicar un IIS reset)

[DenyUrlSequences]
~ ; para corregir error Microsoft IIS tilde directory enumeration

NOTA: Si tienes instalado Acunetix para auditar la seguridad de tus sitios, este error de tilde lo detecta de una, pero con esta corrección deja de aparecer el error.

SQL INJECTION

Al probar con la URL que tiene un "intento" de SQL Injection:

http://misitio.cl/index.asp?select=1

Resultado: Error 404 con detalles



Resultado desde fuera del sitio: Error 404 sin detalles (este error daría si el UrlScan está en producción y queremos acceder desde afuera):



Como nota, el mismo error da cuando escribimos un "intento" de Script Injection:

http://misitio.cl/index.asp?title=<meta%20http-equiv="refresh"%20content="0;">

Logging


El log, en mi caso, urlscan.111615.log, (es 16-nov-2015) va quedando con las entradas bloqueadas y el string o secuencia inválida:

#Software: Microsoft UrlScan 3.1
#Version: 1.0
#Date: 2015-11-16 20:09:41
#Fields: Date Time c-ip s-siteid cs-method cs-uri x-action x-reason x-context cs-data x-control
2015-11-16 20:09:43 172.31.17.26 9 GET /index.asp?item=%3C Rejected disallowed+query+string+sequence query+string - <

Errores comunes

El log solo logea los títulos de las columnas

-Revisa el archivo ini, que no tengas un [Options] ya que en el ejemplo del mismo .ini dice [Options].

Yo tenía:

[Options]
RuleList=SQL Injection

Y debe ser sólo:

RuleList=SQL Injection

-Revisa que le hayas dado permisos de escritura a la carpeta log al usuario de IIS.

Conclusión


UrlScan es la solución para evitar andar programando en el código (IF request ("%, <, >, etc...) == "error") ya que sólo mediante configuración filtras todo lo malo .

Referencias



Anexo: Mi archivo ini


Mi .ini que usé es este. Notar que dejé ScanHeaders=Cookie para incluir que si se crea una Cookie, se validen los strings que tenga como valor:
[options]

UseAllowVerbs=1                ; If 1, use [AllowVerbs] section, else use the
                               ; [DenyVerbs] section.   The default is 1.

UseAllowExtensions=0           ; If 1, use [AllowExtensions] section, else
                               ; use the [DenyExtensions] section. The
                               ; default is 0.

NormalizeUrlBeforeScan=1       ; If 1, canonicalize URL before processing.
                               ; The default is 1.  Note that setting this
                               ; to 0 will make checks based on extensions,
                               ; and the URL unreliable and is therefore not
                               ; recommend other than for testing.

VerifyNormalization=1          ; If 1, canonicalize URL twice and reject
                               ; request if a change occurs.  The default
                               ; is 1.

AllowHighBitCharacters=0       ; If 1, allow high bit (ie. UTF8 or MBCS)
                               ; characters in URL.  The default is 0.

AllowDotInPath=0               ; If 1, allow dots that are not file
                               ; extensions. The default is 0. Note that
                               ; setting this property to 1 will make checks
                               ; based on extensions unreliable and is
                               ; therefore not recommended other than for
                               ; testing.

RemoveServerHeader=0           ; If 1, remove the 'Server' header from
                               ; response.  The default is 0.

EnableLogging=1                ; If 1, log UrlScan activity.  The
                               ; default is 1.  Changes to this property
                               ; will not take effect until UrlScan is
                               ; restarted.

PerProcessLogging=0            ; This property is deprecated for UrlScan
                               ; 3.0 and later.  UrlScan 3.0 and later can
                               ; safely log output from multiple processes
                               ; to the same log file.  Changes to this
                               ; property will not take effect until
                               ; UrlScan is restarted.

AllowLateScanning=0            ; If 1, then UrlScan will load as a low
                               ; priority filter.  The default is 0.  Note
                               ; that this setting should only be used in
                               ; the case where there another installed
                               ; filter is modifying the URL and you wish
                               ; to have UrlScan apply its rules to the
                               ; rewritten URL.  Changes to this property
                               ; will not take effect until UrlScan is
                               ; restarted.

PerDayLogging=1                ; If 1, UrlScan will produce a new log each
                               ; day with activity in the form
                               ; 'UrlScan.010101.log'. If 0, UrlScan will
                               ; log activity to urlscan.log.  The default
                               ; is 1.  Changes to this setting will not
                               ; take effect until UrlScan is restarted.

UseFastPathReject=0            ; If 1, then UrlScan will not use the
                               ; RejectResponseUrl.  On IIS versions less
                               ; than 6.0, this will also prevent IIS
                               ; from writing rejected requests to the
                               ; W3SVC log.  UrlScan will log rejected
                               ; requests regardless of this setting.  The
                               ; default is 0.

LogLongUrls=0                  ; This property is deprecated for UrlScan 3.0
                               ; and later. UrlScan 3.0 and later will
                               ; always include the complete URL in its log
                               ; file.

UnescapeQueryString=1          ; If 1, UrlScan will perform two passes on
                               ; each query string scan, once with the raw
                               ; query string and once after unescaping it.
                               ; If 0, UrlScan will only look at the raw
                               ; query string as sent by the client.  The
                               ; default is 1. Note that if this property is
                               ; set to 0, then checks based on the query
                               ; string will be unreliable.

;
; If UseFastPathReject is 0, then UrlScan will send
; rejected requests to the URL specified by RejectResponseUrl.
; If not specified, '/Rejected-by-UrlScan' will be used.
; Changes to this setting will not take effect until UrlScan
; is restarted.
;
; Note that setting "RejectResponseUrl=/~*" will put UrlScan into Logging
; Only Mode.  In this mode, UrlScan will process all requests per the
; config settings, but it will only log the results and not actually
; reject the requests.  This mode is useful for testing UrlScan settings
; on a production server without actually interrupting requests.
;

RejectResponseUrl=

;
; LoggingDirectory can be used to specify the directory where the
; log file will be created.  This value should be the absolute path
; (ie. c:\some\path).  If not specified, then UrlScan will create
; the log in the same directory where the UrlScan.dll file is located.
; Changes to this setting will not take effect until UrlScan is
; restarted.
;

LoggingDirectory=Logs

;
; If RemoveServerHeader is 0, then AlternateServerName can be
; used to specify a replacement for IIS's built in 'Server' header
;

AlternateServerName=

;
; UrlScan supports custom rules that can be applied in addition to the other
; checks and options specified in this configuration file.  Rules should be
; listed in a comma separated string in the RuleList property.  Each rule in
; the list corresponds to two sections in this configuration file, one
; containing the options for the rule, and one containing deny strings for
; the rule.
;
; Here is an example:
;
;   [Options]
;   RuleList=Rule1
;
;   [Rule1]
;   AppliesTo=.exe,.dll        ; A comma separated list of file extensions to
;                              ; which the rule applies.  If not specified,
;                              ; the rule will be applied to all requests.
;
;   DenyDataSection=Rule1 Data ; The name of the section containing the
;                              ; rule's deny strings
;
;   ScanURL=0                  ; If 1, the URL will be scanned for deny
;                              ; strings. The default is 0.
;
;   ScanAllRaw=0               ; If 1, then the raw request header data will
;                              ; be scanned for deny strings.  The default
;                              ; is 0.
;
;   ScanQueryString=0          ; If 1, the the query string will be scanned
;                              ; for deny strings.  The default is 0.  Note
;                              ; that if UnescapeQueryString=1 is set in the
;                              ; [Options] section, then two scans will be
;                              ; made of the query string, one with the raw
;                              ; query string and one with the query string
;                              ; unescaped.
;
;   ScanHeaders=               ; A comma separated list of request headers to
;                              ; be scanned for deny strings.  The default is
;                              ; no headers.
;
;   DenyUnescapedPercent=0     ; If 1, UrlScan will scan the specified part
;                              ; of the raw request for a % character that is
;                              ; not used as an escape sequence.  If found,
;                              ; the request will be rejected.  This check
;                              ; can be used with ScanQueryString=1,
;                              ; ScanAllRaw=1, or the list of ScanHeaders.
;                              ; The default is 0.  Note that if you want to
;                              ; deny non-escaped % characters in the URL,
;                              ; you can set VerifyNormalization=0 in the
;                              ; [Options] section and then add % as a
;                              ; [DenyUrlSequences] entry.
;
;   [Rule1 data]
;   string1
;   string2
;

RuleList=SQL Injection

[SQL Injection]
AppliesTo=.asp,.aspx
DenyDataSection=SQL Injection Strings
ScanUrl=0
ScanAllRaw=0
ScanQueryString=1
ScanHeaders=Cookie:


[SQL Injection Strings]
--
@ ; also catches @@
alter
cast
convert
create
declare
delete
drop
exec ; also catches execute
fetch
insert
kill
select

[RequestLimits]

;
; The entries in this section impose limits on the length
; of allowed parts of requests reaching the server.
;
; It is possible to impose a limit on the length of the
; value of a specific request header by prepending "Max-" to the
; name of the header.  For example, the following entry would
; impose a limit of 100 bytes to the value of the
; 'Content-Type' header:
;
;   Max-Content-Type=100
;
; Any headers not listed in this section will not be checked for
; length limits.
;
; There are 3 special case limits:
;
;   - MaxAllowedContentLength specifies the maximum allowed
;     numeric value of the Content-Length request header.  For
;     example, setting this to 1000 would cause any request
;     with a content length that exceeds 1000 to be rejected.
;     The default is 30000000.
;
;   - MaxUrl specifies the maximum length of the request URL,
;     not including the query string. The default is 260 (which
;     is equivalent to MAX_PATH).
;
;   - MaxQueryString specifies the maximum length of the query
;     string.  The default is 2048.
;

MaxAllowedContentLength=30000000
MaxUrl=260
MaxQueryString=2048

[AllowVerbs]

;
; The verbs (aka HTTP methods) listed here are those commonly
; processed by a typical IIS server.
;
; Note that these entries are effective if "UseAllowVerbs=1"
; is set in the [Options] section above.
;

GET
HEAD
POST

[DenyVerbs]

;
; The verbs (aka HTTP methods) listed here are used for publishing
; content to an IIS server via WebDAV.
;
; Note that these entries are effective if "UseAllowVerbs=0"
; is set in the [Options] section above.
;

PROPFIND
PROPPATCH
MKCOL
DELETE
PUT
COPY
MOVE
LOCK
UNLOCK
OPTIONS
SEARCH

[DenyHeaders]

;
; The following request headers alter processing of a
; request by causing the server to process the request
; as if it were intended to be a WebDAV request, instead
; of a request to retrieve a resource.
;

Translate:
If:
Lock-Token:
Transfer-Encoding:

[AllowExtensions]

;
; Extensions listed here are commonly used on a typical IIS server.
;
; Note that these entries are effective if "UseAllowExtensions=1"
; is set in the [Options] section above.
;

.htm
.html
.txt
.jpg
.jpeg
.gif

[DenyExtensions]

;
; Extensions listed here either run code directly on the server,
; are processed as scripts, or are static files that are
; generally not intended to be served out.
;
; Note that these entries are effective if "UseAllowExtensions=0"
; is set in the [Options] section above.
;
; Also note that ASP scripts are denied with the below
; settings.  If you wish to enable ASP, remove the
; following extensions from this list:
;    .asp
;    .cer
;    .cdx
;    .asa
;

; Deny executables that could run on the server
.exe
.bat
.cmd
.com

; Deny infrequently used scripts
.htw     ; Maps to webhits.dll, part of Index Server
.ida     ; Maps to idq.dll, part of Index Server
.idq     ; Maps to idq.dll, part of Index Server
.htr     ; Maps to ism.dll, a legacy administrative tool
.idc     ; Maps to httpodbc.dll, a legacy database access tool
.shtm    ; Maps to ssinc.dll, for Server Side Includes
.shtml   ; Maps to ssinc.dll, for Server Side Includes
.stm     ; Maps to ssinc.dll, for Server Side Includes
.printer ; Maps to msw3prt.dll, for Internet Printing Services

; Deny various static files
.ini     ; Configuration files
.log     ; Log files
.pol     ; Policy files
.dat     ; Configuration files
.config  ; Configuration files

[AlwaysAllowedUrls]
;
; URLs listed here will always be explicitly allowed by UrlScan
; and will bypass all UrlScan checks.  URLs must be listed
; with a leading '/' character.  For example:
;
;   /SampleURL.htm
;

[DenyUrlSequences]
;
; If any character sequences listed here appear in the URL for
; any request, that request will be rejected.
;

..  ; Don't allow directory traversals
./  ; Don't allow trailing dot on a directory name
\   ; Don't allow backslashes in URL
:   ; Don't allow alternate stream access
%   ; Don't allow escaping after normalization
&   ; Don't allow multiple CGI processes to run on a single request

[AlwaysAllowedQueryStrings]
;
; Query strings listed here will always be explicitly allowed by
; UrlScan and will bypass all query string based checks.
;


[DenyQueryStringSequences]
;
; If any character sequences listed here appear in the query
; string for any request, that request will be rejected.
;

<   ; Commonly used by script injection attacks
>   ; Commonly used by script injection attacks