text:
<?php include('header.php'); ?>
<?php include('dbconn.php'); ?>

    <?php
    $filters = array
        (
        "username" => array
            (
            "filter" => FILTER_SANITIZE_STRING,
            "options" => array
                (
                "min_range" => 1,
                "max_range" => 10
            )
        ),
        "password" => array
            (
            "filter" => FILTER_SANITIZE_STRING,
            "options" => array
                (
                "min_range" => 1
            )
        ),
        "repeatPassword" => array
            (
            "filter" => FILTER_SANITIZE_STRING,
            "options" => array
                (
                "min_range" => 1
            )
        ),
        "contactNum" => array
            (
            "filter" => FILTER_SANITIZE_STRING,
            "options" => array
                (
                "min_range" => 0,
                "max_range" => 12
            )
        ),
        "email" => FILTER_VALIDATE_EMAIL,
        "area" => array
            (
            "filter" => FILTER_VALIDATE_INT
        ),
        "city" => array
            (
            "filter" => FILTER_VALIDATE_INT
        ),
    );

    $inputs = filter_input_array(INPUT_POST, $filters);

    if (!$inputs["username"]) {
        echo("
Username is required and max. range is 10.
");
    } else {

        $username = $_POST['username'];
        $password = $_POST['password'];
        $contactNumber = $_POST["contact"];
          $asi = $_POST['email'];
        $email = $_POST['location'];
        $ex=$_POST['excercise'];

        $selectOption = $_POST['cars'];

        if($selectOption=="1")
        {

            $ad="male";
        }
        else
        {
                $ad="female";
        }

		//$city = $_POST["qualify"];

        //

       // $query = "INSERT INTO user_auth(username, password, contact_num, email,prev) VALUES('$username', '$password', '$email', '$contactNumber', '$ad')";
            $query = "INSERT INTO patient(age, blood, weight, food,location,exercise,gender) VALUES('$username', '$password','$asi', '$contactNumber', '$email','$ex', '$ad')";

        //$area = $inputs['area'];

        // Check if user_auth table is empty. If empty, then make the first logged in user as SUPER ADMIN. Else make this user as a NORMAL USER (member).

            // End checking.

        $sql = mysql_query($query) or die(mysql_error());

            ?>

            <?php
        }

    if (!$inputs) {
        echo 'Go Back';
    }
    ?>

<?php include('footer.php'); ?>


text: Before you begin, [sign up for a Facebook Developer account](https://developers.facebook.com/).

redpajama_set_name: RedPajamaGithub


text:
package org.trianacode.TrianaCloud.PegasusExecutor;

import org.apache.log4j.Logger;
import org.shiwa.desktop.data.description.SHIWABundle;
import org.trianacode.TrianaCloud.Utils.MD5;
import org.trianacode.TrianaCloud.Utils.Task;
import org.trianacode.TrianaCloud.Utils.TaskExecutor;
import org.trianacode.TrianaCloud.Utils.TaskOps;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Run Pegasus-plan with values found in a SHIWA Bundle
 */
public class PegasusExecutor extends TaskExecutor implements Runnable {

    private Logger logger = Logger.getLogger(this.getClass().toString());

    Task task;
    File temp;
    private byte[] out = new byte[0];

    @Override
    public byte[] executeTask() {

        try {
            Thread thread = new Thread(this);
            thread.run();
            thread.join();

        } catch (Exception e) {
            System.out.println("Error in executor");
            e.printStackTrace();
        }

        try {
            task.setReturnDataType("binary");
            task.setReturnData(out);
            task.setReturnDataMD5(MD5.getMD5Hash(task.getReturnData()));
            return TaskOps.encodeTask(task);
        } catch (IOException e) {
            e.printStackTrace();
            return new byte[0];
        }
    }

    @Override
    public void setTask(Task t) {
        this.task = t;
        temp = null;
        try {
            temp = File.createTempFile("data", ".bundle");
            //temp.deleteOnExit();

            System.out.println(temp.getPath());

            FileOutputStream o = new FileOutputStream(temp);
            o.write(task.getData());

            System.out.println(task.getName());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getRoutingKey() {
        return "*.pegasus";
    }

    @Override
    public void run() {
        SHIWABundle b = null;
        try {
            b = new SHIWABundle(temp);
            RunPegasusPlan pegasusPlan = new RunPegasusPlan();
            out = pegasusPlan.executeBundle(b, null);
//            SHIWABundle execedBundle = testExecution(b);
//            out = TrianaBundle.getFileBytes(
//                    DataUtils.bundle(File.createTempFile("execed", ".tmp"),
//                            execedBundle.getAggregatedResource()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


text:
    Bridge.define("System.Diagnostics.Debug", {
        statics: {
            fields: {
                s_lock: null,
                s_indentLevel: 0,
                s_indentSize: 0,
                s_needIndent: false,
                s_indentString: null,
                s_ShowAssertDialog: null,
                s_WriteCore: null,
                s_shouldWriteToStdErr: false
            },
            props: {
                AutoFlush: {
                    get: function () {
                        return true;
                    },
                    set: function (value) { }
                },
                IndentLevel: {
                    get: function () {
                        return System.Diagnostics.Debug.s_indentLevel;
                    },
                    set: function (value) {
                        System.Diagnostics.Debug.s_indentLevel = value < 0 ? 0 : value;
                    }
                },
                IndentSize: {
                    get: function () {
                        return System.Diagnostics.Debug.s_indentSize;
                    },
                    set: function (value) {
                        System.Diagnostics.Debug.s_indentSize = value < 0 ? 0 : value;
                    }
                }
            },
            ctors: {
                init: function () {
                    this.s_lock = { };
                    this.s_indentSize = 4;
                    this.s_ShowAssertDialog = System.Diagnostics.Debug.ShowAssertDialog;
                    this.s_WriteCore = System.Diagnostics.Debug.WriteCore;
                    this.s_shouldWriteToStdErr = Bridge.referenceEquals(System.Environment.GetEnvironmentVariable("COMPlus_DebugWriteToStdErr"), "1");
                }
            },
            methods: {
                Close: function () { },
                Flush: function () { },
                Indent: function () {
                    System.Diagnostics.Debug.IndentLevel = (System.Diagnostics.Debug.IndentLevel + 1) | 0;
                },
                Unindent: function () {
                    System.Diagnostics.Debug.IndentLevel = (System.Diagnostics.Debug.IndentLevel - 1) | 0;
                },
                Print: function (message) {
                    System.Diagnostics.Debug.Write$2(message);
                },
                Print$1: function (format, args) {
                    if (args === void 0) { args = []; }
                    System.Diagnostics.Debug.Write$2(System.String.formatProvider.apply(System.String, [null, format].concat(args)));
                },
                Assert: function (condition) {
                    System.Diagnostics.Debug.Assert$2(condition, "", "");
                },
                Assert$1: function (condition, message) {
                    System.Diagnostics.Debug.Assert$2(condition, message, "");
                },
                Assert$2: function (condition, message, detailMessage) {
                    if (!condition) {
                        var stackTrace;

                        try {
                            throw System.NotImplemented.ByDesign;
                        } catch ($e1) {
                            $e1 = System.Exception.create($e1);
                            stackTrace = "";
                        }

                        System.Diagnostics.Debug.WriteLine$2(System.Diagnostics.Debug.FormatAssert(stackTrace, message, detailMessage));
                        System.Diagnostics.Debug.s_ShowAssertDialog(stackTrace, message, detailMessage);
                    }
                },
                Assert$3: function (condition, message, detailMessageFormat, args) {
                    if (args === void 0) { args = []; }
                    System.Diagnostics.Debug.Assert$2(condition, message, System.String.format.apply(System.String, [detailMessageFormat].concat(args)));
                },
                Fail: function (message) {
                    System.Diagnostics.Debug.Assert$2(false, message, "");
                },
                Fail$1: function (message, detailMessage) {
                    System.Diagnostics.Debug.Assert$2(false, message, detailMessage);
                },
                FormatAssert: function (stackTrace, message, detailMessage) {
                    var newLine = (System.Diagnostics.Debug.GetIndentString() || "") + ("\n" || "");
                    return "---- DEBUG ASSERTION FAILED ----" + (newLine || "") + "---- Assert Short Message ----" + (newLine || "") + (message || "") + (newLine || "") + "---- Assert Long Message ----" + (newLine || "") + (detailMessage || "") + (newLine || "") + (stackTrace || "");
                },
                WriteLine$2: function (message) {
                    System.Diagnostics.Debug.Write$2((message || "") + ("\n" || ""));
                },
                WriteLine: function (value) {
                    System.Diagnostics.Debug.WriteLine$2(value != null ? Bridge.toString(value) : null);
                },
                WriteLine$1: function (value, category) {
                    System.Diagnostics.Debug.WriteLine$4(value != null ? Bridge.toString(value) : null, category);
                },
                WriteLine$3: function (format, args) {
                    if (args === void 0) { args = []; }
                    System.Diagnostics.Debug.WriteLine$2(System.String.formatProvider.apply(System.String, [null, format].concat(args)));
                },
                WriteLine$4: function (message, category) {
                    if (category == null) {
                        System.Diagnostics.Debug.WriteLine$2(message);
                    } else {
                        System.Diagnostics.Debug.WriteLine$2((category || "") + ":" + (message || ""));
                    }
                },
                Write$2: function (message) {
                    System.Diagnostics.Debug.s_lock;
                    {
                        if (message == null) {
                            System.Diagnostics.Debug.s_WriteCore("");
                            return;
                        }
                        if (System.Diagnostics.Debug.s_needIndent) {
                            message = (System.Diagnostics.Debug.GetIndentString() || "") + (message || "");
                            System.Diagnostics.Debug.s_needIndent = false;
                        }
                        System.Diagnostics.Debug.s_WriteCore(message);
                        if (System.String.endsWith(message, "\n")) {
                            System.Diagnostics.Debug.s_needIndent = true;
                        }
                    }
                },
                Write: function (value) {
                    System.Diagnostics.Debug.Write$2(value != null ? Bridge.toString(value) : null);
                },
                Write$3: function (message, category) {
                    if (category == null) {
                        System.Diagnostics.Debug.Write$2(message);
                    } else {
                        System.Diagnostics.Debug.Write$2((category || "") + ":" + (message || ""));
                    }
                },
                Write$1: function (value, category) {
                    System.Diagnostics.Debug.Write$3(value != null ? Bridge.toString(value) : null, category);
                },
                WriteIf$2: function (condition, message) {
                    if (condition) {
                        System.Diagnostics.Debug.Write$2(message);
                    }
                },
                WriteIf: function (condition, value) {
                    if (condition) {
                        System.Diagnostics.Debug.Write(value);
                    }
                },
                WriteIf$3: function (condition, message, category) {
                    if (condition) {
                        System.Diagnostics.Debug.Write$3(message, category);
                    }
                },
                WriteIf$1: function (condition, value, category) {
                    if (condition) {
                        System.Diagnostics.Debug.Write$1(value, category);
                    }
                },
                WriteLineIf: function (condition, value) {
                    if (condition) {
                        System.Diagnostics.Debug.WriteLine(value);
                    }
                },
                WriteLineIf$1: function (condition, value, category) {
                    if (condition) {
                        System.Diagnostics.Debug.WriteLine$1(value, category);
                    }
                },
                WriteLineIf$2: function (condition, message) {
                    if (condition) {
                        System.Diagnostics.Debug.WriteLine$2(message);
                    }
                },
                WriteLineIf$3: function (condition, message, category) {
                    if (condition) {
                        System.Diagnostics.Debug.WriteLine$4(message, category);
                    }
                },
                GetIndentString: function () {
                    var $t;
                    var indentCount = Bridge.Int.mul(System.Diagnostics.Debug.IndentSize, System.Diagnostics.Debug.IndentLevel);
                    if (System.Nullable.eq((System.Diagnostics.Debug.s_indentString != null ? System.Diagnostics.Debug.s_indentString.length : null), indentCount)) {
                        return System.Diagnostics.Debug.s_indentString;
                    }
                    return ($t = System.String.fromCharCount(32, indentCount), System.Diagnostics.Debug.s_indentString = $t, $t);
                },
                ShowAssertDialog: function (stackTrace, message, detailMessage) {
                    if (System.Diagnostics.Debugger.IsAttached) {
                        debugger;
                    } else {
                        var ex = new System.Diagnostics.Debug.DebugAssertException(message, detailMessage, stackTrace);
                        System.Environment.FailFast$1(ex.Message, ex);
                    }
                },
                WriteCore: function (message) {
                    System.Diagnostics.Debug.WriteToDebugger(message);

                    if (System.Diagnostics.Debug.s_shouldWriteToStdErr) {
                        System.Diagnostics.Debug.WriteToStderr(message);
                    }
                },
                WriteToDebugger: function (message) {
                    if (System.Diagnostics.Debugger.IsLogging()) {
                        System.Diagnostics.Debugger.Log(0, null, message);
                    } else {
                        System.Console.WriteLine(message);

                    }
                },
                WriteToStderr: function (message) {
                    System.Console.WriteLine(message);

                }
            }
        }
    });


text:
<?php

namespace Kraken\Filesystem;

use League\Flysystem\AdapterInterface;

interface FilesystemAdapterInterface extends AdapterInterface
{}


text:
<!doctype html>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="description" content="A front-end template that helps you build fast, modern mobile web apps.">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
    <title>Varredura de Porta</title>

    <link rel="shortcut icon" href="images/favicon.png">

    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="https://code.getmdl.io/1.2.1/material.deep_purple-pink.min.css">
    <link rel="stylesheet" href="styles.css">

Varredura de Portas

          Introdução
 		  Motivação
 		  Principais Técnicas
          NMap
          ZMap
          Comparações
          Teste Prático
          Conclusão
          Perguntas
          Bibliografia

                       Alunos

                        Juliano Marinho

                        Lucas de Paula

                        Lucas Rolim

                        Rodrigo Haddad

                        Professor:

                        Otto Carlos Muniz Bandeira Duarte

Resumo

Varredura de porta, também conhecida com análise de porta ou escaneamento de porta, é o nome dado à técnica usada para identificar o estado de uma porta em uma rede. O principal objetivo dessa técnica é encontrar portas abertas e, dessa forma, uma vulnerabilidade na rede ou sistema. Trata-se de uma técnica largamente utilizada por hackers para realizar ataques ou identificar alvos, uma vez que todos os computadores conectados na internet ou com uma rede local necessariamente precisam ter algumas de suas portas abertas para eventuais trocas de dados ou informações.

                     Em essência, a varredura de portas consiste em enviar mensagens para cada uma das portas da rede alvo, uma mensagem de cada vez, e analisar a resposta obtida. O tipo de resposta pode evidenciar, por exemplo, que uma determinada porta está vulnerável. Esse ato, quando feito em pequena escala, não pode ser identificado como um crime, a não ser que passe a enviar tantas requisições que possa ser considerado uma negação de serviço (DoS).

                    Uma analogia comum para o fácil entendimento é que a varredura de portas é como um bandido que toca diversas campainhas em uma rua. A resposta dos moradores, ou a ausência desses, pode identificar uma vulnerabilidade que pode ser aproveitada pelo mau elemento. Em contrapartida, o ato de tocar a campainha é perfeitamente dentro das leis, a não ser que seja com tal frequência que prejudique os moradores da residência.

                    Ao longo do desenvolvimento deste trabalho, portanto, vamos analisar não só o conceito da varredura de portas, mas também as implicações e os ferramentais mais importantes para o bom entendimento deste tópico.

Conceitos Essenciais

Porta

                    Portas são um mecanismo essencial de todo computador. Elas proporcionam as interfaces de saída e entrada que o dispositivo precisa para se comunicar com periféricos e outros computadores em uma rede local ou internet.

                    Uma porta pode ser física ou virtual. Portas físicas, como por exemplo portas ethernet e portas USB, são usadas para aplicações com roteadores e outros periféricos. Portas virtuais, que serão as quais daremos maior atenção neste trabalho, como as dos padrões TCP e UDP, são usadas para estabelecer a conexão e troca de serviços e dados entre computadores em rede.

0 até 1023  - São as consideradas "portas conhecidas". Portas nesse intervalo são fornecidas apenas para serviços estabelecidos e grandes empresas ou centros de pesquisa de confiança.

1024 até 49151 - São as chamadas "portas registradas". Esse nome significa que as portas nesse intervalo podem ser registradas para protocolos específicos por grandes corporações.

49152 até 65535  - É o intervalo que engloba as portas dinâmicas e as portas privadas. Portas nesse intervalo podem ser usadas por praticamente qualquer um e, portanto, são as com maior probabilidade de haver vulnerabilidade.

Firewall

                    Firewall é um dispositivo de segurança de rede, baseado em software ou hardware, que controla a entrada e saída de tráfego da rede baseado em um conjunto de regras pré estabelecidas.

                    Quando estamos falando de varredura de portas o  Firewall é considerado o melhor tipo de defesa em que se pode investir. Um Firewall pode ser configurado para negar acesso ou tornar "invisível" o estado das portas para requisições que sigam determinado padrão ou cumpram certos requisitos. Dessa forma, o computador defendido fica de certa forma invisível para visitantes ou sistemas de requisição indesejados ou maliciosos.

Direitos Autorais:

                        "Este trabalho foi totalmente produzido pelos autores que declaram não terem violado os direitos autorais de terceiros, sejam eles pessoas físicas ou jurídicas. Havendo textos, tabelas e figuras transcritos de obras de terceiros com direitos autorais protegidos ou de domínio público tal como idéias e conceitos de terceiros, mesmo que sejam encontrados na Internet, os mesmos estão com os devidos créditos aos autores originais e estão incluídas apenas com o intuito de deixar o trabalho autocontido. O(s) autor(es) tem(êm) ciência dos Artigos 297 a 299 do Código Penal Brasileiro e também que o uso do artifício de copiar/colar texto de outras fontes e outras formas de plágio é um ato ilícito, condenável e passível de punição severa. No contexto da Universidade a punição não precisa se restringir à reprovação na disciplina e pode gerar um processo disciplinar que pode levar o(s) aluno(s) à suspensão;"

Importância da Varredura de portas

                   O estudo de técnicas de varredura de porta e o bom entendimento de como gerenciar o fluxo de informações que passa
                   pelas portas de um dispositivo vem se tornando cada vez mais importante nos dias atuais. Grande parte do aumento
                   dessa importância advém do fato da maior parte de técnicas mais avançadas de exploração de falhas de segurança
                    utilizarem a varredura de portas como uma primeira "sondagem" em suas vítimas para encontrar pontos de ataque.
                     Outro grande fator influenciador é o crescimento de dispositivos conectados a internet. Com o possível sucesso
                      da chamada Internet das Coisas, o número de dispositivos conectados na rede aumentará de maneira jamais
                       vista, o que por consequência aumentará o número de portas que precisarão ser utilizadas e exigirá dos
                        profissionais de segurança uma estruturação e gestão do fluxo de abertura e fechamento de portas de
                         maneira muito mais eficiente.

Portas e os perigos de as deixarem abertas

                    De acordo com o Wikipédia temos a seguinte definição para uma porta:

Uma porta é uma conexão virtual/lógica de dados que pode ser usada por programas para
                     trocar dados diretamente, ao invés de passar por um arquivo ou outro local de armazenamento
                    temporário. As mais comuns são as
                    portas do tipo TCP e UDP, que são usadas para trocar dados entre computadores na Internet.

                    Uma porta aberta é uma superfície de ataque e um dos princípios fundamentais de Segurança da Informação é
                    o de diminuir ao máximo as superfícies de ataque e garantir que os servidores tenham mínimo possível
                     de seus serviços e informações expostas. Dessa forma, portas abertas desnecessariamente ou de maneira
                      imprudente podem servir de ponto de vulnerabilidade para, por exemplo, ataques de buffer overflow.

                    Portas abertas podem revelar informações sobre o sistema ou arquitetura de rede de uma possível vítima.
                     Muitas vezes é possível descobrir, por exemplo, que o usuário vítima usa alguma versão de software que possui
                      uma vulnerabilidade já conhecida e então partir para um ataque mais avançado que utilize essa vulnerabilidade.

                   Outro problema que pode ser causado pela varredura de portas, mesmo quando as portas se encontram
                    fechadas, é o esgotamento de recursos da rede. As diversas requisições enviadas para cada porta,
                     dependendo do volume e da frequência, podem culminar em uma negação de serviço (DoS) e prejudicar
                     o desempenho da máquina do usuário vítima. Isso porque mesmo tratando as requisições enviadas pela
                      varredura como inválida elas ainda consomem processamento de entrada.

                    Abaixo podemos ver um exemplo de varredura realizado pelo Nmap, que iremos abordar mais afundo nesse trabalho.

                          NMap (Network Mapper) é uma ferramenta de código aberto utilizada para exploração de redes e análise de segurança,
                          seja de hosts únicos ou largas redes. Com ele, é possível determinar os hosts disponíveis na rede, bem como os
                          serviços que cada host dispõe, seus sistemas operacionais além dos tipos de firewall e filtro de pacotes em uso.

                          O NMap possui diversos métodos de varreduras que podem ser personalizadas, deixando-as fácil ou dificilmente detectáveis.
                          Além disso, alguns desses métodos de varredura podem simular a origem da varredura, logo,
                          falsificando o emissor do ataque, além de poder simular diversas varreduras pela rede.

Timing e Desempenho

                          O NMap utiliza de paralelismo e algoritmos que aceleram a execução das varreduras, contudo, determinadas escolhas
                          de varredura podem acarretar em uma queda de performance, que também está atrelado ao tamanho da rede.

                          Usuários experientes executam varreduras em busca apenas de informações que são de interesse, atendendo,
                          inclusive à uma restrição de tempo. Para melhorar os tempos da varredura pode-se omitir testes não críticos,
                          e otimizar os parâmetros de tempo, como "--host-timeout", que define um tempo limite para tentativa de
                          varredura em um dado host. É possível definir não só o valor, mas também a unidade (horas, minutos, segundos
                          [padrão], milissegundos) aplicando --host-timeout 900s / 900000ms / 900 / 15m.

                          Outro parâmetro que afeta diretamente o desempenho do NMap é o --min-hostgroup <number of hosts>.
                          O NMap tem a capacidade de analisar diversos hosts em paralelo, e faz isso com o auxílio deste comando.
                          O IP destino é dividido em grupos, e, então, cada grupo é analisado por vez. Em geral, grupos grandes são
                          mais eficientes. A desvantagem, é que o relatório da varredura só é exposto ao usuário após o grupo todo
                          ser analisado; assim, caso haja 50 hosts em um grupo, apenas após os 50 serem analisados, é que é possível
                          saber a situação de um dado host nesse meio.

                          Acompanhado de --max-hostgroup que determina o máximo de hosts para um grupo (O NMap utiliza esse
                          parâmetro como limite superior, enquanto o mínimo é o inferior). Contudo, há uma exceção: caso não
                          hajam hosts suficientes para o número mínimo especificado, o NMap irá utilizar valores inferiores
                          ao limite estabelecido.

                          Os comandos --min-parallelism <numprobes>; --max-parallelism <numprobes> controlam o número total
                          de análises que podem estar pendentes por um grupo de hosts. O NMap calcula automaticamente o
                          número ideal, não necessitando trabalhar com esses comandos, muito embora, para usuários avançados
                          e para determinados testes possa ser interessante. É comum utilizar esse comando para agilizar a
                          análise da rede, porém, é sempre um risco pois pode afetar a precisão dos resultados.

Interação em Tempo de Execução

                          Enquanto o NMap está sendo executado, as teclas pressionadas são capturadas e interpretadas,
                          permitindo assim a interação do usuário com o software sem abortar a operação em andamento
                          naquele instante.

                          Determinadas teclas alteram opções do scan, enquanto outras exibem informações na tela.
                          Para o segundo caso, existe uma convenção, onde letras minúsculas aumentam a taxa de
                          exibição e letras maiúsculas reduzem a taxa de exibição de novas informações.

Outros Usos do NMap

                          O NMap consegue, de forma bastante simples (do ponto de vista do usuário final) detectar
                          informações acerca de um dado dispositivo. Com o comando -O você já obtém informações do
                          sistema operacional; adicionando também o comando -v você consegue novas informações sobre
                          o sistema.

                          Diante dos dados coletados, algumas das informações fornecidas são: tipo de dispositivo,
                          distância da rede, predição de sequência TCP e geração de sequência IP ID.

Figura 5 - Terminal com relatório de uma varredura com NMap

Modus operandi

O ZMap é o varredor de porta usado para varreduras massivas em todo o espaço IPv4 da rede, almejando a uma porta comum entre todos os hosts varridos e realizando seu objetivo em altíssima velocidade. Esse varredor envia tantos pacotes quanto a NIC e a CPU do remetente aguentam. Pacotes são enviados, no ZMap, através de "raw socket" (socket que permite o envio e recebimento de pacotes sem o uso específico de algum protocolo de transporte) diretamente na camada Ethernet. Desta maneira, o ZMap impede que o Sistema Operacional realize tarefas de rotina sobre os pacotes. Como tecnicamente não é estabelecida uma conexão TCP, assim que o host fonte receber TCP SYN-ACK, a resposta de TCP RST será enviada. Na sua forma básica, esse varredor suporta TPC SYN, ICMP e UDP scans.

                         O ZMap foi feito para realizar scans de toda Internet (IPv4), mas suporta a exclusão de endereços (blacklisting) das suas varreduras para melhora de performance (endereços da IANA) e outros por pedidos de administradores dos alvos. Quanto aos hosts "disponíveis" para scan, o módulo de recebimento do ZMap precisa saber se o tráfico de pacotes recebido é proveniente de respostas ao scans, ou faz parte de algum tráfico de fundo da fonte. Para que isso ocorra, campos dos pacotes enviados são preenchidos com dados que sejam replicados nos pacotes de resposta. Para cada host varrido, ZMap computa o MAC (Media Access Control) do host de destino nos campos de Número de Sequência e porta de destino (para TCP) e Número de Sequência e identificador ICMP (para ICMP).

Limitações

                          Apesar de conseguir fazer varreduras rápidas no espaço IPv4, ZMap ainda não é rápido o bastante para fazer
                          varreduras no espaço de endereços IPv6. Além disso, o ZMap também está limitado pela velocidade da internet
                          do host remetente. Uma internet mais lenta do que a usada para testes [1] pode resultar em scans mais lentos,
                          enquanto uma internet mais rápida pode acabar sobrecarregando redes e hosts.

Usos experimentados

Medição de adesão de protocolo

                        Uma mesma porta deve ser varrida várias vezes ao longo de algum período de tempo, possibilitando, dessa forma, que seja identificado algum acréscimo no número de portas abertas. Caso isso aconteça, pode-se dizer que houve um aumento no protocolo usado naquela porta. Como por exemplo, pode-se configurar o ZMap para fazer varreduras constantes na porta 443, identificando possíveis variações no uso do protocolo HTTPS.

Scanner global de vulnerabilidades de alta velocidade

                       Uma vulnerabilidade pode ser detectada em hosts no mundo inteiro num espaço curto de tempo. Possibilitando que usuários mal intencionados façam ataques com alta possibilidade de sucesso em portas executando aplicações vulneráveis. Exemplos de vulnerabilidade são o SQL Server operando na porta 1434 (já foi sujeito a buff overflow, possibilitando a execução de código malicioso) e aparelhos UPnP.

Monitoramento da disponibilidade de serviço

                       Estudos predecessores ao ZMap já previam que o uso do scan ICMP echo request poderiam detectar interrupções em massa da Internet. Durante o Furacão Sandy, que atingiu a costa oeste dos EUA em 2013, o ZMap foi usado para varrer a porta 443 (é usada para a comunicação com websites em geral) de todo o espaço do IPv4 a cada duas horas [1]. O observado foi que, nas localidades afetadas, houve uma queda de 30% na quantidade de portas abertas.

Comunicação anônima

                       Por causa da característica de enviar incontáveis pacotes para toda a rede IPv4, torna-se impossível de se rastrear qual era o real destinatário de um envio de mensagem objetivando o anonimato.

Principais técnicas de Varredura de Portas

TCP SYN

Figura 1 - Esquema do TCP SYN

                      Esse é um dos tipos de varredura mais utilizados devido à sua velocidade de execução,
                      pois em condições favoráveis é capaz de escanear milhares de portas em pouco segundos.
                      Uma das características do TCP SYN é o fato dele ser camuflado, pois durante a sua varredura
                      ele não completa uma conexão TCP, sendo assim menos intrusivo.

                      Nesse tipo, é enviado um pacote SYN tentando abrir uma conexão. Se for recebido uma
                      resposta SYN/ACK significa que a porta está ouvindo e caso seja recebido um RST como resposta,
                      a porta não estará ouvindo. O diferencial é que quando é recebido um SYN/ACK indicando porta
                      aberta, logo é enviado um RST para cancelar a conexão, assim na maioria das vezes, não é
                      detectado nenhuma conexão.

ICMP

                      É o scan base de vários tipos de varredores de porta. É usado antes dos outros tipos de scan para detectar
                      quais hosts estão conectados à rede. Um ICMP echo request é enviado para o host alvo. Se e o alvo responder
                      com um ICMP echo reply, ele está ativo.

UDP

                      Serviços UDP são amplamente difundidos pela rede e o escaneamento das portas que registram serviços UDP
                      costumam ser mais lentos, pois ao enviar um pacote UDP, ele espera por um certo tempo uma resposta.
                      Quando a resposta não chega, supõe-se que a porta está aberta ou filtrada. Na presença de firewall, como
                      não haverá resposta, o scan pode retornar como se a porta estivesse aberta, sendo que está filtrada. Em outros
                      casos, será retornado um erro e a porta será classificada como fechada.

TCP Connect

Figura 2 - Esquema do TCP Connect

                      Esse tipo é utilizado quando não é possível usar o TCP SYN. A diferença entre esses dois é que, no TCP Connect,
                      ao receber um SYN/ACK indicando porta aberta, o sinal de RST não é enviado, mas sim um ACK, estabelecendo uma
                      conexão com a porta. O estabelecimento dessa conexão demanda mais tempo e também é facilmente percebido por qualquer
                      programa com o propósito de detectar alguma atividade estranha nas portas, pois informações do IP invasor
                      estão nessa resposta.

X-MAS Tree, TCP Null e FIN

                      Esses três tipos de varredura tem o comportamento muito parecidos. A diferença são as flags TCP dos pacotes de sondagem.
                      No X-mas é enviado um pacote com as flags FIN, PSH e URG ativados, No FIN é marcado a flag FIN (como o próprio nome já diz),
                      já o TCP Null não marca nenhuma flag no pacote.
                      Quando nenhuma resposta é recebida, a porta está aberta. Caso um RST ou ACK seja recebido, significa que a porta está fechada.

Idle

                        Tipo de varredura altamente camuflada devido à sua natureza cega. Para que funcione, são necessárias três máquinas:
                        a do invasor, a máquina zumbi e a máquina alvo.

Figura 3 - Esquema do Idle

                        A máquina zumbi é uma máquina que não está realizando absolutamente nenhuma conexão, pois será possível saber se
                        a porta da máquina alvo está aberta através do IPID na máquina zumbi. IPID é um identificador que há em todo pacote
                        e é incrementado sequencialmente.

                        O invasor manda um SYN/ACK para o zumbi que não espera conexão, então ele manda um RST e retorna um IPID
                        incrementado em um. Em seguida, a máquina invasora manda um SYN para a máquina alvo que retorna um SYN/ACK para
                        o zumbi que novamente retorna outro RST, incrementando o IPID em mais um novamente. Assim, se a máquina invasora
                        manda SYN/ACK novamente para o zumbi, ele retornará o RST com um IPID incrementado em dois, mostrando assim que a
                        porta testada da máquina alvo está aberta. Se a porta estiver fechada e ela receber um SYN, o retorno será um
                        RST direcionado ao zumbi que não terá seu IPID incrementado. Assim, se o invasor mandar um SYN/ACK novamente
                        para o zumbi, ele retornará um RST com o seu IPID incrementado apenas em um.

FTP Bounce

Figura 4 - Etapas do FTP Bounce

                      Nesse caso, o invasor solicita a um servidor FTP que um arquivo seja enviado a uma determinada
                      porta para o alvo. O alvo retorna informações para o servidor FTP e esse servidor entrega essa
                      informação para o invasor. Assim, o invasor terá informações sobre a determinada porta.

TCP ACK

                      Essa técnica não consegue identificar se uma porta está ou não aberta, mas sim se há um firewall presente e
                      quais são os conjuntos de regras que compõem esse firewall e as portas filtradas por ele.

                      Um pacote ACK é enviado, caso seja recebido um RST, então não há firewall, mas nada se pode dizer
                      sobre a disponibilidade da porta. Quando não há resposta ou quando há sinais de erro, isso significa
                      que há um firewall bloqueando esse pacote.

IP Protocol

                      Muito semelhante com o UDP, porém ele envia cabeçalhos de pacote IP. Quando recebe qualquer resposta ou nenhuma, a porta é marcada como aberta.

TCP Window

                      Muito semelhante ao ACK, porém ele diferencia a porta de aberta e fechada.
                      Ele faz isso analisando a janela TCP do pacote RST devolvido. Essas janelas possuem
                      valores positivos quando a porta do RST está aberta e zero quando está fechada.

Bibliografia

                ZMap: Fast Internet-wide Scanning and Its Security Applicatons
                Software-Defined Networking: A Comprehensive Survey
                Computer Networking: A Top-Down Approach
                The Official Nmap Project Guide to Network Discovery and Security Scanning
                Imagens

              [1] Z. Durumeric, E. Wustrow, J. Alex Halderman, Univesidade de Michigan. ZMap: Fast Internet-wide Scanning and Its Security Applicatons, Agosto 2013.

              [2] Diego Kreutz et al; Software-Defined Networking: A Comprehensive Survey.

              [3] J. Kurose, K. Ross. Computer Networking: A Top-Down Approach.

              	[4] L. Gordon; The Official Nmap Project Guide to Network Discovery and Security Scanning

[1] Ícone Firewall disponibilizado por Madebyoliver

[2] Ícone Connect disponibilizado por Freepik

[3] Figura 1. Defenses Against TCP SYN Flooding Attacks - The Internet Protocol Journal - Volume 9, Number 4

[4] Figura 2. INFOSEC INSTITUTE Port Scanning using Scapy

[4] Figura 3. Nmap: a "Hacker Tool" for Security Professionals

[5] Figura 4. Computer Security and PGP BLOG - What is an FTP Bounce Attack ?

[6] Figura 5. NMap Manual (NMap.org)

[7] Figura 6. ZMap: Fast Internet-wide Scanning and Its Security Applicatons

[8] Figura 7. ZMap: Fast Internet-wide Scanning and Its Security Applicatons

Conclusão

                      A varredura de portas, além de possibilitar a descoberta de quais serviços estão sendo executados
                      nos hosts de uma determinada rede, o que é interessante para um administrador de redes, por exemplo,
                      também detecta portas vulneráveis que podem ser usadas para ataques externos. Assim, a varredura de
                      portas é uma ferramenta poderosa tanto para usuários com boas intenções, como para usuários maliciosos.

                     Existem vários tipos de port scanners. Dentre eles, dois se destacam; ZMap e NMap. Por possuírem
                     características díspares, a análise deles, em conjunto, é muito conclusiva. Apesar de funcionarem
                     com o mesmo objetivo (varrer portas), cada varredor alcança um resultado muito diferente. O ZMap visa,
                     através da sua varredura única de porta e global do IPv4, a reunir informações sobre toda rede. Por
                     outro lado, o NMap age de maneira mais individual, dando mais atenção a cada host e fazendo uma varredura
                     total, ou parcial, de suas portas.

                      Como dito anteriormente, mesmo sendo scanners com objetivos diferentes, ZMap e NMap alcançam seus
                      resultados da mesma forma: através da transmissão de pacotes através da rede. O ZMap, em sua
                      configuração inicial, realiza varreduras TCP SYN, UDP e ICMP, enquanto o NMap possui uma gama bem
                      maior de scans, realizando esses e outros tipos, pois deve se preocupar em varrer várias portas num
                      mesmo alvo sem ser detectado.

                      Por conta dessas ameaças, o usuário precisa entender que um host está em constante risco de ataque
                      e medidas de segurança devem ser tomadas. O firewall é uma das  ferramentas de segurança indicadas
                      para esse tipo de problema, pois previne conexões indesejadas às portas abertas, criando condições
                      para que pacotes sejam entregues ao host protegido.

NMap vs ZMap

                      NMap e ZMap foram desenvolvidos para propósitos bem diferentes. Enquanto o NMap é otimizado
                      para varrer um número grande de portas em um host ou num número reduzido de hosts, o ZMap é
                      feito para varrer somente uma porta em toda a rede da Internet. A título de comparação, ao se
                      varrer a porta 443 em todo o espaço de endereços IPv4 usando o TCP SYN, é estimada uma duração de
                      1h10min para o ZMap e 63 dias para o NMap [1].

Figura 6 - Comparação em número com NMap

Sondagem otimizada

                      Enquanto o NMap adapta sua taxa de transmissão de pacotes para evitar saturar as redes da fonte
                      e do destino, ZMap assume que a rede do alvo consegue sustentar sua taxa de envio e que, por conta
                      da aleatoriedade nas escolhas dos alvos, não haverá perigo de sobrecarregar um caminho em comum.
                      Na fonte, o ZMap manda tantos pacotes quanto a Placa de Rede do host permite, "pulando" o protocolo
                      TCP/IP e gerando Ethernet frames diretamente.

Conexão sem estado

                      Enquanto NMap mantém o estado de cada conexão para ter controle de hosts varridos, retransmissões
                      e timeouts, ZMap não registra informações dos endereços varridos, ou que precisam ser varridos. Para
                      evitar repetições de endereços e manter a aleatoriedade, esse scan usa um método chamado "permutação
                      aleatória gerada por um grupo de multiplicação cíclica" [1]. Ao invés de fazer controle dos timeouts,
                      ZMap aceita respostas aos pacotes enviados por toda a duração do scan.

Retransmissão

                      Enquanto NMap transmite, por padrão, dois pacotes por porta e faz adaptações de retransmissão de
                      acordo com os timeouts causados por perda de pacotes, ZMap sempre manda uma quantidade fixa de
                      pacotes (um). Apesar de parecer que esse scan acaba ficando defasado no quesito confiabilidade, foi
                      estimado que, mesmo com o scan usando apenas um pacote e sem uso de timeouts, 98% dos alvos são varridos.

Figura 7 - Comparação de características

1.Explique em poucas palavras o que é Varredura de Portas e como funciona.

Varredura de portas é uma técnica utilizada para testar a vulnerabilidade de redes
                                         ou de sistemas, verificando se as portas conectadas estão abertas ou fechadas. Durante
                                         a varredura são enviadas mensagens a determinadas portas, e é possível fazer uma
                                         análise da resposta dessas mensagens, assim é possível determinar se a porta está
                                         ou não vulnerável.

2.Explique as três características que garantem que o ZMap é ideal para varreduras num
                              espaço muito largo de endereços.

ZMap envia pacotes tão rapidamente quanto a placa de rede do remetente
                                          aguenta pulando protocolos de transporte e enviando frames diretamente
                                          na camada Ethernet através de raw sockets. Não há armazenamento de
                                          endereços e, por consequência, nem controle de timeouts e retransmissões, ou seja,
                                          pode ser considerado sem estado. Somente um pacote é enviado para cada host alvo,
                                          sem retransmissões.

3.Explique alguns modos de utilização do ZMap.

Detecção global de vulnerabilidades: é possível descobrir o volume de hosts que
                                          executam aplicações com falhas. Comunicação anônima: através de alterações no pacote
                                          enviado durante a varredura, é possível que haja comunicação na qual não é possível
                                          saber qual host é o verdadeiro alvo. Monitoramento da disponibilidade do serviço:
                                          através do ICMP sweep, pode ser checada a disponibilidade de acesso a rede,
                                          e, por conta da alta velocidade, permitir que medidas imediatas sejam tomadas. Medição
                                          da adoção de protocolos: por haver portas associadas a certos protocolos, é possível
                                          medir sua adesão ao longo do tempo. Uma vez que o ZMap encontra essa porta aberta, é
                                          certo que tal protocolo esteja sendo utilizado.

4.Qual é a principal diferença entre o TCP SYN e o TCP Connect?

                      A principal diferença entre esses dois tipos de varredura é que ao ser recebido uma resposta
                      SYN/ACK do servidor, o TCP SYN envia um RST para que a conexão não seja completada, já o TCP
                      Connect manda um ACK que estabelece a conexão. Assim, o TCP SYN acaba sendo bem mais rápido
                      do que o TCP Connect, já que não precisa de uma conexão completa.

5.Visto que é possível interagir com o NMap ao longo de uma varredura, responda: é possível alterar configurações da varredura ao longo de sua execução?

                      Nem todas as configurações podem ser alteradas em tempo de execução, pois, caso contrário algumas informações poderiam ser perdidas. Contudo, é possível alterar o nível de verbosidade (velocidade com que as informações são exibidas no terminal durante uma varredura); ligar ou desligar o rastreamento de pacotes (packet tracing); exibir informações de ajuda; e, também alterar o nível do debug, a fim de extrair mais informações da varredura.

Para fins de aplicação dos conceitos apresentados aqui nesse trabalho, foi realizado um teste prático utilizando um ambiente virtual, emulado pelo Virtual Box, com sistema operacional Kali Linux.

	              		Máquina Virtual sendo criada

Antes de apresentar de fato os testes, abaixo estão mais alguns conceitos importantes para pleno compreendimento do procedimento realizado:

VirtualBox: Ambiente de virtualização de máquinas Open Source, sob licença GNU GPL. É compatível com Windows, Solaris, Linux e Macintosh, e suporta praticamente todos os tipos de sistemas operacionais existentes. Há uma grande comunidade focada no desenvolvimento e aprimoração do produto.

Kali Linux: É uma distribuição Linux baseada no Debian, voltado para auditoria de segurança de computadores em geral. Dispõe de inúmeros softwares para testes de segurança, dentre eles o NMap, apresentado neste trabalho.

O Teste Prático

Tendo instalado o ambiente necessário, foi realizado o seguinte teste:
Nmap –sp 192.168.0.0-100 (faz a varredura dos endereços de IP de 192-168.0.0 até 192-168.0.101)

O resultado foi o seguinte:

							Teste 1 - O tempo necessário para analisar cada IP é irrisório

O segundo teste realizado foi Nmap –sS 192.168.0.NUMERO_PORTA -O
(Realiza a varredura da porta de número escolhido utilizando a técnica Nmap. O parâmetro Ss significa que estamos usando a técnica SYN scan. O parâmetro –O, por sua vez, significa que estamos fazendo uma detecção de Sistema Operacional.)

							Teste 2 - Nesse caso vemos que todas as requisições foram filtradas, o que nos lembra da importância do Firewall.

Algumas vezes somos capazes de obter alguma informação mesmo com as requisições do Nmap sendo filtradas. Contudo, esses resultados não são confiáveis. Abaixo um exemplo.

							Teste 3 - Exemplo de testes com resultados não confiáveis.

Em determinados casos um aviso RTTVAR (Round Trip Time Variation) é exibido devido ao aumento do tempo para se varrer uma ou mais portas. Geralmente é causado por filtros que são usados pelo Firewall da "vítima".

							Teste 4 - RTTVAR sendo exibido após tentativa de varredura em uma vítima com Firewall.

Em um dos testes foi possível comprovar também o efeito de uma boa configuração de segurança contra uma varredura de portas:

							Teste 5 - Escanear a porta de um determinado endereço demorou 44 minutos, quando os demais comumente demoraram segundos.

Abaixo está o exemplo de portas que estão abertas, informadas após uma varredura do NMap:

              Mais Informações

Código do Projeto

Copyright © 2016


text:
using DeveMazeGeneratorCore.Generators;
using DeveMazeGeneratorCore.Generators.Helpers;
using DeveMazeGeneratorCore.Helpers;
using DeveMazeGeneratorCore.InnerMaps;
using System;
using Xunit;

namespace DeveMazeGeneratorCore.Tests.Generators
{
    namespace AlgorithmDivisionDynamicWithPathFacts
    {
        public class TheGenerateMethod
        {
            [Fact]
            public void GeneratesAPerfectMaze()
            {
                //Arrange
                long current = 0;
                long total = 0;
                var mazeAction = new Action<int, int, long, long>((x, y, cur, tot) =>
                {
                    current = cur;
                    total = tot;
                });

                //Act
                var maze = MazeGenerator.Generate<AlgorithmDivisionDynamicWithPath, BitArreintjeFastInnerMap, NetRandom>(128, 128, mazeAction);

                Assert.True(MazeVerifier.IsPerfectMaze(maze.InnerMap));
            }
        }
    }
}


text:
namespace Prototype.User
{
    public class UserOptions
    {

        public UserOptions()
        {
        }
    }
}


text:
- Fix attribute escaping of html_safe string
    - https://github.com/eagletmt/faml/issues/48

## 0.8.0 (2016-01-22)
- Drop Ruby 2.0.0 support
    - Ruby 2.0.0 is End of Life http://www.ruby-lang.org/en/news/2016/02/24/support-plan-of-ruby-2-0-0-and-2-1/

## 0.7.3 (2016-01-22)
- Fix build error when `$CXXFLAGS` is unavailable
- Fix StaticHashParser for parser 2.3.0.0

## 0.7.2 (2015-12-13)
- Improve AttributeBuilder performance
    - Replace std::ostringstream with std::string
- Fix compile error in some platforms

## 0.7.1 (2015-12-04)
- Fix compiler options for old compilers

## 0.7.0 (2015-11-30)
- Rewrite AttributeBuilder in C++
    - It improves performance,  memory usage, and readability

## 0.6.5 (2015-11-28)
- Delete falsey values after merging all attributes
    - `%span(foo=true){foo: false}` now renders `<span></span>`, because old attributes have priority even if the value is falsey.
    - https://github.com/eagletmt/faml/pull/43
- Fix duplicated attribute in dynamic attribute
    - `%span{foo: 1, 'foo' => 1+1}` now renders `<span foo='2'></span>` correctly
    - https://github.com/eagletmt/faml/pull/45

## 0.6.4 (2015-11-28)
- Flatten `id` and `class` attributes
    - https://github.com/eagletmt/faml/pull/41

## 0.6.3 (2015-11-22)
- Remove duplicated class in runtime attribute case
    - `%span.foo{h}` where `h = { class: 'foo bar' }` now renders `<span class='bar foo'></span>` .
    - `%span.foo{class: 'foo bar'}` renders `<span class='bar foo'></span>` since v0.2.12 .

## 0.6.2 (2015-11-22)
- Fix data-id and data-class attribute
    - https://github.com/eagletmt/faml/pull/39
    - It's regression in v0.6.1

## 0.6.1 (2015-11-21)
- Fix handling duplicated old attributes and new attributes
    - https://github.com/eagletmt/faml/pull/37
    - `%span{class: 1}(class: 2)` now renders `<span class='1 2'></span>` . `class` and `id` are correctly merged.
    - `%span{foo: 1}(foo: 2)` now renders `<span foo='1'></span>` . Old attributes has priority over new attributes.

## 0.6.0 (2015-11-21)
- Disable Faml::Helpers by default
    - https://github.com/eagletmt/faml/pull/35
    - Set `Faml::Engine.options[:extend_helpers] = true` to enable `preserve` helper method

## 0.5.1 (2015-11-18)
- Fix id ordering of object reference
    - https://github.com/eagletmt/faml/issues/33

## 0.5.0 (2015-11-17)
- Support object reference syntax
    - https://github.com/eagletmt/faml/pull/32

## 0.4.2 (2015-11-16)
- Fix CLI slow startup
    - https://github.com/eagletmt/faml/issues/21

## 0.4.1 (2015-11-16)
- Fix "end" insertion for `rescue` and `ensure` cases
    - It's regression in v0.4.0

## 0.4.0 (2015-11-15)
- Fix "end" insertion for empty else clause
    = https://github.com/eagletmt/faml/pull/31
    - It also requires haml_parser v0.2.0 or above.

## 0.3.6 (2015-11-06)
- Fix attribute escape on forward slashes
    - https://github.com/eagletmt/faml/pull/30
    - It's regression in v0.3.2

## 0.3.5 (2015-10-19)
- Fix empty class or id rendering
    - It's a regression in v0.3.4.
- Ignore falsey elements in class or id array
    - For compatibility with haml
    - `%span{class: [1, nil, false, true]}` now renders `<span class='1 true'></span>` .

## 0.3.4 (2015-10-19)
- Support array, rational and complex literal optimization
    - Now `%div{class: %w[foo bar], data: { foo: 1i, bar: 2r }}` is compiled into string literal.
- Remove `Kernel#eval` from compiler
- Improve `faml stats` subcommand
    - Show more detailed attribute information
    - Fix several bugs

## 0.3.3 (2015-10-07)
- Improve `Faml::AttributeBuilder.build` performance
    - Optimize string conversions
- Fix handling true/false/nil values in data attribute
- Add `stats` subcommand
    - Currently, it shows AST ratio and element attribute's ratio.

## 0.3.2 (2015-09-24)
- Fix illegal constant name
- Use `require_relative` if possible
    - It improves loading performance a little especially when there's long
      `$LOAD_PATH` by Bundler.
- Improve `Faml::AttributeBuilder.build` performance
    - Call `escape_html` C-API (vmg/houdini) directly.
    - Avoid `String#gsub` for performance
- Allow NUL characters in attribute keys
    - You should not include NUL characters, of course.

## 0.3.1 (2015-09-20)
- Improve `Faml::AttributeBuilder.build` performance
    - Reduce String allocations

## 0.3.0 (2015-09-13)
- Move Haml parser and AST definition to haml_parser
    - https://github.com/eagletmt/haml_parser
    - Remove `faml parse` subcommand

## 0.2.16 (2015-08-05)
- Fix incompatibility to tilt 2.x
    - https://github.com/eagletmt/faml/issues/23

## 0.2.15 (2015-06-14)
- Improve compatibility of tilt filter indentations
- Raise error when ids or classes don't have values

## 0.2.14 (2015-06-11)
- Check indent size consistency for compatibility with Haml
- Intentionally prohibit indentations with hard tabs

## 0.2.13 (2015-04-14)
- Fix attribute rendering in non-html format when the value is true
- Fix Faml::Engine constructor to allow user to set options via `Faml::Engine.options`

## 0.2.12 (2015-04-12)
- Remove duplicated class values
    - For compatibility
- Add `version` subcommand
- Add `--format` option to cli

## 0.2.11 (2015-04-07)
- Keep code newlines within multiline in HTML-style attribute list
    - https://github.com/eagletmt/faml/issues/19

## 0.2.10 (2015-04-06)
- Keep code newlines within Ruby multiline

## 0.2.9 (2015-04-04)
- Keep code newlines with multiline
    - https://github.com/eagletmt/faml/issues/18
- Disable haml multiline syntax within filter
- Fix `__LINE__` and `__FILE__` in attribute lists

## 0.2.8 (2015-04-02)
- Allow empty silent script body
    - For compatibility with haml
    - https://github.com/eagletmt/faml/issues/16
- Fix parse error at multiline in attribute list
    - https://github.com/eagletmt/faml/issues/15

## 0.2.7 (2015-03-31)
- Improve backtrace of compile time errors
- Annotate Faml::Ast with filename and line number (internal)
- Fix error with tilt 1.x.

## 0.2.6 (2015-03-31)
- Fix dependency on temple
- Improve backtrace when syntax error is raised
    - https://github.com/eagletmt/faml/issues/13

## 0.2.5 (2015-03-30)
- Fix parser when parsing attributes in `{'foo': 'bar'}` form
    - The syntax was introduced in Ruby 2.2.

## 0.2.4 (2015-03-26)
- Fix parser when parsing `>` or `<` after attribute lists
    - `%div{foo: :bar} <br>` was incorrectly parsed as `%div{foo: :bar}< br>` .

## 0.2.3 (2015-03-25)
- Always escape texts in :escape filter
    - It was not escaped when used in Rails
- `preserve` helper returns html_safe string in Rails
    - For compatibility with haml's Haml::Helpers::XssMods

## 0.2.2 (2015-03-23)
- Fix attribute rendering when the key is in `:'foo-bar'` form
- Provide `preserve` method in view contexts
    - For compatibility with haml's Haml::Helpers

## 0.2.1 (2015-03-23)
- Allow double rmnl
    - simply ignore the second rmnl

## 0.2.0 (2015-03-19)
- Rename from fast_haml to faml
- Allow .faml extension

## 0.1.10 (2015-03-19)
- Fix ruby filter to not generate newlines
- Support markdown filter

## 0.1.9 (2015-03-18)
- Refactor script parser (internal)
- Fix newline generation with filters
- Support sass, scss and coffee filter

## 0.1.8 (2015-03-17)
- Fix whitespace removal (`<` and `>`) behavior
    - Internally, new instructions `mknl` and `rmnl` are added.

## 0.1.7 (2015-03-16)
- Fix attribute rendering with falsey values
    - https://github.com/eagletmt/faml/pull/11

## 0.1.6 (2015-03-11)
- Fix render error with comment-only script
    - https://github.com/eagletmt/faml/issues/6
- Fix parsing error at multiline attributes
    - https://github.com/eagletmt/faml/issues/7

## 0.1.5 (2015-03-01)
- Fix minor newline generation bug with Haml comment

## 0.1.4 (2015-02-28)
- Fix newline generation around empty lines
    - Internal: introduce Ast::Empty and remove LineCounter

## 0.1.3 (2015-02-27)
- Fix internal compiler error when `>` is used
- Fix newline generation at Ast::Element case

## 0.1.2 (2015-02-24)
- Keep newlines for better backtrace (#4)

## 0.1.1 (2015-02-23)
- Fix attribute parsing with `%span {foo}` or `%span (foo)` cases.
- Fix comparison with statically-compilable class attributes like `%span.foo{class: bar}` .

## 0.1.0 (2015-02-23)
- Initial release


text:
package org.apache.camel.converter;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.camel.Converter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Converter
public final class TimePatternConverter {
    private static final Logger LOG = LoggerFactory.getLogger(TimePatternConverter.class);
    private static final String NUMBERS_ONLY_STRING_PATTERN = "^[-]?(\\d)+$";
    private static final String REPLACEMENT_PATTERN = "[our|inute|econd](s)?";
    private static final String HOUR_REGEX_PATTERN = "((\\d)*(\\d))[h|H]";
    private static final String MINUTES_REGEX_PATTERN = "((\\d)*(\\d))[m|M]";
    private static final String SECONDS_REGEX_PATTERN = "((\\d)*(\\d))[s|S]";

    /**
     * Utility classes should not have a public constructor.
     */
    private TimePatternConverter() {
    }

    @Converter
    public static long toMilliSeconds(String source) throws IllegalArgumentException {
        long milliseconds = 0;
        boolean foundFlag = false;
        Matcher matcher;

        matcher = createMatcher(NUMBERS_ONLY_STRING_PATTERN, source);
        if (matcher.find()) {
            // Note: This will also be used for regular numeric strings.
            //       This String -> long converter will be used for all strings.
            milliseconds = Long.valueOf(source).longValue();
        } else {
            matcher = createMatcher(REPLACEMENT_PATTERN, source);
            String replacedSource = matcher.replaceAll("");

            LOG.trace("Replaced original source {} to {}", source, replacedSource);

            matcher = createMatcher(HOUR_REGEX_PATTERN, replacedSource);
            if (matcher.find()) {
                milliseconds = milliseconds + (3600000 * Long.valueOf(matcher.group(1)).longValue());
                foundFlag = true;
            }

            matcher = createMatcher(MINUTES_REGEX_PATTERN, replacedSource);
            if (matcher.find()) {
                long minutes = Long.valueOf(matcher.group(1)).longValue();
                if ((minutes > 59) && foundFlag) {
                    throw new IllegalArgumentException("Minutes should contain a valid value between 0 and 59: " + source);
                }
                foundFlag = true;
                milliseconds = milliseconds + (60000 * minutes);
            }

            matcher = createMatcher(SECONDS_REGEX_PATTERN, replacedSource);
            if (matcher.find()) {
                long seconds = Long.valueOf(matcher.group(1)).longValue();
                if ((seconds > 59) && foundFlag) {
                    throw new IllegalArgumentException("Seconds should contain a valid value between 0 and 59: " + source);
                }
                foundFlag = true;
                milliseconds = milliseconds + (1000 * seconds);
            }

            // No pattern matched... initiating fallback check and conversion (if required).
            // The source at this point may contain illegal values or special characters
            if (!foundFlag) {
                milliseconds = Long.valueOf(source).longValue();
            }
        }

        LOG.trace("source: {} milliseconds: ", source, milliseconds);

        return milliseconds;
    }

    private static Matcher createMatcher(String regexPattern, String source) {
        Pattern pattern = Pattern.compile(regexPattern, Pattern.CASE_INSENSITIVE);
        return pattern.matcher(source);
    }
}


text:
import pymysql
import sys
pymysql.install_as_MySQLdb()


text:
package com.sheepdog.mashmesh.models;

import com.google.appengine.api.datastore.GeoPt;
import com.google.appengine.api.datastore.QueryResultIterable;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Indexed;
import com.googlecode.objectify.annotation.Unindexed;
import com.googlecode.objectify.condition.IfFalse;
import com.googlecode.objectify.condition.IfTrue;
import com.sheepdog.mashmesh.Itinerary;
import org.joda.time.DateTime;
import org.joda.time.Duration;

import javax.persistence.Id;

@Entity
public class RideRecord {
    @Id private Long id;

    @Indexed private Key<UserProfile> volunteerUserProfileKey;
    @Unindexed private GeoPt volunteerLocation;
    @Unindexed private DateTime departureTime;

    @Indexed private Key<UserProfile> patientProfileKey;
    @Unindexed private GeoPt patientLocation;
    @Unindexed private DateTime pickupTime;

    @Indexed private DateTime arrivalTime;

    @Indexed private String appointmentAddress;
    @Unindexed private GeoPt appointmentLocation;
    @Indexed private DateTime appointmentTime;

    @Unindexed private double distanceMiles;
    @Indexed(IfTrue.class) private boolean isExportable = false;

    public RideRecord() {
    }

    public RideRecord(RideRequest rideRequest, UserProfile volunteerUserProfile, Itinerary itinerary) {
        this.volunteerUserProfileKey = volunteerUserProfile.getKey();
        this.volunteerLocation = volunteerUserProfile.getLocation();
        this.departureTime = itinerary.getDepartureTime();

        this.patientProfileKey = rideRequest.getPatientUserProfileKey();
        this.patientLocation = rideRequest.getPatientLocation();
        this.pickupTime = itinerary.getPickupTime();

        this.arrivalTime = itinerary.getArrivalTime();

        this.appointmentAddress = rideRequest.getAppointmentAddress();
        this.appointmentLocation = rideRequest.getAppointmentLocation();
        this.appointmentTime = rideRequest.getAppointmentTime();

        this.distanceMiles = itinerary.getDistanceMiles();
    }

    public Long getId() {
        return id;
    }

    public Key<RideRecord> getKey() {
        return new Key<RideRecord>(RideRecord.class, id);
    }

    public Key<UserProfile> getVolunteerUserProfileKey() {
        return volunteerUserProfileKey;
    }

    public void setVolunteerUserProfileKey(Key<UserProfile> volunteerUserProfileKey) {
        this.volunteerUserProfileKey = volunteerUserProfileKey;
    }

    public GeoPt getVolunteerLocation() {
        return volunteerLocation;
    }

    public void setVolunteerLocation(GeoPt volunteerLocation) {
        this.volunteerLocation = volunteerLocation;
    }

    public DateTime getDepartureTime() {
        return departureTime;
    }

    public void setDepartureTime(DateTime departureTime) {
        this.departureTime = departureTime;
    }

    public Key<UserProfile> getPatientProfileKey() {
        return patientProfileKey;
    }

    public void setPatientProfileKey(Key<UserProfile> patientProfileKey) {
        this.patientProfileKey = patientProfileKey;
    }

    public GeoPt getPatientLocation() {
        return patientLocation;
    }

    public void setPatientLocation(GeoPt patientLocation) {
        this.patientLocation = patientLocation;
    }

    public DateTime getPickupTime() {
        return pickupTime;
    }

    public void setPickupTime(DateTime pickupTime) {
        this.pickupTime = pickupTime;
    }

    public DateTime getArrivalTime() {
        return arrivalTime;
    }

    public void setArrivalTime(DateTime arrivalTime) {
        this.arrivalTime = arrivalTime;
    }

    public String getAppointmentAddress() {
        return appointmentAddress;
    }

    public void setAppointmentAddress(String appointmentAddress) {
        this.appointmentAddress = appointmentAddress;
    }

    public GeoPt getAppointmentLocation() {
        return appointmentLocation;
    }

    public void setAppointmentLocation(GeoPt appointmentLocation) {
        this.appointmentLocation = appointmentLocation;
    }

    public DateTime getAppointmentTime() {
        return appointmentTime;
    }

    public void setAppointmentTime(DateTime appointmentTime) {
        this.appointmentTime = appointmentTime;
    }

    public double getDistanceMiles() {
        return distanceMiles;
    }

    public void setDistanceMiles(double distanceMiles) {
        this.distanceMiles = distanceMiles;
    }

    public double getTripMinutes() {
        return new Duration(departureTime, arrivalTime).getStandardMinutes();
    }

    public boolean isExportable() {
        return isExportable;
    }

    public void setExportable(boolean isExportable) {
        this.isExportable = isExportable;
    }

    public static QueryResultIterable<RideRecord> getExportableRecords() {
        return OfyService.ofy().query(RideRecord.class)
                .filter("isExportable", true)
                .fetch();
    }
}


text:
[Redmine](http://www.redmine.org) is a free and open source, web-based project management and issue tracking tool.

## TL;DR;

```bash
$ helm install stable/redmine
```

## Introduction

This chart bootstraps a [Redmine](https://github.com/bitnami/bitnami-docker-redmine) deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager.

It also packages the [Bitnami MariaDB chart](https://github.com/kubernetes/charts/tree/master/stable/mariadb) and the [PostgreSQL chart](https://github.com/kubernetes/charts/tree/master/stable/postgresql) which are required for bootstrapping a MariaDB/PostgreSQL deployment for the database requirements of the Redmine application.

Bitnami charts can be used with [Kubeapps](https://kubeapps.com/) for deployment and management of Helm Charts in clusters. This chart has been tested to work with NGINX Ingress, cert-manager, fluentd and Prometheus on top of the [BKPR](https://kubeprod.io/).

## Prerequisites

- Kubernetes 1.12+
- Helm 2.11+ or Helm 3.0-beta3+
- PV provisioner support in the underlying infrastructure
- ReadWriteMany volumes for deployment scaling

## Installing the Chart

To install the chart with the release name `my-release`:

```bash
$ helm install --name my-release stable/redmine
```

The command deploys Redmine on the Kubernetes cluster in the default configuration. The [Parameters](#parameters) section lists the parameters that can be configured during installation.

> **Tip**: List all releases using `helm list`

## Uninstalling the Chart

To uninstall/delete the `my-release` deployment:

```bash
$ helm delete my-release
```

The command removes all the Kubernetes components associated with the chart and deletes the release.

## Using PostgreSQL instead of MariaDB

This chart includes the option to use a PostgreSQL database for Redmine instead of MariaDB. To use this, MariaDB must be explicitly disabled and PostgreSQL enabled:

```
helm install --name my-release stable/redmine --set databaseType.mariadb=false,databaseType.postgresql=true
```

## Parameters

The following table lists the configurable parameters of the Redmine chart and their default values.

|            Parameter                |              Description                   |                          Default                        |
| ----------------------------------- | ------------------------------------------ | ------------------------------------------------------- |
| `global.imageRegistry`              | Global Docker image registr  y             | `nil`                                                   |
| `global.imagePullSecrets`           | Global Docker registry secret names as an array | `[]` (does not add image pull secrets to deployed pods) |
| `global.storageClass`                     | Global storage class for dynamic provisioning                                               | `nil`                                                        |
| `image.registry`                    | Redmine image registry                     | `docker.io`                                             |
| `image.repository`                  | Redmine image name                         | `bitnami/redmine`                                       |
| `image.tag`                         | Redmine image tag                          | `{TAG_NAME}`                                            |
| `image.pullPolicy`                  | Image pull policy                          | `IfNotPresent`                                          |
| `image.pullSecrets`                 | Specify docker-registry secret names as an array | `[]` (does not add image pull secrets to deployed pods)   |
| `nameOverride`                      | String to partially override redmine.fullname template with a string (will prepend the release name) | `nil`     |
| `fullnameOverride`                  | String to fully override redmine.fullname template with a string                                     | `nil`     |
| `redmineUsername`                   | User of the application                    | `user`                                                  |
| `redminePassword`                   | Application password                       | _random 10 character long alphanumeric string_          |
| `redmineEmail`                      | Admin email                                | `user@example.com`                                      |
| `redmineLanguage`                   | Redmine default data language              | `en`                                                    |
| `extraVars`                         | Environment variables, passed to redmine   | `nil`                                                   |
| `smtpHost`                          | SMTP host                                  | `nil`                                                   |
| `smtpPort`                          | SMTP port                                  | `nil`                                                   |
| `smtpUser`                          | SMTP user                                  | `nil`                                                   |
| `smtpPassword`                      | SMTP password                              | `nil`                                                   |
| `smtpTls`                           | Use TLS encryption with SMTP               | `nil`                                                   |
| `existingSecret`                    | Use existing secret for password details (`smtpPassword` and `redminePassword` will be ignored and picked up from this secret). The secret has to contain the keys `redmine-password` and `smtp-password`. | `nil`                        |
| `databaseType.postgresql`           | Select PostgreSQL as database              | `false`                                                 |
| `databaseType.mariadb`              | Select MariaDB as database                 | `true`                                                  |
| `mariadb.enabled`                   | Whether to deploy a MariaDB server to satisfy the applications database requirements     | `true`    |
| `mariadb.rootUser.password`         | MariaDB admin password                     | `nil`                                                   |
| `postgresql.enabled`                | Whether to deploy a PostgreSQL server to satisfy the applications database requirements  | `false`   |
| `postgresql.postgresqlDatabase`     | PostgreSQL database                        | `bitnami_redmine`                                       |
| `postgresql.postgresqlUsername`     | PostgreSQL user                            | `bn_redmine`                                            |
| `postgresql.postgresqlPassword`     | PostgreSQL password                        | `nil`                                                   |
| `externalDatabase.host`             | Host of the external database              | `localhost`                                             |
| `externalDatabase.name`             | Name of the external database              | `localhost`                                             |
| `externalDatabase.user`             | External db user                           | `user`                                                  |
| `externalDatabase.password`         | Password for the db user                   | `""`                                                    |
| `externalDatabase.port`             | Database port number                       | `3306`                                                  |
| `service.type`                      | Kubernetes Service type                    | `LoadBalancer`                                          |
| `service.port`                      | Service HTTP port                          | `80`                                                    |
| `service.nodePorts.http`            | Kubernetes http node port                  | `""`                                                    |
| `service.externalTrafficPolicy`     | Enable client source IP preservation       | `Cluster`                                               |
| `service.loadBalancerIP`            | LoadBalancer service IP address            | `""`                                                    |
| `service.loadBalancerSourceRanges`  | An array of load balancer sources          | `0.0.0.0/0`                                             |
| `ingress.enabled`                   | Enable or disable the ingress              | `false`                                                 |
| `ingress.hosts[0].name`             | Hostname to your Redmine installation      | `redmine.local  `                                       |
| `ingress.hosts[0].path`             | Path within the url structure              | `/`                                                     |
| `ingress.hosts[0].tls`              | Utilize TLS backend in ingress             | `false`                                                 |
| `ingress.hosts[0].certManager`      | Add annotations for cert-manager           | `false`                                                 |
| `ingress.hosts[0].tlsSecret`        | TLS Secret (certificates)                  | `redmine.local-tls-secret`                              |
| `ingress.hosts[0].annotations`      | Annotations for this host's ingress record | `[]`                                                    |
| `ingress.secrets[0].name`           | TLS Secret Name                            | `nil`                                                   |
| `ingress.secrets[0].certificate`    | TLS Secret Certificate                     | `nil`                                                   |
| `ingress.secrets[0].key`            | TLS Secret Key                             | `nil`                                                   |
| `nodeSelector`                      | Node labels for pod assignment             | `{}`                                                    |
| `tolerations`                       | List of node taints to tolerate            | `{}`                                                    |
| `affinity`                          | Map of node/pod affinities                 | `{}`                                                    |
| `podAnnotations`                    | Pod annotations                            | `{}`                                                    |
| `persistence.enabled`               | Enable persistence using PVC               | `true`                                                  |
| `persistence.existingClaim`         | The name of an existing PVC                | `nil`                                                   |
| `persistence.storageClass`          | PVC Storage Class                          | `nil` (uses alpha storage class annotation)             |
| `persistence.accessMode`            | PVC Access Mode                            | `ReadWriteOnce`                                         |
| `persistence.size`                  | PVC Storage Request                        | `8Gi`                                                   |
| `podDisruptionBudget.enabled`       | Pod Disruption Budget toggle               | `false`                                                 |
| `podDisruptionBudget.minAvailable`  | Minimum available pods                     | `nil`                                                   |
| `podDisruptionBudget.maxUnavailable`| Maximum unavailable pods                   | `nil`                                                   |
| `replicas`                          | The number of pod replicas                 | `1`                                                     |
| `resources`                         | Resources allocation (Requests and Limits) | `{}`                                                    |
| `securityContext`                   | SecurityContext                            | `{}`                                                    |
| `livenessProbe.enabled`             | would you like a livenessProbe to be enabled                                                | `true` |
| `livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated                                                    | 300    |
| `livenessProbe.periodSeconds`       | How often to perform the probe                                                              | 10     |
| `livenessProbe.timeoutSeconds`      | When the probe times out                                                                    | 5      |
| `livenessProbe.successThreshold`    | Minimum consecutive successes for the probe to be considered successful after having failed | 1      |
| `livenessProbe.failureThreshold`    | Minimum consecutive failures for the probe to be considered failed after having succeeded.  | 3      |
| `readinessProbe.enabled`            | would you like a readinessProbe to be enabled                                               | `true` |
| `readinessProbe.initialDelaySeconds`| Delay before readiness probe is initiated                                                   | 5      |
| `readinessProbe.periodSeconds`      | How often to perform the probe                                                              | 10     |
| `readinessProbe.timeoutSeconds`     | When the probe times out                                                                    | 1      |
| `readinessProbe.successThreshold`   | Minimum consecutive successes for the probe to be considered successful after having failed | 1      |
| `readinessProbe.failureThreshold`   | Minimum consecutive failures for the probe to be considered failed after having succeeded.  | 3      |

The above parameters map to the env variables defined in [bitnami/redmine](http://github.com/bitnami/bitnami-docker-redmine). For more information please refer to the [bitnami/redmine](http://github.com/bitnami/bitnami-docker-redmine) image documentation.

Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,

```bash
$ helm install --name my-release \
  --set redmineUsername=admin,redminePassword=password,mariadb.mariadbRootPassword=secretpassword \
    stable/redmine
```

The above command sets the Redmine administrator account username and password to `admin` and `password` respectively. Additionally, it sets the MariaDB `root` user password to `secretpassword`.

Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart. For example,

```bash
$ helm install --name my-release -f values.yaml stable/redmine
```

> **Tip**: You can use the default [values.yaml](values.yaml)

## Configuration and installation details

### [Rolling VS Immutable tags](https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/)

It is strongly recommended to use immutable tags in a production environment. This ensures your deployment does not change automatically if the same tag is updated with a different image.

Bitnami will release a new chart updating its containers if a new version of the main container, significant changes, or critical vulnerabilities exist.

### Replicas

Redmine writes uploaded files to a persistent volume. By default that volume cannot be shared between pods (RWO). In such a configuration the `replicas` option must be set to `1`. If the persistent volume supports more than one writer (RWX), ie NFS, `replicas` can be greater than `1`.

## Persistence

The [Bitnami Redmine](https://github.com/bitnami/bitnami-docker-redmine) image stores the Redmine data and configurations at the `/bitnami/redmine` path of the container.

Persistent Volume Claims are used to keep the data across deployments. This is known to work in GCE, AWS, and minikube. The volume is created using dynamic volume provisioning. Clusters configured with NFS mounts require manually managed volumes and claims.

See the [Parameters](#parameters) section to configure the PVC or to disable persistence.

### Existing PersistentVolumeClaims

The following example includes two PVCs, one for Redmine and another for MariaDB.

1. Create the PersistentVolume
1. Create the PersistentVolumeClaim
1. Create the directory, on a worker
1. Install the chart

```bash
$ helm install --name test --set persistence.existingClaim=PVC_REDMINE,mariadb.persistence.existingClaim=PVC_MARIADB  redmine
```

## Upgrading

### 13.0.0

Helm performs a lookup for the object based on its group (apps), version (v1), and kind (Deployment). Also known as its GroupVersionKind, or GVK. Changing the GVK is considered a compatibility breaker from Kubernetes' point of view, so you cannot "upgrade" those objects to the new GVK in-place. Earlier versions of Helm 3 did not perform the lookup correctly which has since been fixed to match the spec.

In https://github.com/helm/charts/pull/17309 the `apiVersion` of the deployment resources was updated to `apps/v1` in tune with the api's deprecated, resulting in compatibility breakage.

This major version signifies this change.

### To 5.0.0

Backwards compatibility is not guaranteed unless you modify the labels used on the chart's deployments.
Use the workaround below to upgrade from versions previous to 5.0.0. The following example assumes that the release name is redmine:

```console
$ kubectl patch deployment redmine-redmine --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]'
# If using postgresql as database
$ kubectl patch deployment redmine-postgresql --type=json -p='[{"op": "remove", "path": "/spec/selector/matchLabels/chart"}]'
# If using mariadb as database
$ kubectl delete statefulset redmine-mariadb --cascade=false
```


text:
package com.java110.job.adapt.hcIot.car;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.java110.dto.owner.OwnerCarDto;
import com.java110.dto.ownerCarAttr.OwnerCarAttrDto;
import com.java110.dto.parking.ParkingSpaceDto;
import com.java110.entity.order.Business;
import com.java110.intf.community.IParkingSpaceInnerServiceSMO;
import com.java110.intf.user.IOwnerCarAttrInnerServiceSMO;
import com.java110.intf.user.IOwnerCarInnerServiceSMO;
import com.java110.job.adapt.DatabusAdaptImpl;
import com.java110.job.adapt.hcIot.asyn.IIotSendAsyn;
import com.java110.po.car.OwnerCarPo;
import com.java110.utils.constant.StatusConstant;
import com.java110.utils.util.Assert;
import com.java110.utils.util.BeanConvertUtil;
import com.java110.utils.util.DateUtil;
import com.java110.utils.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * HC iot 车辆同步适配器
 * 接口协议地址: https://gitee.com/java110/MicroCommunityThings/blob/master/back/docs/api.md
 *
 * @desc add by 吴学文 18:58
 */
@Component(value = "modifyCarToIotAdapt")
public class ModifyCarToIotAdapt extends DatabusAdaptImpl {

    @Autowired
    private IIotSendAsyn hcOwnerCarAsynImpl;

    @Autowired
    private IOwnerCarInnerServiceSMO ownerCarInnerServiceSMOImpl;

    @Autowired
    private IOwnerCarAttrInnerServiceSMO ownerCarAttrInnerServiceSMOImpl;

    @Autowired
    private IParkingSpaceInnerServiceSMO parkingSpaceInnerServiceSMOImpl;

    /**
     * accessToken={access_token}
     * &extCommunityUuid=01000
     * &extCommunityId=1
     * &devSn=111111111
     * &name=车辆名称
     * &positionType=0
     * &positionUuid=1
     *
     * @param business   当前处理业务
     * @param businesses 所有业务信息
     */
    @Override
    public void execute(Business business, List<Business> businesses) {
        JSONObject data = business.getData();
        if (data.containsKey(OwnerCarPo.class.getSimpleName())) {
            Object bObj = data.get(OwnerCarPo.class.getSimpleName());
            JSONArray businessOwnerCars = null;
            if (bObj instanceof JSONObject) {
                businessOwnerCars = new JSONArray();
                businessOwnerCars.add(bObj);
            } else if (bObj instanceof List) {
                businessOwnerCars = JSONArray.parseArray(JSONObject.toJSONString(bObj));
            } else {
                businessOwnerCars = (JSONArray) bObj;
            }
            //JSONObject businessOwnerCar = data.getJSONObject("businessOwnerCar");
            for (int bOwnerCarIndex = 0; bOwnerCarIndex < businessOwnerCars.size(); bOwnerCarIndex++) {
                JSONObject businessOwnerCar = businessOwnerCars.getJSONObject(bOwnerCarIndex);
                doSendOwnerCar(business, businessOwnerCar);
            }
        }
    }

    private void doSendOwnerCar(Business business, JSONObject businessOwnerCar) {

        OwnerCarPo ownerCarPo = BeanConvertUtil.covertBean(businessOwnerCar, OwnerCarPo.class);

        OwnerCarDto ownerCarDto = new OwnerCarDto();
        ownerCarDto.setCarNum(ownerCarPo.getCarNum());
        ownerCarDto.setCommunityId(ownerCarPo.getCommunityId());
        List<OwnerCarDto> ownerCarDtos = ownerCarInnerServiceSMOImpl.queryOwnerCars(ownerCarDto);

        Assert.listOnlyOne(ownerCarDtos, "未找到停车场");

        //没有车位就不同步了
        if (StringUtil.isEmpty(ownerCarDtos.get(0).getPsId()) || "-1".equals(ownerCarDtos.get(0).getPsId())) {
            return;
        }

        //电动车
        //三轮车 不同步物联网系统
        if ("9904,9905".contains(ownerCarDtos.get(0).getCarType())) {
            return;
        }

        ParkingSpaceDto parkingSpaceDto = new ParkingSpaceDto();
        parkingSpaceDto.setPsId(ownerCarDtos.get(0).getPsId());
        parkingSpaceDto.setCommunityId(ownerCarDtos.get(0).getCommunityId());
        List<ParkingSpaceDto> parkingSpaceDtos = parkingSpaceInnerServiceSMOImpl.queryParkingSpaces(parkingSpaceDto);
        Assert.listOnlyOne(ownerCarDtos, "未找到车位");

        ownerCarDto = new OwnerCarDto();
        ownerCarDto.setOwnerId(ownerCarPo.getOwnerId());
        ownerCarDto.setCommunityId(ownerCarPo.getCommunityId());
        ownerCarDto.setStatusCd(StatusConstant.STATUS_CD_VALID);
        long parkingSpaceCount = ownerCarInnerServiceSMOImpl.queryOwnerParkingSpaceCount(ownerCarDto);

        //查询属性
        OwnerCarAttrDto ownerCarAttrDto = new OwnerCarAttrDto();
        ownerCarAttrDto.setCarId(ownerCarDtos.get(0).getCarId());
        ownerCarAttrDto.setCommunityId(ownerCarDtos.get(0).getCommunityId());
        List<OwnerCarAttrDto> parkingAreaAttrDtos = ownerCarAttrInnerServiceSMOImpl.queryOwnerCarAttrs(ownerCarAttrDto);

        JSONObject postParameters = new JSONObject();

        postParameters.put("carNum", ownerCarDtos.get(0).getCarNum());
        postParameters.put("startTime", DateUtil.getFormatTimeString(ownerCarDtos.get(0).getStartTime(), DateUtil.DATE_FORMATE_STRING_A));
        postParameters.put("endTime", DateUtil.getFormatTimeString(ownerCarDtos.get(0).getEndTime(), DateUtil.DATE_FORMATE_STRING_A));
        postParameters.put("extPaId", parkingSpaceDtos.get(0).getPaId());
        postParameters.put("personName", ownerCarDtos.get(0).getOwnerName());
        postParameters.put("personTel", ownerCarDtos.get(0).getLink());
        postParameters.put("personId", ownerCarDtos.get(0).getOwnerId());
        postParameters.put("extCarId", ownerCarDtos.get(0).getCarId());
        postParameters.put("parkingNum", parkingSpaceCount);
        postParameters.put("extCommunityId", ownerCarDtos.get(0).getCommunityId());
        postParameters.put("attrs", parkingAreaAttrDtos);
        hcOwnerCarAsynImpl.updateOwnerCar(postParameters);
    }
}


text:
import unittest
from unittest.mock import patch
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from datetime import datetime
from meerkat_abacus.config import config
from meerkat_abacus import model
from meerkat_abacus.pipeline_worker.process_steps import initial_visit_control
from meerkat_abacus.consumer.database_setup import create_db

class TestInitialVisitControl(unittest.TestCase):

    def setUp(self):

        create_db(config.DATABASE_URL, drop=True)
        engine = create_engine(config.DATABASE_URL)
        model.form_tables(config)
        model.Base.metadata.create_all(engine)
        self.engine = create_engine(config.DATABASE_URL)
        Session = sessionmaker(bind=self.engine)
        self.session = Session()

    def test_initial_visit_control(self):
        config.country_config["initial_visit_control"] = {
            "demo_case": {
                "identifier_key_list": ["patientid", "icd_code"],
                "visit_type_key": "intro./visit",
                "visit_date_key": "visit_date",
                "module_key": "module",
                "module_value": "ncd"

            }
        }

        ivc = initial_visit_control.InitialVisitControl(config, self.session)

        existing_data = [{
            "uuid": "a",
            "data": {
                "visit_date": "2017-01-14T05:38:33.482144",
                "icd_code": "A01",
                "patientid": "1",
                "module": "ncd",
                "intro./visit": "new",
                "id": "1"
            }
        }]
        table = model.form_tables(config)["demo_case"]
        con = self.engine.connect()
        con.execute(table.__table__.insert(), existing_data)
        con.close()

        new_data = {
            "visit_date": "2017-02-14T05:38:33.482144",
            "icd_code": "A01",
            "patientid": "1",
            "module": "ncd",
            "intro./visit": "new",
            "id": "2"
        }

        new_data_wrong_module = {
            "visit_date": "2017-02-14T05:38:33.482144",
            "icd_code": "A01",
            "patientid": "1",
            "module": "cd",
            "intro./visit": "new"
        }

        new_data_different_pid = {
            "visit_date": "2017-02-14T05:38:33.482144",
            "icd_code": "A01",
            "patientid": "2",
            "module": "ncd",
            "intro./visit": "new"
        }

        new_data_different_icd = {
            "visit_date": "2017-02-14T05:38:33.482144",
            "icd_code": "A02",
            "patientid": "1",
            "module": "ncd",
            "intro./visit": "new"
        }

        result = ivc.run("demo_register", new_data)[0]
        self.assertEqual(result["form"], "demo_register")
        self.assertEqual(result["data"], new_data)

        result = ivc.run("demo_case", new_data_wrong_module)
        self.assertEqual(len(result), 1)
        result = ivc.run("demo_case", new_data_different_pid)
        self.assertEqual(len(result), 1)
        result = ivc.run("demo_case", new_data_different_icd)
        self.assertEqual(len(result), 1)

        result = ivc.run("demo_case", new_data)
        self.assertEqual(len(result), 2)
        self.assertEqual(result[1]["data"]["intro./visit"], "return")
        self.assertEqual(result[1]["data"]["id"], "2")

        new_data = {
            "visit_date": "2017-01-01T05:38:33.482144",
            "icd_code": "A01",
            "patientid": "1",
            "module": "ncd",
            "intro./visit": "new",
            "id": "2"
        }
        result = ivc.run("demo_case", new_data)
        self.assertEqual(len(result), 2)
        self.assertEqual(result[1]["data"]["intro./visit"], "return")
        self.assertEqual(result[1]["data"]["id"], "1")