terça-feira, 31 de outubro de 2017

Nextcloud - configuração do arquivo de log

A configuração do arquivo de log no Nextcloud é feita no arquivo config.php no diretório config.

A localização do arquivo é definida pela chave logfile, mas cuidado! O valor padrão assumido é o diretório de dados do Nextcloud, definido pela chave datadirectory.

Configuração em servidor Linux

O arquivo de log deve ter código de permissão 640 e ser de propriedade do usuário www-data.

O código 640 atribui permissão de leitura e escrita (6) para o dono do arquivo, somente leitura para usuários do mesmo grupo (4) e nenhuma permissão para outros usuários (0). 

Comandos para configurar isso no GNU/Linux:

chmod 640 [arquivo de log]
chown www-data [arquivo de log]

Se após a criação do diretório, o Nextcloud reclamar que não há permissão para o arquivo de log, crie o arquivo .ocdata no diretório de dados [datadirectory].

sexta-feira, 30 de junho de 2017

Amanhecer Esmeralda

Já imaginou poder comprar uma revista em quadrinhos com uma história completa que não continue na próxima edição, ou que não faça referência a 30 outras revistas diferentes? Para leitores de quadrinhos mais infantis, como os da Turma da Mônica (original) e da Disney, essa é uma realidade quase frequente. Mas para os leitores de quadrinhos de super-heróis é um sonho distante. 

"Uma história com começo, meio e fim em uma única revista?"
Entretanto houve um tempo em que as histórias de super-heróis tinham roteiros tão descompromissados quanto os quadrinhos infantis de hoje. Era o tempo em que os editores ainda não tinham grandes preocupações com a continuidade e a cronologia dos personagens. Era o tempo em que ainda os editores ainda não haviam visto a oportunidade de obrigar os fãs a comprarem dezenas de revistas para acompanhar uma história.

Os super-heróis da DC Comics, conhecidos entre os setentistas e oitentistas como Superamigos, e pelos mais novos como Liga da Justiça, viveram um momento em que os roteiristas não precisavam de uma enciclopédia com referências cruzadas e vários álbuns para poder escrever uma história. Eles podiam ignorar fatos passados ou simplesmente incluí-los, contradizendo o que já havia sido escrito antes.

Guerra Civil: contradição de caráter

Foi assim que o Superman, que no início só torna-se herói adulto, logo depois passa a ter uma adolescência como Superboy. E logo o último sobrevivente de Krypton passa a não ser mais tão último assim, encontrando prima, cachorro, gato, cavalo e até inimigos vindos de seu planeta.


Os super-animais de estimação

 Nos anos 40 vários personagens foram criados, muitos tendo a magia como fonte de poder, como o Lanterna Verde original, Alan Scott, o Senhor Destino e o Gavião Negro original.  Nos anos 60, vários heróis foram reformulados, para terem uma origem mais científica. Assim surgiram o segundo e mais conhecido Flash, Barry Allen, o Lanterna Verde Hal Jordan, e o Gavião Negro alienígena Katar Hol.

Os Flashes da Era de Prata e de Ouro
 
Os Lanternas Verdes da Era de Prata e de Ouro


Só que havia um problema. Superman,  Batman e Mulher-Maravilha haviam lutado com os heróis dos anos 40, a Sociedade da Justiça. E agora, eles lutam com os heróis dos anos 60, a Liga da Justiça. E em vinte anos, continuavam enxutos. Como explicar isso? Aliás, como explicar que, aparentemente, a trindade da DC Comics parecia não se lembrar de ter lutado com a Sociedade da Justiça?    Em uma história do Flash Barry Allen chamada Flash of Two Worlds, publicada na revista Flash #123 de 1961, o Flash dos anos 60 se encontra com o Flash dos anos 40. Voltando no tempo? Não, porque o Flash dos anos 40 nunca existiu na história do Flash dos anos 60. Então como? O que ocorre é que ambos descobrem que existem terras paralelas. Ou seja, em uma Terra há um Flash, e ela está na década de 40, enquanto em sua cópia há um outro, só que ela está vive a década de 60. 


Superman e Superboy

Confuso? Isso piorou com o tempo. Pra tentar explicar as incoerências geradas pela falta de continuidade nas histórias foram sendo criadas várias terras paralelas: Terra 3, Terra X, Terra S, Terra Prime e milhares outras. A Terra da Liga da Justiça era a 1, enquanto a Terra da Sociedade da Justiça era a 2. De vez em quando os heróis de Terras diferentes se encontravam. Às vezes ocorriam coisas curiosas, como a morte do Batman da Terra 2 (que teve uma filha com a Mulher Gato) enquanto sua contraparte na Terra 1 permanecia viva.    Bem, um dia a DC resolveu arrumar a bagunça e tentar estabelecer uma única Terra, com uma única cronologia. Mas não dava pra simplesmente começar do zero sem dar uma satisfação para os leitores. Então surgiu uma das maiores sagas dos quadrinhos nos anos 80: a Crise nas Infinitas Terras. Essa foi uma história magistral, publicada originalmente em doze edições, que reuniu todos (TODOS) os personagens da DC Comics em um confronto com o Antimonitor, uma criatura de anti-matéria que queria destruir o multiverso (o universo com as múltiplas Terras).   

Os personagens de Crise nas Infinitas Terras, por Alex Ross
 
No final da saga, as Terras (que sobreviveram) são fundidas em uma única Terra. Alguns heróis e vilões morrem, para solucionar as incoerências, como o Robin e a Caçadora da Terra 2 e a Supermoça. Infelizmente, alguns que não precisavam morrer por causa disso também sucumbem, como o Flash.    A partir do final da Crise, toda a cronologia do universo DC foi unificada, tanto que os autores da saga, Marv Wolfman e George Pérez, escreveram "A História do Universo DC", para servir de referência para os artistas e leitores. A partir daí, os principais personagens da DC Comics tiveram suas origens recontadas. Um desses foi o Lanterna Verde da Era de Prata (anos 60). E tudo o que foi falado até agora foi apenas uma introdução para a história dos anos 80 que reconta a origem do personagem criado na década de 60.

A história do universo DC
O nome dessa história é Emerald Dawn, traduzida aqui como Amanhecer Esmeralda. O que ela tem de importante hoje? Bem, parte dela serviu para o infame primeiro filme solo do Lanterna Verde. E olha que o personagem já apareceu em péssimas produções cinematográficas antes, mas sempre como parte de uma equipe. 

Os fãs do Lanterna Verde esperaram pela chance de assistir a uma produção que honrasse toda a mitologia da Tropa dos Lanternas Verdes, conceito criado por John Broome e Gil Kane, logo na primeira história em quadrinhos de Hal Jordan, o Lanterna que foi interpretado por Ryan Reynolds que mais tarde ironizou sua atuação no filme solo de Deadpool.

O primeiro filme solo do Lanterna Verde
A Tropa dos Lanternas Verdes tem uma grande importância na Crise das Infinitas Terras. Na verdade, a origem da crise se dá no planeta Oa, que é o lar dos Guardiões do Universo, os criadores da Tropa. 

Os milhares de membros da Tropa dos Lanternas Verdes, exceto Mogo, um vírus e uma equação
Eu resolvi reescrever este artigo, criado originalmente em meu site (www.fgsl.eti.br) após assistir ao primeiro trailer do filme Lanterna Verde, que infelizmente não foi o filme que o gladiador esmeralda merecia. Mas percebi que diversas frases foram retiradas da história Amanhecer Esmeralda. Eu pessoalmente gosto muito dessa história. É bem escrita (ao contrário do filme) e bem desenhada, e ainda não tem aquela sanguinolência dos quadrinhos pós-Watchmen e Cavaleiro das Trevas. É algumas vezes poética e até inspiradora.    

Em uma das cenas do filme, Hal Jordan diz que um Lanterna Verde não pode ter medo, mas ele não é assim. Em Amanhecer Esmeralda, quando Abin Sur encontra Hal e lhe diz que ele foi escolhido para ser seu sucessor, ele responde: 

 "Você disse que um Lanterna Verde tem de ser corajoso e eu estou me borrando nas calças".    

Abin Sur responde:    

"Se o anel o escolheu, é porque você tem o potencial para superar o medo".    

Abin Sur e Hal Jordan
No infame filme, é Carol Ferris, o amor de Hal, quem lhe diz:

"Você tem a habilidade de superar o medo".  

Blake Lively como Carol Ferris

O encontro entre Hal e Abin Sur ocorre, guardadas as adaptações, de maneira bastante similar a origem recontada em 1986, embora de forma bem sucinta (e pouco épica). Aliás, no filme aparece o planeta Oa e os outros Lanternas que Hal conhece na história, que serão os mais influentes em sua carreira de super-herói: Tomar Re, Killowog e Sinestro. 

O Hal Jordan vivido por Reynolds é um sujeito pouco responsável, que de repente se vê com uma enorme responsabilidade nas mãos. 

Em Amanhecer Esmeralda, Hal é retratado como um cara que carrega uma dor pela morte do pai (que também era piloto) e vive uma fase de seguidos fracassos. A cena fo filme em que ele ejeta do caça após uma pane me deixou com a suspeita de que tentaram fazer referência ao roteiro de Amanhecer Esmeralda, mas infelizmente, descartaram essa explicação.

Eu sempre quis que Amanhecer Esmeralda virasse filme, pois é uma história fantástica, realmente poderia ser a origem definitiva (mas contaram ela de novo pra consertar a besteira de terem matado Hal Jordan). Seria fantástico assistir a um filme baseado nessa saga. Aliás, eu não entendo porque Warner Bros complica tanto suas produções, enquanto a Marvel Studios apenas segue os roteiros dos quadrinhos adaptando o que é necessário mas mantendo a essência dos personagens e a trama principal das sagas.


Amanhecer Esmeralda - versão brasileira

Uma nova produção com a Tropa dos Lanternas Verdes já foi anunciada. Quem sabe eu ainda ouça a frase de Hal, quando entrou na bateria central pela primeira vez:    "Eu anda tenho medo? Sim. Mas o medo não importa mais". 

terça-feira, 14 de fevereiro de 2017

Cloud programmers






O conceito de programador em nuvem (em inglês, cloud programmer) refere-se à utilização total da memória e das capacidades de raciocínio de um programador por meio de todos os meios de comunicações que estiverem disponíveis para abrir demandas.

O programador em nuvem pode ser acionado de qualquer lugar do mundo, a qualquer hora. Não há necessidade do programador comparecer a um local de trabalho, porque qualquer lugar onde ele possa conectar seu notebook e pegar sinal de celular é um local de trabalho. Você pode abrir demandas para o programador em nuvem remotamente, através da Internet, usando e-mail, mensageria instantânea, Skype, ou qualquer outro programa

O programador em nuvem tem elasticidade. Ele é capaz de aumentar a sua capacidade de resolver problemas de acordo com o aumento da demanda.

O programador em nuvem é multitarefa: ele trabalha em vários projetos simultaneamente. Ele usa várias janelas no seu desktop e vários monitores ao mesmo tempo. Ele codifica usando as mãos, os pés, a voz e os olhos. Enquanto ele desenvolve, atende ao telefone, participa de reuniões, faz relatórios e presta consultoria.

O programador em nuvem é 24X7. Não existe distinção entre vida profissional e vida social. Aliás, não existe vida social. Todos os recursos devem ser direcionados para o atendimento de demandas.

Você não precisa de mais programadores. Basta abrir as demandas para o programador em nuvem e ele automaticamente irá expandir o tempo para terminar dez demandas no período em que ele não conseguiria nem atender a uma.

O programador em nuvem está em algum local elevado, onde não existe necessidade de comida, lazer ou qualquer coisa mundana. Só precisa de um suprimento de oxigênio para o cérebro funcionar.

O programador em nuvem é onipresente. Envolva ele em quantos compromissos você quiser, agende quantas reuniões você precisar. Ele conseguirá tempo infinito para participar de todas as atividades dispensáveis e ainda fazer o seu trabalho.

Não fique preso à tecnologia

Filme: Homem de Ferro 2.
Cena: Tony Stark recebeu alguns objetos pessoais de seu pai Howard Stark, dados por Nick Fury, o diretor da S.H.I.E.L.D. Entre os objetos está uma fita de vídeo, com uma gravação feita em 1974.  Quando seu pai termina a mensagem para a Expo Stark, ele inicia uma outra mensagem para o filho. Nela, Howard diz que está limitado pela tecnologia de sua época, mas que Tony não, e por isso poderá realizar aquilo que ele projetou.

Howard Stark, pai de Tony Stark
Tony está sendo envenenado pelo paladium, o elemento utilizado no reator arc de seu peito, que o mantém vivo, desde que estilhaços de uma bomba se alojaram em seu peito, no Afeganistão. Ele precisa substituir o paladium por outro elemento químico, mas não existe um substituto disponível. A partir da mensagem do pai, Tony descobre que a maquete da Expo Stark é um esquema para a composição de um novo elemento químico. Ele cria um acelerador de partículas, e partir do esquema do pai, cria o novo elemento, que passa a usar em um novo reator.

Quero enfatizar a mensagem de Howard Stark, de que ele estava limitado pela tecnologia da época. Ela vale para o desenvolvimento de software. Nós também limitamos nossos projetos à tecnologia que temos disponível. Na verdade, é ainda pior que isso, ficamos presos a somente um tipo de tecnologia e passamos a criar arquitetura a partir de uma tecnologia existente, em vez de projetar a arquitetura e buscar as tecnologias que a implementam. Ficamos subjugados pelas soluções de software existentes e não inovamos por não desafiar as restrições que elas impõem.

Um arquiteto tem de ousar experimentar. Tem de ter uma atitude Oscar Niemeyer. Já pensaram se Niemeyer ficasse limitado às tecnologias de construção civil para conceber seus projetos. Ele viaja, ousa, depois verifica se é possível. Não sendo possível, pode rever o projeto. Mas ele não tem medo de ousar.

É natural que nos apeguemos ao passado, pois isso gera uma sensação de conforto. Aquilo que já vimos funcionar nos dá mais segurança. Não queremos arriscar, porque o sucesso é esquecido rapidamente, mas o fracasso é lembrado eternamente. Um sucesso não apaga um fracasso. Mas isso é decorrência do medo também, porque o fracasso sempre é uma possibilidade. Faz parte de qualquer empreendimento. Deve constar na avaliação de riscos. Mas não podemos trabalhos com risco zero. Conforme houver capacidade de recuperação, devemos tentar algo novo, algo inesperado.

Os primeiro carros eram parecidos com carruagens, porque esse era o modelo que o homem conhecia à época. Ele tentava criar uma carruagem sem cavalos. A medida que a lembrança das carruagens foi ficando mais distante, o carro começou a se tornar algo completamente diferente da carruagem. Mas mesmo assim, alguns ousavam. Veja a imagem abaixo.

Thomas Edison e um de seus carros elétricos
Um carro elétrico, produzido pelo inventor da lâmpada, Thomas Edison. Na verdade, os carros elétricos existiam desde 1830. Nos Estados Unidos houve uma época em que havia estações de recarga de baterias, no lugar de postos de gasolina. Hoje estamos discutindo a poluição causada pelos veículos a gasolina e uma das barreiras para substitui-los por carros elétricos é a falta de estações de recarga. Depois de quase um século, vemos que Thomas Edison SEMPRE ESTEVE CERTO QUANTO AO CARRO ELÉTRICO. Porque ousou experimentar.

Linux: Como saber quantos arquivos existem um um diretório

O comando abaixo: 

ls -laR | grep -v ^[.dlt] | grep -v ^$ | wc -l

lista todos os arquivos dentro do diretório atual, incluindo todos os seus subdiretórios. 

Você pode fazer o teste em um diretório com poucos arquivos e subdiretórios (que você consiga contar), só pra verificar que funciona mesmo. Eu obtive essa informação no site linuxquestions.org, por meio do usuário w1k0. Como seguramente irei esquecê-lo (tanto o comando quanto o link), registrei aqui para acesso rápido e compartilhado.

PHP e Python para Universitários - aula zero

Segundo o professor Carlos Yujiro Shigue (2009), "o Cálculo Numérico consiste na obtenção de soluções aproximadas de problemas de Álgebra Linear e Não-Linear, Estatística e Análise de Dados, Cálculo Diferencial e Integral e outros métodos matemáticos, utilizando métodos numéricos. Com a popularização de computadores de baixo custo e de alta capacidade de processamento, praticamente todas as atividades de Engenharia tem feito uso cada vez mais intensivo dos métodos e técnicas computacionais na resolução de problemas reais, para os quais as soluções manuais são impraticáveis e/ou imprecisas".

No entanto, o professor também chama a atenção para alguns problemas relacionados à aritmética computacional: 

  • "No computador, geralmente, a quantidade de operações aritméticas que se pode realizar é muito maior do que aquelas realizadas manualmente, de forma que o erro de arredondamento do dispositivo de cálculo se torna importante".
  • "No computador não temos como checar cada operação, tendo em vista a velocidade com elas são realizadas e também pela quantidade, que impossibilita a conferência dos resultados das operações aritméticas".

O professor Shigue mostra um exemplo de problema usando linguagem C:

void main() {
    int i;
    float soma = 0.;
    for(i=1;i<=10000;i++)
        soma = soma + .0001;
    printf("Soma = %10.7f", soma);

Veja, estamos somando 1 milionésimo mil vezes. Bem, 1000 X 0,001 = 1, certo? Por isso, o código acima deveria, teoricamente, imprimir o número 1, com sete zeros na parte fracionária. Mas em vez disso, segundo o professor, ele imprime 1.0000535. Eu fiz um teste criando um programa com o código acima. Compilei com o gcc 5.4.0 em uma máquina com Ubuntu 16.04. É claro que acrescentei no início a importação #include <stdio.h>, que o professor omite em sua nota de aula. Sem essa linha o código não funciona. Bem, eu obtive como resultado exatamente 1.0000535, confirmando o que o professor disse. 

Bem, meus amigos, tenho que lhes dizer que isso não acontece em PHP e Python. Fiz o código equivalente em PHP: 

<?php
$soma = 0;
for($i=1;$i<=10000;$i++)
    $soma = $soma + (float) 0.0001;
printf("Soma = %10.7f", $soma);

Executei esse código com o PHP 7.0.8 e o resultado foi este: 1.0000000

Fiz o código equivalente em Python:

soma = 0.0; 
for i in range(1,10001):
    soma = soma + 0.0001
print "Soma = %10.7f" % soma

Executei esse código com o Python 2.6.5 e o resultado foi este: 1.0000000 Ora, vejam só! PHP e Python são mais precisos que a linguagem C! 

É claro! Eles são escritos em C, mas aprimoram os recursos dela. Bem, para quem achava que PHP e Python não serviam para computação científica, se quiser envie uma mensagem perguntando como se resolvem problemas de matemática computacional com essas duas linguagens livres e podemos publicar outros artigos. Até lá.

Referência: Shigue, C. Y. Notas de Aula. Disponível em http://www.alunos.eel.usp.br/numerico/notas.html. Acesso em 13/04/2011.

Tipagem de Variáveis

Podemos considerar duas classificações para variáveis, uma baseada na manutenção dos tipos de dados existentes e outra baseada na definição de seus tipos. Para a primeira classificação, podemos distinguir dois tipos de variáveis: forte e fraca. Para a segunda temos outros dois: estática e dinâmica. A tipagem forte ocorre quando a linguagem não permite que uma variável tenha seu valor automaticamente alterado para outro tipo para possibilitar uma operação . A tipagem fraca ocorre quando a linguagem permite que uma variável tenha seu valor automaticamente alterado para outro tipo para possibilitar uma operação. A tipagem estática ocorre quando a linguagem obriga a prévia declaração de tipo de uma variável, sendo que uma vez definida, ela não pode mudar de tipo. A tipagem dinâmica ocorre quando a linguagem não obriga a prévia declaração de tipo de uma variável. O tipo é assumido na atribuição de valor à variável, que pode ser por presunção ou forçado com casting. Além disso, é possível modificar o tipo da variável atribuindo-lhe outro valor. 

Com relação a tipagem forte e fraca, podemos ver um exemplo simples utilizando os modos interativos de PHP e Python. Execute o Python no terminal: 

Python 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

Agora vamos criar duas variáveis. Uma chamada numero1 é um inteiro contendo o número 2. A segunda, chamada numero2 é uma string contendo o texto "3". Em seguida vamos tentar somar o conteúdo das duas variáveis.

>>> numero1 = 2 
>>> numero2 = "3" 
>>> print numero1 + numero2 
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str' 
>>> 

Como você pode ver, ocorreu um erro, pois as variáveis são de tipos diferentes. Ou melhor, não dá para adicionar um tipo inteiro a um string. Agora vamos fazer a mesma coisa em PHP. Primeiro, abra o modo interativo: 

 ~$ php -a 
Interactive mode enabled

php >


Agora tente somar um inteiro com um string: 

php > $numero1 = 2; 
php > $numero2 = '3';
php > print $numero1 + $numero2;

php >

Que interessante. PHP não se voltou para o programador e disse "seu burro, não posso somar um número com um texto!". A partir da operação, ele tomou uma decisão: 'é uma soma aritmética, então os dois operandos tem de ser números. como um deles é texto, vou converter seu conteúdo para inteiro, visto que não o número representado pelo texto não possui casas decimais'. Qual a conclusão que temos? 

Tanto PHP quanto Python possuem tipagem dinâmica. Não precisamos declarar as variáveis, elas assumem um tipo quando recebem um valor. Python, porém, possui tipagem forte. Você não pode executar uma operação se os tipos não forem os especificados pela operação. PHP, por outro lado, tem tipagem fraca. Ele altera o tipo de forma para se ajustar à operação. A tipagem do Python é melhor do que o PHP? Não. É apenas uma questão de abordagem. 

O Python está preocupado em impedir operações indevidas. O PHP, por outro lado, não está sendo conivente com elas, apenas oferece um mecanismo facilitador para o programador, que, se usado de forma indevida, é potencialmente perigoso. Lembre-se de que a mesma faca usada para passar manteiga no pão pode matar uma pessoa. Tudo depende de quem maneja a faca. Um último comentário. Em Python, todas as variáveis contém objetos, ou seja, todos os tipos são classes. Então ao atribuir um valor, a variável referencia um objeto que encapsula aquele valor. PHP, por sua vez, não converte valores automaticamente em objetos. 

Python é melhor do que PHP porque cria objetos pra tudo? Bem, será que você precisa de objetos pra tudo? Não existe melhor linguagem de programação. Existe aquela que é mais adequada para uma determinada aplicação. Utilizar uma única tecnologia para fazer tudo é como usar somente um tipo de material para todas as partes de uma construção. 

Referência: SEBESTA, Robert W. Conceitos de Linguagens de Programação. 5.ed. Porto Alegre. Bookman, 2003.

Segurança no PHP



O PHP é seguro? Essa não é a pergunta certa. A pergunta correta é se o programador PHP codifica de forma segura. Uma aplicação segura nada tem a ver com a linguagem de programação, mas com a arquitetura de software. 

A configuração adequada do ambiente de produção também deve ser uma preocupação. Coisas como deixar mensagens de erro serem vistos pelo usuário ocorrem em aplicações Java, Python, PHP, Ruby e são consequências de uma configuração feita sem preocupação com segurança. 

Para software, não basta performance. É preciso ter capacidade de se defender de ataques. Isso não significa que a aplicação deve ficar invulnerável. Significa que ela deve tornar a vida do atacante um inferno. Para software, não basta ser o Flash. É preciso ser o Superman. Mas saiba que sempre haverá kriptonita. 

Como parte da lenta, gradual e segura recuperação segura de conteúdo para o meu site (provocada pela migração para um novo provedor), estou novamente disponibilizando minha tradução do capítulo 10 do guia de certificação Zend. Esse capítulo é uma amostra grátis obtida na Amazon. Eu só fiz a versão em português. É uma leitura obrigatória para programadores PHP. Você pode obter a tradução aqui.

Para mais informações sobre segurança no PHP, você pode consultar a página do OWASP sobre segurança em PHP.

domingo, 5 de fevereiro de 2017

Criando e aplicando patches com GIT

Você fez um branch de um projeto com GIT e quer submeter um patch.

Veja bem, você não vai empurrar as suas alterações diretamente para o repositório remoto, você irá enviar um arquivo contendo as alterações para alguém aplicá-las, possivelmente, um revisor de código ou o git master.

Após fazer as alterações e executar o git commit, você utiliza o seguinte comando:

git format-patch master --stdout > [nome do arquivo].patch

O argumento master indica que as alterações serão aplicadas no branch master.

Vamos agora pensar do ponto de vista de quem recebe o patch. A pessoa que enviou deve ter explicado em um fórum, lista de discussão e/ou por um relato em um sistema de solicitações de mudança, o que ela fez. Mas você quer saber realmente o que será alterado, antes de aplicar o patch. Você pode ver as alterações antes de aplicá-las com o seguinte comando:

git apply --stat [nome do arquivo].patch

A próxima questão é saber se não haverá problemas em aplicar o patch. Você fazer um teste com o seguinte comando:

git apply --check fix_empty_poster.patch

Tendo certeza de que não haverá problemas, você pode aplicar o patch usando o seguinte comando:

git am --signoff < [nome do arquivo].patch

O argumento --signoff identificará que o commit resultante foi originário de um patch, incluindo o nome de usuário e e-mail que você configurou com git config.

Erros comuns no PostgreSQL II - comparação entre timestamps

Um modo de resolver problema de comparação de datas do tipo timestamp with timezone no PostgreSQL 8.4.8

Estou trabalhando na conversão de um banco MySQL para PostgreSQL. Embora exista uma SQL ANSI, cada banco tem seu dialeto particular. Além disso, há os tipos de dados específicos de cada banco.

Bem, eu tive de passar um campo de data para o tipo timestamp with timezone do PostgreSQL, versão 8.4.8. E na aplicação que usa o banco existem algumas consultas que fazem comparações de data.

Bem, havia uma comparação assim: 'expires_at' > NOW(). O campo expires_at é do tipo timestamp with timezone e a função NOW retorna o dia de hoje como timestamp with timezone também. Então, a princípio, eu estava comparando limão com limão e deveria funcionar.

Mas na execução, o PostgreSQL chiava dizendo que havia uma entrada inválida e apontava o campo expires_at. Peguei a documentação do PostgreSQL, na parte de funções de data e hora, e tentei desvendar o problema. Parecia não ter sentido, pois eu estava comparando coisas iguais.

Consultei um colega antes de submeter essa dúvida a um fórum, para verificar se não era algo trivial e evitar ser massacrado pelos especialistas, fartos de responderem questões perdidas na milésima página de resultados das buscas. Bem, não desvendamos o mistério, mas encontramos uma solução alternativa:

age(expires_at,now()) > interval '1 day'

Quer dizer, em vez de comparar as datas diretamente, eu comparei o intervalo. Mas isso não parecia elegante.

Depois de pensar bastante na mensagem de erro original, fiz um teste. O delimitador do PostgreSQL é apóstrofo. Mas em um paradoxo, coloquei o campo expires_at entre aspas. E funcionou. Por que? Não sei, só sei que foi assim.

Solução:

"expires_at" > now()

Estou contando porque se alguém passar por um problema parecido, há uma solução. Solução, não explicação.

Erros comuns no PostgreSQL - Superusuário sem senha


Você está usando uma distribuição Ubuntu. Acabou de instalar o PostgreSql, phppgadmin e pgadmin III, com o synaptic. Todo empolgado, abre o pgadmin III e tenta se conectar usando o usuário postgres. Certo, você não deveria usar o superusuário, deveria criar um usuário para o banco que vai utilizar. Mas você quer apenas saber se uma aplicação se conecta com o PostgreSQL, não quer modelar um banco de dados para uma situação real.

Bem, se receber esta mensagem:

Um erro ocorreu:

Error connecting to the server: FATAL:  autenticação do tipo password falhou para usuário "postgres"
FATAL:  autenticação do tipo password falhou para usuário "postgres"

A causa é muito simples: seu usuário postgres não tem senha. Basta criar uma senha para ele.

Como fazer isso?

Seu usuário precisa ter acesso de root, ou seja, ser administrador de sua máquina. Se isso for verdade, você pode dar o comando sudo su postgres e digitar a sua senha (a do seu usuário).

Em seguida, execute o comando psql. Ele abrirá o terminal de controle do PostgreSQL, que permite a você operar um SGBD. Nesse terminal, digite o seguinte comando:

alter role postgres encrypted password 'a senha que você quiser';

Pronto, agora você pode se conectar.

sexta-feira, 27 de janeiro de 2017

Como instalar o WordPress no CentOS 7

Instalação do Apache

sudo yum install httpd
 
Instalação do PHP e extensões requeridas pelo WordPress

sudo yum install php php-devel php-gd php-pecl-memcache php-pspell php-snmp php-xmlrpc php-xml
 
Instalação do MariaDB

sudo yum install mariadb-server mariadb
 
Início do serviço Apache

sudo apachectl start
 
Início do serviço MariaDB

sudo systemctl start mariadb.service
 
Configuração de senha do usuário administrador MariaDB

/usr/bin/mysqladmin -u root password '[SENHA]'
 
Download do pacote do WordPress

sudo yum install wget

cd /var/www/html

sudo wget https://wordpress.org/latest.tar.gz

sudo tar zxvf latest.tar.gz
 
Download e configuração do idioma Português

cd /var/www/html
sudo wget https://br.wordpress.org/latest-pt_BR.zip
sudo mkdir wpptbr
sudo unzip latest-pt_BR.zip -d wpptbr
cd /var/www/html/wordpress/wp-content
sudo mkdir languages
cd languages
sudo cp /var/www/html/wpptbr/wordpress/wp-content/languages/*.mo .
sudo cp /var/www/html/wpptbr/wordpress/wp-content/languages/*.po .
 
Instalação do WordPress
  1. Acesse o endereço http://[IP]/wordpress
  2. Preencha os dados de conexão com o banco de dados
  3. Crie o arquivo wp-config.php de acordo com o template apresentado
Habilitação do idioma Português

cd /var/www/html/wordpress

sudo vi wp-config.php
 
Adicione a seguinte linha ao arquivo citado acima:

define('WPLANG','pt_BR');

Como adicionar dependências com Maven no Eclipse

Em um projeto Maven há um arquivo chamado pom.xml.

Na aba Dependencies do editor de arquivos pom.xml é possível adicionar dependências, clicando sobre o botão Add.. do quadro Dependencies, à esquerda.

Esse botão abrirá uma janela como a exibida na figura 1:

Figura 1


No campo Group Id deve ser colocado o nome do pacote da dependência.

No campo Artifact Id deve ser colocado o nome da dependência.

No campo Version deve ser colocada a versão desejada.

Após preencher os campos e clicar sobre o botão OK, atualize o projeto selecionando o nome do projeto com o botão direito do mouse e selecionando o Maven > Update Project conforme a figura 2.

Figura 2


A dependência aparecerá no nó Maven Dependencies.

Instalando OwnCloud 9.1 no Debian 8

sudo apt-get update

sudo apt-get install apache2

cd /var/www/html

wget https://download.owncloud.org/community/owncloud-9.1.1.zip

sudo apt-get install unzip

unzip owncloud-9.1.1.zip

sudo apt-get install mysql-server

sudo apt-get install mysql-client

sudo apt-get install phpmyadmin

sudo apt-get install php5-curl


O arquivo /etc/apache2/apache2.conf  deve ter a seguinte seção alterada:

<Directory /var/www/html>Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>


A diretiva AllowOverride All deve ser configurada para All para permitir a leitura do arquivo .htaccess do Owncloud. Não basta configurar para FileInfo, pois o arquivo .htaccess possui diretivas php_value, que alterar a configuração padrão do PHP definida pelo arquivo php.ini

Como instalar o Graylog no Debian 8

Este guia foi construído a partir de uma instalação Debian 8 32 bits feita em uma máquina virtual sobre VirtualBox 5.1.6.

Atualize o repositório Debian:

sudo echo "deb http://ftp.debian.org/debian jessie-backports main" > /etc/apt/sources.list.d/backports.list
sudo apt-get update


Instale as dependências:

sudo apt-get install apt-transport-https openjdk-8-jre-headless uuid-runtime pwgen

IMPORTANTE! Deve ser instalado o Java 8. Sem ele, o servidor Graylog irá lançar uma exceção e não conseguirá levantar. Por isso verifique se o link simbólico /usr/lib/jvm/default-jre está apontando para o diretório da versão 8 do JRE. Se não estiver, reconstrua o link para apontar o Java 8. Também altere o link simbólico /etc/alternatives/java para apontar para o interpretador java (que fica na pasta jre/bin da instalação Java).

Instale o MongoDB:

sudo apt-get install mongodb-server

Instale o ElasticSearch:

wget -qO - https://packages.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
echo "deb https://packages.elastic.co/elasticsearch/2.x/debian stable main" | sudo tee -a /etc/apt/sources.list.d/elasticsearch-2.x.list
sudo apt-get update && sudo apt-get install elasticsearch


Modifique o arquivo /etc/elasticsearch/elasticsearch.yml, configurando a seguinte diretiva:

cluster.name: graylog

Configure o ElasticSearch como um serviço para que ele seja iniciado automaticamente:

sudo systemctl daemon-reload
sudo systemctl enable elasticsearch.service
sudo systemctl restart elasticsearch.service


Instale o Graylog:

wget https://packages.graylog2.org/repo/packages/graylog-2.1-repository_latest.deb
sudo dpkg -i graylog-2.1-repository_latest.deb
sudo apt-get update && sudo apt-get install graylog-server


Edite o arquivo /etc/graylog/server/server.conf e configure a diretiva password_secret com a senha gerada pelo comando abaixo:

pwgen -N 1 -s 96

Edite o arquivo /etc/graylog/server/server.conf e configure a diretiva root_password_sha2 com uma senha criptografada com o comando abaixo:

echo -n [SENHA] | sha256sum

Configure o Graylog como um serviço para que ele seja iniciado automaticamente:

sudo systemctl daemon-reload
sudo systemctl enable graylog-server.service
sudo systemctl start graylog-server.service


Tornando a interface web disponível

No arquivo /etc/graylog/server/server.conf existem duas diretivas para controlar a exposição da interface web do Graylog. De acordo com a configuração da rede, pode ser necessário substituir a configuração padrão dessas diretivas pelo IP pelo qual o servidor do Graylog será visível na rede.

  • web_listen_uri: configura o acesso à interface HTML
  • rest_listen_uri: configura o acesso à API REST

Como enviar dados do Apache para o Graylog a partir de um servidor Debian 8

Premissa: ter um servidor com Graylog instalado.

Instale o módulo de desenvolvimento do Apache e suas dependências:

sudo apt-get update
sudo install openssl
sudo apt-get install libssl-dev
sudo apt-get install libtool
sudo apt-get install apache2-dev


Baixe o código-fonte do módulo de https://github.com/mikkolehtisalo/mod_gllog.

Entre na pasta mod_gllog e compile o módulo:

sudo apxs -i -c mod_gllog.c

Habilite o módulo SSL do Apache:

sudo a2enmod ssl

Crie um arquivo para carregar o módulo gllog no Apache:

sudo vi /etc/apache2/mods-available/gllog.load

Preencha o arquivo com as seguintes instruções:

LoadFile /usr/lib/x86_64-linux-gnu/libssl.so
LoadModule gllog_module /usr/lib/apache2/modules/mod_gllog.so


Crie um link simbólico para o arquivo:

cd /etc/apache2/mods-enabled
sudo ln -s ../mods-available/gllog.load


Crie um arquivo de configuração para um virtual host que configure o módulo gllog:

cd /etc/apache2/conf-available/
sudo vi vhosts.conf


Preencha o arquivo com esta seção:

<VirtualHost *:80>
        # Master switch for the module
        GlLog On
        # The application.secret for graylog-web, stolen from application.config
        GlLogKey "xTnfNbUH7KFAM9AyPGUgD4ka17dFzpYfKmPzzFDxXmyeVpz2emInSFFmw6c1J6IoDSZishz4e7nR9O5BeJRJonNCxkx7hoTs"
        # Switch for checking validity of the signature
        GlLogSignature On

        # Use the LogFormat defined earlier
        CustomLog ${APACHE_LOG_DIR}/access.log gl_combined
</VirtualHost>


Onde o valor de GlLogKey deve ser substituído pelo valor da diretiva password_secret do arquivo /etc/graylog/server/server.conf.

Crie um link simbólico para o arquivo:

cd /etc/apache2/conf-enabled
sudo ln -s /etc/apache2/conf-available/vhosts.conf


Finalmente, é necessário reiniciar o Apache:

sudo service apache2 restart





Configuração do contexto com JBoss AS 6.x

Para configurar o contexto de uma aplicação JEE com JBoss AS 6.x, é necessário criar um arquivo jboss-web.xml na pasta WEB-INF, com o seguinte conteúdo:



<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
    <context-root>/[CONTEXTO]</context-root>
</jboss-web>


Implementação de CORS em aplicações Web para requisições HTTP POST

Por segurança, navegadores bloqueiam scripts que fazem requisições para domínios diferentes da página de onde se originam. Para permitir que um script consiga submeter uma requisição HTTP para um domínio diferente, é necessário configurar os cabeçalhos de requisição e resposta tanto no cliente quanto no servidor.

O que o cliente precisa enviar para o servidor:

Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST


O que o servidor precisa responder:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:content-type
Access-Control-Allow-Methods:POST
Access-Control-Allow-Origin: [DOMÍNIO DO REQUISITANTE - * para qualquer um]

Instalação do ChromeDriver no Ubuntu 16.04

A seguência de comandos é a seguinte:
 


sudo apt-get install unzip

wget -N http://chromedriver.storage.googleapis.com/2.20/chromedriver_linux64.zip

unzip chromedriver_linux64.zip

chmod +x chromedriver

sudo mv -f chromedriver /usr/local/share/chromedriver

sudo ln -s /usr/local/share/chromedriver /usr/local/bin/chromedriver


sudo ln -s /usr/local/share/chromedriver /usr/bin/chromedriver

Começando com Ajax

O modo de padrão para fazer Ajax é usar o objeto XMLHttpRequest, conhecido como XHR por seus amigos. Use XHR diretamente, ou por meio das bibliotecas Ajax salvadoras como Prototype ou JQuery. Como nós usamos XHR "manualmente"? Para começar, nós precisamos obter uma referência para ele:


if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr = new ActiveXObject(“Microsoft.XMLHTTP”);
}


Nós podemos então abrir uma conexão para um URL:

xhr.open(
“GET”,
“my-dynamic-content.jsp?id=”
+encodeURI(myId),
true
);


Especificar uma função de retorno de chamada para receber a resposta:

xhr.onreadystatechange = function(){
processReqChange(req);
}


e então enviar a requisição:

xhr.send(null);

O servidor pode estar ocupado, ou a rede pode estar lenta. Nós não queremos sentar por perto sem fazer nada até a resposta chegar, e por termos associado a função de retorno de chamada, nós não temos de fazer isso. Este é o guia de cinco minutos para o impaciente. Para aqueles que gostam de saber os detalhes, nós listamos os detalhes completos do objeto XHR abaixo.



Method Name Parameters and Descriptions
open(method, url, async) abre uma conexão para um URL
method = verbo HTTP (GET, POST, etc.)
url = url a ser aberto, pode incluir querystring
async = se faz requisição assíncrona
onreadystatechange associa um objeto função como retorno de chamada(similar a onclick,
onload, etc. no modelo de evento do browser)
setRequestHeader
(namevalue)
adiciona um cabeçalho à requisição HTTP
send(body) envia a requisição
body = texto a ser usado como requisição
abort() faz com que o XHR pare de esperar pela resposta
readyState nível no ciclo de vida da resposta (somente populado após send()
ser chamado)
httpStatus O código de retorno HTTP (inteiro, somente populado após
a resposta alcançar o estado carregado)
responseText corpo da resposta como um texto JavaScript (somente configurado após
a resposta alcançar o readyState interativo)
responseXML corpo da resposta como um objeto documento XML (somente
configurado após a reposta alcançar o readyState interativo)
getResponseHeader
(name)
lê um cabeçalho de resposta pelo nome
getAllResponseHeaders() Obtém um array de todos os nomes de cabeçalho de resposta



Tradução de: CRANE, Dave. Getting Started in Getting Started with Ajax. Disponível em www.dzone.com