quinta-feira, 2 de agosto de 2012

ORACLE SQL PLUS WEB





Se vc já precisou acessar um banco de dados ORACLE com php, este exemplo será bem Util.
Como eu não tinha acesso a rede interna por estar fora da empresa e precisava testar as consultas fiz uma página onde eu pudesse colocar o SQL e retornar os resultados durante o desenvolvimento do site.
É mais fácil visualizar dados de consultas em Grades, certo ?

Porém p/ não comprometer a segurança desses dados procurei fazer essa ferramenta permitindo apenas comandos de SELECT * . 

veja os screenshots :
Consulta efetuada com sucesso

Consulta efetuada com erro



Consulta com palavra negada

Codigo da Página SQLQueryTool.php
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . '/lib/Conexao.php');
$resultMode = false;
if (isset($_POST['Query'])) {
    $resultMode = true;
    $sql = $_POST['Query'];
    preg_match('/^SELECT./i', $sql, $achei); //instrução tem q começar com SELECT
    if (!$achei) {
        die('1: ONLY SELECTS');
    }
    //bloqueia as palvras
    $pattern = array("DELETE", "UPDATE", "INSERT", "DROP",
        "ALTER", "ANALYZE", "AUDIT", "CONNECT", "CREATE",
        "GRANT", "LOCK", "NOAUDIT", "RENAME", "REVOKE", "SET CONSTRAINTS",
        "SET ROLE", "SET TRANSACTION", "TRUNCATE", "EXIT", "BEGIN",
        "EXEC", "UNION", "\"", "--", "INTERSECT", "MINUS", "TABLE", "VIEW");
    preg_match(sprintf('/%s/i', implode('|', $pattern)), $sql, $achei2);
    if ($achei2) {

        $msgErro = '2: ONLY SELECTS.<br>' .
//            preg_last_error() .
                "Palavra Negada: <b>" . $achei2[0] . "</b>";
    } else {
        $conexao = new Conexao();
        $conexao->conecta();
        $rs = $conexao->executeQuery($sql);
        // p/ pegar o nome das colunas
        $conn = oci_connect($conexao->getUser(), $conexao->getPass(), $conexao->getHost() . "/" . $conexao->getDbname(), $conexao->getEncoding());
        $columns = ociparse($conn, $sql);
        ociexecute($columns);
//    var_dump($columns);
    }
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
        <title>MCezzare Oracle SQL QUERY TOOL WEB®</title>
        <link href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css" rel="stylesheet" type="text/css"></link>
        <link href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css" rel="stylesheet" type="text/css"></link>
        <script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript">
        </script>
        <script src="http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js" type="text/javascript">
        </script>
        <script language="javascript">
            SyntaxHighlighter.config.bloggerMode = true;
            SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
            SyntaxHighlighter.all();
        </script>
        <style type="text/css">
            body {
                font-family: Verdana, Geneva, sans-serif;
                font-size: 12px;
            }
            th {
                color: #FFF;
                background-color: #003366;
                font-weight: bold;
                font-size: 12px;
            }
            tr {
                color: #000;
                font-size: 10px;
            }
        </style>
    </head>

    <body>
        <div id="form">
            <form id="form1" name="form1" method="post" action="<? echo $_SERVER['PHP_SELF']; ?>">
                <legend> SQL:  </legend>
                <textarea name="Query" id="Query" cols="45" rows="5" class="brush: sql"></textarea>

                <input type="submit" name="submit" id="submit" value="@GO" />
            </form>
        </div>
        <div id="results">
            <? if (($resultMode) && (!$achei2)) { ?>
                <b>SQL:</b><br> 
                    <pre class="brush: sql" style="font-size: 8px;"><? echo $sql; ?>
                    </pre>
                    <table border="1" cellpadding="1" cellspacing="1">

                        <? // var_dump($rs); ?>
                        <?
                        if (count($rs) > 0) {
                            $controle = 0;

                            foreach ($rs as $row) {

                                if ($controle == 0) { // apenas da 1ª vez p/ gerar o header da tabela
                                    echo "<thead>\n";
                                    echo "<tr>\n";
                                    $ncols = oci_num_fields($columns);
                                    for ($i = 1; $i <= $ncols; $i++) {
                                        echo "<th>" . oci_field_name($columns, $i) . "</th>\n";
                                    }
                                    echo "</tr>\n";
                                    echo "</thead>\n";
                                }
                                echo "<tbody>\n";
                                echo "<tr>\n";
//                    print_r($row);
                                foreach ($row as $linha) {
                                    echo "<td>" . ($linha !== null ? htmlentities($linha, ENT_QUOTES) : "&nbsp;") . "</td>\n";
                                }
                                echo "</tr>\n";
                                $controle++;
                            }
                        }
                        echo "</tbody>\n";
                        echo "</table>";
                    } else {
                        echo $msgErro;
                        ?>
                    <? } ?>

                    </div>
                    </body>
                    </html>

Codigo da lib de Conexão ao Banco
<?

error_reporting('E_ALL');
/*
  @arquivo = /lib/Conexao.php
  MVC :  controller
  objeto : Conexao
  obs : arquivo em uso na versão corrente banco ORACLE
 */

Class Conexao {

    // db data
    private $host;
    private $user;
    private $pass;
    private $dbname;
    private $encoding;
    //controle
    private $status; // 0 / 1
    private $db;  // oci_pconnect 
    private $execMode;
    private $entrada;
    private $saida = array();

    public function getHost() {
        return $this->host;
    }

    public function setHost($host) {
        $this->host = $host;
    }

    public function getUser() {
        return $this->user;
    }

    public function setUser($user) {
        $this->user = $user;
    }

    public function getPass() {
        return $this->pass;
    }

    public function setPass($pass) {
        $this->pass = $pass;
    }

    public function getDbname() {
        return $this->dbname;
    }

    public function setDbname($dbname) {
        $this->dbname = $dbname;
    }

    public function getEncoding() {
        return $this->encoding;
    }

    public function setEncoding($encoding) {
        $this->encoding = $encoding;
    }

    public function getDb() {
        return $this->db;
    }

    public function setDb($db) {
        $this->db = $db;
    }

    public function getStatus() {
        return $this->status;
    }

    public function setStatus($status) {
        $this->status = $status;
    }

    public function getEntrada() {
        return $this->entrada;
    }

    public function setEntrada($entrada) {
        $this->entrada = $entrada;
    }

    public function getSaida() {
        return $this->saida;
    }

    public function setSaida($saida) {
        $this->saida = $saida;
    }

    public function getExecMode() {
        return $this->execMode;
    }

    public function setExecMode($execMode) {
        $this->execMode = $execMode;
    }

    function Conexao() {
        $this->setStatus(0);
        $this->setHost("ENDERECO_IP");
        $this->setUser("USUARIO");
        $this->setPass("SENHA");
        $this->setDbname("NOME_BANCO");
        $this->setEncoding("WE8ISO8859P15");
//        $this->conecta(); // pode ser automatico
    }

    public function conecta() {

        $this->setDb(oci_pconnect($this->getUser(), $this->getPass(), $this->getHost() . "/" . $this->getDbname(), $this->getEncoding()));
        if (!$this->getDb()) {
            $err = oci_error();
            echo $this->mostraErro($err);
            return false;
        } else {
            $this->setStatus(1);
//            echo "Conectado no banco.<br>";
            return true;
        }
    }

    public function executeQuery($sql, $mode = OCI_FETCHSTATEMENT_BY_ROW,$safe=false) {

        if ($this->getStatus() == 1) {
            $this->entrada = ociparse($this->getDb(), $sql);

            if ($safe){
            $r = ociexecute($this->getEntrada()); //OCI_AUTO_COMMIT defaults
            }
            else {
            $r = ociexecute($this->getEntrada(),OCI_NO_AUTO_COMMIT); //OCI_NO_AUTO_COMMIT    
            }
            if (!$r) {
                $err = oci_error($this->entrada);
                echo $this->mostraErro($err);
                $this->desconecta();
            } else {
                if ($nrows = oci_fetch_all($this->getEntrada(), $this->saida, null, null, $mode)) {
                    return $this->getSaida();
                }
            }
        } else {
            echo $this->mostraErro(null, "Não estou conectado.");
        }
    }

    public function executeUpdate($sql) {

        if ($this->getStatus() == 1) {
            $this->entrada = ociparse($this->getDb(), $sql);
            $r = ociexecute($this->getEntrada());
            if (!$r) {
                $err = oci_error($this->entrada);
                echo $this->mostraErro($err);
                $this->desconecta();
            } else {
                return $r;
            }
        } else {
            echo $this->mostraErro(null, "Não estou conectado.");
        }
    }

    function desconecta() {
        $this->setStatus(0);
        if ($this->entrada) {
            oci_free_statement($this->entrada);
        }
        if ($this->db) {
            @oci_close($this->db);
        }
//        return 
    }

    function mostraErro($err, $msg = "") {
//        var_dump($err);
        $logMsg = $msg;
        if (is_array($err)) {
            foreach ($err as $key => $val) {
                $logMsg.="$key :  " . $val . "<br>\n";
            }
        }
        $retorno = "";
        $retorno.="<h1 style=\"color:#F00; font-size:19px; margin:5px 0 20px; text-shadow:1px 1px 2px #602526;\">Erro</h1>";
        $retorno.="<pre style=\"border:solid 1px #EA9C5C; padding:3px; color:#000000; background-color:#ededed \">$logMsg</pre>";
        return $retorno;
        die(); // opcional p/ travar a pagina
    }

    public function __destruct() {
        $this->desconecta();
    }

}
?>
e boas consultas.

OBS: não esqueça de restringir o acesso a essa página por autenticação ou um arquivo .htaccess
exemplo de um arquivo .htaccess que bloqueia o acesso  esse arquivo


<Files SQLQueryTool.php>
AuthType Basic
AuthName "Restricted Area" 
AuthBasicProvider file
AuthUserFile /var/www/html/delagelanden3.portari.com.br/pages/.htpasswd
Require  valid-user
</Files>

e crie o arquivo (logado no servidor) com o comando (comandos em negrito)
usuario@host:~#
htpasswd -c .htpasswd usuario

New password:
Re-type new password:x 
Adding password for user usuario

explicação:
htpasswd = programa
-c = p/ criar o arquivo .htpasswd
usuario = o login q vc quiser

veja conteudo do arquivo gerado:
usuario@host:~#cat .htpasswd 
usuario:DQK07/M2P2hkY


2 comentários:

Nada a Declarar disse...

Amigo parabens muito bom, me diz voce nao tem este codigo em jsp?

Nada a Declarar disse...

Amigo muito bom, parabens, nao abusando, mais voce nao tem este codigo em jsp? pergunto porque aqui nao posso usar o PHP