Fonte para Linux
Para quem está procura de uma boa fonte para Linux pode dar uma experimentada na Liberation, é uma fonte que fica muito bem com um tamanho pequeno.
Para instalar no Arch Linux
pacman -S ttf-liberation
- Publicado por Rafael Souza as 00:17
- 0 comentários publicados
- Tags: linux, dica, fonte
Adicionando e removendo um usuário de um grupo no Linux
Hoje precisei definir uns grupos para um usuário e achei os comandos abaixo
Para adicionar um usuário em um grupo:
useradd -G nome_do_grupo nome_do_usuario
Você pode passar vários grupos também, basta separar a lista por vírgula:
usermod -G nome_do_grupo,nome_de_outro_grupo nome_do_usuario
Para remover um usuário de um grupo:
usermod -G nome_do_grupo nome_do_usuario
Note que a sintaxe para remover é a mesma para adicionar, porém a lista de grupos terá apenas os grupos em que você deseja manter o usuário.
Outra forma de remover todos os grupos secundários (adicionados com os comandos acima) é usando '' (vazio)
usermod -G '' nome_do_usuario
- Publicado por Rafael Souza as 13:33
- 0 comentários publicados
- Tags: linux, dica
Apache ouvindo em duas (ou mais) portas diferentes
É muito simples, basta colocar quantas diretivas Listen você precisar
Listen 80
Listen 81
Listen 82
Retirado daqui
Eu estou usando isso para poder diferenciar quando estou rodando a aplicação via Selenium ou não.
- Publicado por Rafael Souza as 19:43
- 0 comentários publicados
- Tags: php, apache, configuração
PHP, PDO e ... Sei lá o que!
Eu não ainda não consegui achar explicação para o código
Gerar a saída
C:\01projetos\teste>php pdo_fetchmode.php
setting: id with 18
setting: client_id with 48
setting: is_active with 1
setting: name with Site v1
setting: proposal with 1626
setting: description with
setting: created_at with 0000-00-00 00:00:00
setting: updated_at with
setting: created_by with
calling constructor
setting: id with 17
setting: client_id with 13
setting: is_active with 1
setting: name with Supra v1
setting: proposal with 1593
setting: description with
setting: created_at with 0000-00-00 00:00:00
setting: updated_at with
setting: created_by with
calling constructor
setting: id with 19
setting: client_id with 56
setting: is_active with 1
setting: name with Atualizacao
setting: proposal with
setting: description with
setting: created_at with 0000-00-00 00:00:00
setting: updated_at with 2008-09-15 10:02:34
setting: created_by with
calling constructor
Tenho o costume de sempre retornar objetos em resultados de banco de dados, acho mais fácil de trabalhar do que com arrays.
Ontem eu estava implementando algumas funcionalidades no ORM que fizemos aqui e me deparei com esse problema, eu precisava usar nos métodos __get e __set uma variável setada no construtor, mas começou a gerar um outro erro, causado pelo fato de que a variável não estava setada.
Procurei na documentação do PHP e só achei esse comentário, onde no final diz
Note also that the constructor is called AFTER the data is set on the object.
AFTER?! Isso vai contra toda e qualquer lógica de OOP que eu conheça!! Como que ele cria um objeto, seta todos os atributos nele e só chama o construtor depois de tudo?
Se alguém puder me explicar o motivo, razão ou circunstância, por favor, sinta-se mais do que a vontade.
- Publicado por Rafael Souza as 10:57
- 1 comentário publicado
- Tags: php, pdo, orm, behavior
Problemas com o blog
Esse final de semana tive uma batalha, batalha contra os spammers. De sexta (05/09) até hoje (07/09) eu estava tentando encontrar uma forma de bloqueá-los, acho que consegui.
Primeiro, um trecho do access_log do apache:
61.139.105.163 - - [06/Sep/2008:15:44:16 -0400] "GET http://www.esavingsnet.com/adscript_contextual.php?addcode=CD2049&bannerid=3377&optionalinfo=&deploy_id=0&landing_id=0 HTTP/1.1" 302 - "http%3A%2F%2Fwww.popflashgames.com%2Findex.html" "Mozilla/4.75 [en] (Win98; U)"
60.168.227.97 - - [06/Sep/2008:15:44:16 -0400] "GET http://ad.yieldmanager.com/pixel?id=79470&t=2 HTTP/1.0" 302 - "http://ad.103092804.com/st?ad_type=iframe&ad_size=728x90§ion=334436" "Mozilla/4.0 (compatible; MSIE 5.0; AOL 5.0; Windows 98; DigExt)"
221.224.78.254 - - [06/Sep/2008:15:44:16 -0400] "GET http://afe.specificclick.net/?l=1212015023&sz=300x250&wr=j&t=j&u=http%3A//www.autoefax.com/best_deals/bestdeals/index.php&r= HTTP/1.0" 200 4736 "http://www.autoefax.com/best_deals/bestdeals/index.php" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)"
72.52.146.79 - - [06/Sep/2008:15:44:16 -0400] "GET http://ad.yieldmanager.com/imp?Z=0x0&y=29&s=289946&_salt=3097474688&B=2&u=http%3A%2F%2Fwww.vafq.com%2Findex.html HTTP/1.1" 200 6663 "http%3A%2F%2Fwww.vafq.com%2Findex.html" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 2.0.40"
72.52.146.79 - - [06/Sep/2008:15:44:16 -0400] "GET http://ad.adserverplus.com/rw?title=&qs=iframe3%3Fks9PAJpsBABbCBIA%2Eo0FAAIAAAAAAP8AAAAHEAICAAMsnQUActkEAKJNCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgzmzM2z8AAAAAAAAAAAAA4CUp2%2DM%2EAAAAAAAAAAAAAJCf94vwPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtAncswPCCwWKJq27l%2Dt%2EpvPxUBCN1rTpsKxzOgAAAAA%3D%2C%2Chttp%3A%2F%2Fwww%2Evafq%2Ecom%2Findex%2Ehtml HTTP/1.1" 200 542 "http%3A%2F%2Fwww.vafq.com%2Findex.html" "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)"
61.139.105.166 - - [06/Sep/2008:15:44:16 -0400] "GET http://banner.addlvr.com/cpi.jsp?&pvr=84&p=112839&aid=29606&partnerMin=0&ron=on&ronMin=0&cpviw=160&cpvih=600&url=http%3A//www.freeaddictinggame.net/&context= HTTP/1.0" 302 - "http://www.freeaddictinggame.net/" "Mozilla/4.0 (compatible; MSIE 4.01; Windows 98)"
Como minha VPS tem apenas 160MB de RAM, tenho que ficar controlando o consumo de memória, e sexta veriquei que o blog estava muito lento, quase inacessível. Parei o apache, instalei o nginx e o consumo baixou.
Mas o negócio não estava 100% ainda, fui ver os logs e descobri que ele tinha todas aquelas requisições partindo do meu server, então, hoje (07/09), depois de muito pensar para tentar entender o que estava acontecendo e solucionar o problema, fiz um script para testar se era possível usar meu servidor para fazer essas requisições, e descobri que é possível :(
Qualquer pessoa pode abrir uma conexão com um servidor na porta 80 (usando socket por exemplo), e fazer uma requisição assim:
GET http://www.terra.com.br/capa/ HTTP/1.1
Fácil assim, sem dificuldade nenhuma, como é possível ver no log do apache ali em cima, todas as requisições retornam status 302, funcionando normalmente, porém quando troquei para o nginx, a coisa mudou, ficando assim:
221.224.78.234 - - [07/Sep/2008:18:48:53 -0400] 221.224.78.234 "GET http://221.224.78.234:51317/was-pv.dll HTTP/1.0" 502 529 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" "-"
221.224.78.234 - - [07/Sep/2008:18:48:53 -0400] www.google.com "GET http://www.google.com/ HTTP/1.0" 502 529 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" "-"
118.248.1.167 - - [07/Sep/2008:18:49:04 -0400] uk.vortal.com "GET http://uk.vortal.com/xml.php?Terms=Jewelry&strict=1&affiliate=lookfree&IP=69.89.12.138&rpp=10 HTTP/1.1" 502 529 "-" "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 4.0)" "-"
118.248.1.167 - - [07/Sep/2008:18:49:04 -0400] uk.vortal.com "GET http://uk.vortal.com/xml.php?Terms=Jewelry&strict=1&affiliate=woonkrant&IP=69.89.12.138&rpp=10 HTTP/1.1" 502 529 "-" "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 4.0)" "-"
222.184.123.6 - - [07/Sep/2008:18:49:04 -0400] www.linkbucks.com "GET http://www.linkbucks.com/link/f88c0a49 HTTP/1.0" 502 529 "http://www.google.com/" "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT 5.0; Alexa Toolbar)" "-"
118.248.1.167 - - [07/Sep/2008:18:49:05 -0400] uk.vortal.com "GET http://uk.vortal.com/xml.php?Terms=Jewelry&strict=1&affiliate=woonkrant&IP=69.89.12.138&rpp=10 HTTP/1.1" 502 529 "-" "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 4.0)" "-"
118.248.1.167 - - [07/Sep/2008:18:49:05 -0400] uk.vortal.com "GET http://uk.vortal.com/xml.php?Terms=Jewelry&strict=1&affiliate=lookfree&IP=69.89.12.138&rpp=10 HTTP/1.1" 502 529 "-" "Mozilla/4.0 (compatible; MSIE 4.01; Windows NT 4.0)" "-"
Status 502, Bad Gateway, o nginx trata esse tipo de requisição de um jeito diferente do apache, que na minha opnião, é muito mais inteligente.
Resolvi procurar como bloquear essas requisições mais explicitamente, deixando claro que essas requisições não eram permitidas. Então configurei o nginx para bloquear requisições que partirem de um host diferente que não o meu.
if ($host !~* ^www\.joeh\.com\.br$) {
return 403;
}
Veremos agora se terei mais problemas com os spammers do mal :)
- Publicado por Rafael Souza as 20:20
- 0 comentários publicados
- Tags: servidor, eapps, nginx, apache, configuração
Closures no PHP 5.3
Dias desses publiquei no Gist um trecho de código que faz uso de Closures do PHP 5.3, mostrando um pouco do que é possível com essa nova versão.
Esses dias estava eu mexendo com Malline e Haml quando me surgiu a idéia, poderia eu fazer algo parecido usando PHP 5.3 e Closures? A resposta é o código abaixo:
A saída será essa:
<html><head><title>Titulo da Pagina</title></head><body><p>Hello World</p><p>Outro Paragrafo<p>Um subparagrafo agora</p></p></body></html>
Isso mostra que será possível fazer um linguagem de template usando PHP puro, muito parecido com o que Malline faz para o Ruby/Rails.
- Publicado por Rafael Souza as 13:24
- 2 comentários publicados
- Tags: php, closure, código, gist, template engine
Teste com o Sinatra
Esses dias vi alguém no Twitter falando do Sinatra (não me lembro quem, e também fiquei com preguiça de procurar :P ) e resolvi testar. Fiz um script que monta um select com todos os episódios do Rails Podcast Brasil, e ainda dando a possibilidade de ver o show notes de cada um deles.
Para instalar o Sinatra basta um simples
sudo gem install sinatra
Para ver se está funcionando basta criar um arquivo muito simples como esse: (test_sinatra.rb)
require 'rubygems'
require 'sinatra'
get '/' do
"Funciona muuuito esse Sinatra"
end
Botar o webserver a rodar
ruby test_sinatra.rb
E rodar no browser
http://localhost:4567/
Se aparecer na sua tela: Funciona muito esse Sinatra então tudo funcionou como deveria :)
Agora vamos a parte mais "complicada". Vamos pegar o nosso arquivo test_sinatra.tb e colocar o código abaixo:
require 'rubygems'
require 'sinatra'
require 'hpricot'
require 'open-uri'
get '/' do
body = '<form method="post" action="/"><select name="link">'
doc = Hpricot(open("http://podcast.rubyonrails.pro.br/"))
(doc/'div.sub').each do |sub|
a = sub.next_sibling.search('a').last
if a
(sub/'h1').each do |h1|
number = h1.children[0].inner_text
puts number.to_s
if number[0] == 35 # igual a #
body << '<option value="' + a[:href] + '">Episódio ' + number + ' - ' + h1.children[2].inner_text + '</option>'
end
end
end
end
body << '</select><button>Ok</button></form>'
end
post '/' do
body = '<form method="post" action="/"><select name="link">'
doc = Hpricot(open("http://podcast.rubyonrails.pro.br/"))
(doc/'div.sub').each do |sub|
a = sub.next_sibling.search('a').last
if a
(sub/'h1').each do |h1|
number = h1.children[0].inner_text
if number[0] == 35 # igual a #
body << '<option value="' + a[:href] + '">Episódio ' + number + ' - ' + h1.children[2].inner_text + '</option>'
end
end
end
end
body << '</select><button>Ok</button></form>'
doc = Hpricot(open("http://podcast.rubyonrails.pro.br#{params[:link]}"))
body << (doc/'div.content ul').last.to_html
end
Pelo código podemos ver que temos uma chamada para get '/' e outra post '/'. Elas tratam da mesma URL, porém dependendendo do método HTTP atual ele chama um ou outro, isso é bom para separar alguma lógica que seja diferente entre eles.
Mas temos um problema, o nosso código não está DRY, tem muito código duplicado. Para resolver isso o Sinatra possui helpers também, que podem ser criados facilmente usando o método helpers, assim:
helpers do
def meu_helper
# faz alguma coisa e retorna o resultado
end
end
Depois é só usar onde quiser
get '/minha_pagina' do
meu_helper
end
Simples assim. Abaixo o script atualizado usando um helper
require 'rubygems'
require 'sinatra'
require 'hpricot'
require 'open-uri'
helpers do
def episodes_form
body = '<form method="post" action="/"><select name="link">'
doc = Hpricot(open("http://podcast.rubyonrails.pro.br/"))
(doc/'div.sub').each do |sub|
a = sub.next_sibling.search('a').last
if a
(sub/'h1').each do |h1|
number = h1.children[0].inner_text
puts number.to_s
if number[0] == 35 # igual a #
body << '<option value="' + a[:href] + '">Episódio ' + number + ' - ' + h1.children[2].inner_text + '</option>'
end
end
end
end
body << '</select><button>Ok</button></form>'
end
end
get '/' do
episodes_form
end
post '/' do
body = episodes_form
doc = Hpricot(open("http://podcast.rubyonrails.pro.br#{params[:link]}"))
body << (doc/'div.content ul').last.to_html
end
Para coisas muito simples, frameworks como o Sinatra ajudam bastante, deixando tudo mais prático, mas obviamente tudo tem um limite, não recomendaria ele para aplicações maiores, então, caso precise de algo "mais sério", vá de Rails :)
OBS: O código está usando Hpricot, um parser HTML, bem rápido e fácil de usar, caso você não tenha ele instalado basta fazer como sempre
sudo gem install hpricot
OBS 2: Eu tinha colocado os códigos no gist, mas parece que ele não permite "embedar" diferentes revisões de um mesmo código, então resolvi tirar e colocar somente o link para lá, caso alguem queira dar uma fuçada.
- Publicado por Rafael Souza as 21:28
- 0 comentários publicados
- Tags: ruby, sinatra, web, framework
Adicionando tipos de arquivo ao gedit
Estou testando agora o Malline, que está sendo assunto na lista rails-br, e precisei editar os templates no gedit, porém conforme eu ia renomeando os arquivos de .erb para .mn, que é a extensão do Malline, os arquivos iam desaparecendo do File Browser.
Para resolver isso é simples, basta adicionar o mime-type no arquivo:
/usr/share/mime/packages/rails.xml*
assim:
<mime-type type="application/x-ruby">
<comment xml:lang="en">Malline Template</comment>
<glob pattern="*.mn"/>
</mime-type>
salve o arquivo, feche o gedit e rode:
sudo update-mime-database /usr/share/mime
abra o gedit e veja que os arquivos aparecem novamente no File Browser :)
* Não sei se esse arquivo já vem com o gedit ou se alguma extensão/plugin colocou ele ali.
Paginando com acts_as_taggable
Para paginar modelos que usam acts_as_taggable é bem simples
Post.paginate_tagged_with('nome_da_tag', :page => params[:page], :per_page = 10)
Demorei um pouco até descobrir isso, então resolvi anotar aqui :)
- Publicado por Rafael Souza as 01:32
- 0 comentários publicados
- Tags: ruby, rails, paginação, dica, acts_as_taggable
Codificando e decodificando strings com HTML Entities
HTML Entities é uma gem para Ruby que serve para codificar e decodificar html entities.
gem install htmlentities
Para codificar uma string usamos
require 'rubygems'
require 'htmlentities'
he = HTMLEntities.new
encoded = he.encode("essa gem é uma mão na roda!", :named)
puts encoded # essa gem é uma mão na roda!
e para decodificar
require 'rubygems'
require 'htmlentities'
he = HTMLEntities.new
decoded = he.decode("essa gem é uma mão na roda!")
puts decoded # essa gem é uma mão na roda!
- Publicado por Rafael Souza as 00:30
- 1 comentário publicado
- Tags: ruby, html entities, encode, decode
