Arquivo da tag: geshi

Compras e Blog

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Hoje, no Linuxmall, comprei um pequeno livro chamado Invasão de Redes: Ataques e Defesas e foi escrito por Tiago José Pereira Nogueira. Nunca vi nada desse cara, ninguém me recomendou esse livro e não conheço ninguém que já tenha lido ou comentado alguma coisa sobre ele. É um livro que parece ser novo e me deu vontade de comprar porque sempre quis saber trabalhar com redes no C. Ele aborda tópicos interessantes, como sockets e conexões, port scanners, DDoS, entre outras coisas. Só tô explicando pra vocês não pensarem que eu comprei porque decidi virar um cracker maligno invasor de redes… :lol: Aproveitei o frete pra comprar também um novo adesivo pro laptop, um Tux grande (de 11x13cm – eu medi antes pra ver se ficava legal no laptop) que custou R$ 2,00. A compra deve chegar quinta-feira. A propósito, alguém já ouviu falar de E-Sedex? Parece ser legal… Barato e rápido! Pedi essa compra com ele pra testar. Faz tanto tempo que não compro na internet que eu fico por fora dessas novidades!

Vou aproveitar o post pra postar os códigos que eu estou fazendo pra interpretação de BBCodes e estatísticas do blog que eu, o Hélio e o Gustavo começamos a desenvolver semana passada e queremos acabar até no máximo o final de novembro (pretendemos acabar perto do dia 15/11).

Expressões Regulares

< ?php
/* A parte de regex de códigos precisa do GeSHi Highlighter. Includando-o... */
include("geshi.php");
 
/* Essa classe serve para ser usada com "extends", ela sozinha "não é nada". */
class Regex {
 
    /* Função que interpreta emoticons */
    function Emoticons() {
        $origem=Array(":)", ":(", ":D", ":P", ":O", ":S", ":lol:", ":blink:");
        $destino=Array("feliz.gif", "triste.gif", "sorriso.gif", "lingua.gif", "espantado.gif", "confuso.gif", "riso.gif", "confuso.gif");
        // EM DESENVOLVIMENTO!
    }
 
    /* Função que interpreta BBCodes...
     * Totalmente desenvolvida por mim. (nem parece de tão linda, né?) */
    function InterpretaBBCodes() {
        /* Vamos começar pelos [codes], porque só o que tá fora deles deve ser
           interpretado depois. */
 
        preg_match_all("/[code language=([a-z]+)](.*)[/code]/sU", $this->texto, $matches_com_linguagens);
        preg_match_all("/[code](.*)[/code]/sU", $this->texto, $matches_sem_linguagens);
 
        /* - A parte dos códigos é $matches_com_linguagens[$i][2] e $matches_sem_linguages[$i][1].
               - A parte que diz em que linguagem os códigos $matches_com_linguagens[$i][2] foi escrita
              é $matches_com_linguagens[$i][1].
           - Para facilitar os códigos abaixo, vou trocar matches_com_linguagens para mcl e
           matches_sem_linguagens para msl. Só não fiz em cima pra quem tá de fora entender o que
           eu tô fazendo nessa parte do código. ;)
        */
 
        $mcl=$matches_com_linguagens;
        $msl=$matches_sem_linguagens;
 
        $con=0;
        for ($i=0; $i<sizeof ($mcl[0]); $i++) {
            $g=new GeSHi($mcl[2][$i], $mcl[1][$i], "./geshi/");
            $geshi_mcl[$i]=$g->parse_code();
            $mcl_md5[$i]=md5(time()*$con++);
            $this->texto=str_replace($mcl[0][$i], $mcl_md5[$i], $this->texto);
        }
        for ($i=0; $i</sizeof><sizeof ($msl[0]); $i++) {
            /* Aqui, vocês vão perguntar: "Por que passar no GeSHi, se não sei highlightear essa linguagem?
               A resposta é que o GeSHi não só highlighta, mas formata o código de forma que ele fique
               legível (por exemplo, troca < por &lt. */
            $g=new GeSHi($msl[1][$i], "", "./geshi/");
            $geshi_msl[$i]=$g->parse_code();
            $msl_md5[$i]=md5(time()*$con++);
            $this->texto=str_replace($msl[0][$i], $msl_md5[$i], $this->texto);
        }
 
        /* Beleza, agora precisamos sempre lembrar de não highlightear o que estiver entre <pre>.
           E também não podemos deixar nada fora dos padrões XHTML Strict. */
 
        $this->texto=str_replace("&", "&amp;", $this->texto);
        $this->texto=str_replace("< ", "&lt;", $this->texto);
        $this->texto=str_replace(">", "&gt;", $this->texto);
        $this->texto=str_replace(""", "&quot;", $this->texto);
 
        // Aqui tá o meu "nl2br" semântico! =)
        $this->texto="<p>".$this->texto."</p>";
        $this->texto=preg_replace("/nnn*/", "<p>", $this->texto);
            /* </p><p></p> vazios não são semânticos. Mas estive pensando depois de fazer isso e acho que
                algumas pessoas podem querer dar um grande espaço entre os <p>, por isso estou
                pensando em fazer uma ER que a cada n a mais de dois n's adicione 10px ao
                margin-bottom do último </p><p>. O que vocês acham? */
        $this->texto=preg_replace("/n/", "<br />n", $this->texto);
        $this->texto=preg_replace("/< /p></p><p>/", "</p>n<p>", $this->texto);
 
        // Formatação básica (negrito, itálico, sublinhado, cores, cabeçalhos)
           $this->texto=preg_replace("/[b](.*)[/b]/sU", "<strong>\1</strong>", $this->texto);
        $this->texto=preg_replace("/[i](.*)[/i]/sU", "<em>\1</em>", $this->texto);
        $this->texto=preg_replace("/[u](.*)[/u]/sU", "<span style="text-decoration:underline;">\1</span>", $this->texto);
        $this->texto=preg_replace("/[color=([^]]+)](.*)[/color]/sU", "<span style="color:\1;">\2</span>", $this->texto);
        $this->texto=preg_replace("/[h([1-6])](.*)[/h\1]/sU", "<h \1>\2< /h\1>n", $this->texto);
 
        // Citações
        $this->texto=preg_replace("/[quote](.*)[/quote]/sU", "<q>\1</q>n", $this->texto);
        $this->texto=preg_replace("/[quote=([^]]+)](.*)[/quote]/sU", "<q>\2</q>n<cite>\1</cite>", $this->texto);
 
        // URLs
        $this->texto=preg_replace("/([^"/=]])(www.[^[:blank:]"< ]+)/", "\1<a href="http://\2">\2", $this->texto);
        $this->texto=preg_replace("/([^"=]])(http://[^[:blank:]"< ]+)/", "\1<a href="\2">\2", $this->texto);
 
        $this->texto=preg_replace("/[url]([^"]*)[/url]/sU", "<a href="\1">\1</a>", $this->texto);
        $this->texto=preg_replace("/[url=([^[:blank:]"]+)[[:blank:]]+title=([^]"]+)](.*)[/url]/sU", "<a href="\1" title="\2">\3</a>", $this->texto);
        $this->texto=preg_replace("/[url=([^]"]+)](.*)[/url]/sU", "<a href="\1">\2</a>", $this->texto);
 
 
        preg_match_all("/<a href="([^"]+)">/U", $this->texto, $matches);
 
        for ($i=0; $i<count ($matches[0]); $i++) {
            $parse=parse_url($matches[1][$i]);
            $dominio=$parse["host"];
            $this->texto=str_replace($matches[0][$i], "<a href="".$matches[1][$i]."" title="Link Externo: $dominio">", $this->texto);
        }
 
        // Imagens    
        $this->texto=preg_replace("/[img=([^]]+)]([^"]*)[/img]/U", "<img src="\2" alt="\1" />", $this->texto);
        $this->texto=preg_replace("/[img]([^"]*)[/img]/U", "<img src="\1" alt="Imagem: \2" />", $this->texto);
 
        // Listas
        $this->texto=preg_replace("/[list](.*)[/list]/sU", "<ul>\1</ul>", $this->texto);
        $this->texto=preg_replace("/[li](.*)[/li]/sU", "<li><p>\1</p></li>", $this->texto);
 
        // Limpando besteiras... Alguém tem alguma idéia melhor do que esse FOR feio?
        for ($count=0; $count&lt;10; $count++) {
            $this->texto=preg_replace("/<br />< /li>/", "", $this->texto);
            $this->texto=preg_replace("/<ul><br />/", "</ul><ul>", $this->texto);
            $this->texto=preg_replace("/< (/?)li><br />/", "< \1li>",  $this->texto);
            $this->texto=preg_replace("/<q><br />/", "</q><q>", $this->texto);
            $this->texto=preg_replace("/< /q><br />/", "</q>", $this->texto);
        }
 
        // Emoticons
        // $this->Emoticons();
 
        /* Lembram que o código tinha sido transformado em md5s com o tempo, pros
           bbcodes não entrarem em ação dentro deles? Então vamos transformar de
           volta em códigos agora... */
 
        for ($i=0; $i<sizeof ($mcl[0]); $i++) {
            $this->texto=str_replace($mcl_md5[$i], $geshi_mcl[$i], $this->texto);
        }
 
        for ($i=0; $i</sizeof><sizeof ($msl[0]); $i++) {
            $this->texto=str_replace($msl_md5[$i], $geshi_msl[$i], $this->texto);
        }
 
        // Limpando as besteiras que não precisam ser repetidas (e coloquei depois dos codes porque
        // aqui corrijo o negócio com os <pre>s.
        $this->texto=preg_replace("/<p>[[:blank:]]*<pre>(.*)< /pre>[[:blank:]]*< /p>/sU", "<\/pre><pre>\1<\/pre>", $this->texto);
        $this->texto=preg_replace("/</p><p>[[:blank:]]*<ul>(.*)< /ul>[[:blank:]]*< /p>/sU", "</ul><ul>\1</ul>", $this->texto);
        $this->texto=preg_replace("/</p><p>[[:blank:]]*<h (.)>(.*)< /h\1>[[:blank:]]*< /p>/sU", "</h><h \1>\2</h>", $this->texto);
        $this->texto=preg_replace("/< ([^>]+)>[[:blank:]]?< /\1>/", "", $this->texto);
 
        // E pra finalizar, o mais mala de todos... =)
        $this->texto.="n";
    }
}
?>

Tá bem comentado e queria pedir pra quem puder, dar uma testada com ele (coloquem uns BBCodes errados e coisas que vocês acham que eu não iria prever). Aí embaixo então a parte das estatísticas, para as quais estou usando um pouco do código do Shortstat. Ela tá assim por enquanto:

Estatísticas

< ?php
class Estatisticas {
    var $ip, $pais, $codigopais, $referer, $url, $dominio, $res, $useragent, $navegador, $versaonavegador, $plataforma, $unixtime;
 
    /* Função que descobre o IP real do visitante
     * Copiada de: www.foo.com.br
     */
    function IpReal() {
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "desconhecido")) {
            $ip=getenv("HTTP_CLIENT_IP");
        } else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "desconhecido")) {
            $ip=getenv("HTTP_X_FORWARDED_FOR");
        } else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "desconhecido")) {
            $ip=getenv("REMOTE_ADDR");
        } else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "desconhecido")) {
            $ip=$_SERVER['REMOTE_ADDR'];
        } else {
            $ip="desconhecido";
        }
 
        return $ip;
    }
 
    /* Função para descobrir navegador, sistema operacional, etc. com base no User Agent.
     * "SI_parseUserAgent()" do Shortstat, levemente modificada.
     */
    function ParseUserAgent($ua) {
        $plataforma="Desconhecida";
        $navegador="Desconhecido";
        $versao="";
 
        if (eregi("Win", $ua)) {
            $plataforma="Windows";
        } else if (eregi("Mac", $ua)) {
            $plataforma="Macintosh";
        } else if (eregi("Linux", $ua)) {
            $plataforma="Linux";
        } else if (eregi("W3C", $ua)) {
            $plataforma="W3C Validator";
            $navegador="W3C Validator";
            $versao="-";
        } else if (eregi("Googlebot", $ua)) {
            $plataforma="Googlebot";
        } else if (eregi("msnbot", $ua)) {
            $plataforma="MSNBot";
        } else if (eregi("Cynthia", $ua)) {
            $plataforma="Cynthia";
            $navegador="Cynthia";
            $versao="0";
        }
 
        if (eregi("Mozilla/4", $ua)&&!eregi("compatible", $ua)) {
            $navegador="Netscape";
            eregi('Mozilla/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Mozilla/5", $ua)||eregi("Gecko", $ua)) {
            $navegador="Mozilla";
            eregi('rv(:| )([[:digit:].]+)', $ua, $b);
            $versao=$b[2];
        }
        if (eregi("Safari", $ua)) {
            $navegador="Safari";
            $plataforma="Macintosh";
            eregi('Safari/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("iCab", $ua)) {
            $navegador="iCab";
            eregi('iCab/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Firefox", $ua)) {
            $navegador="Firefox";
            eregi('Firefox/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Firebird", $ua)) {
            $navegador="Firebird";
            eregi('Firebird/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Phoenix", $ua)) {
            $navegador="Phoenix";
            eregi('Phoenix/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Camino", $ua)) {
            $navegador="Camino";
            eregi('Camino/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Chimera", $ua)) {
            $navegador="Chimera";
            eregi('Chimera/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Netscape", $ua)) {
            $navegador="Netscape";
            eregi('Netscape[0-9]?/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("MSIE", $ua)) {
            $navegador="Internet Explorer";
            eregi('MSIE ([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Opera", $ua)) {
            $navegador="Opera";
            eregi('Opera( |/)([[:digit:].]+)', $ua, $b);
            $versao=$b[2];
        }
        if (eregi("OmniWeb", $ua)) {
            $navegador="OmniWeb";
            eregi('OmniWeb/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Konqueror", $ua)) {
            $navegador="Konqueror";
            $plataforma="Linux";
            eregi('Konqueror/([[:digit:].]+', $ua, $b);
            $versao=$b[1];
        }
        if (eregi('Crawl', $ua) || eregi('bot', $ua) || eregi('slurp', $ua) || eregi('spider', $ua)) {
            $navegador="Crawler/Search Engine";
            $versao="-";
        }
        if (eregi('Lynx', $ua)) {
            $navegador="Lynx";
            eregi('Lynx/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
            $plataforma="Linux";
        }
        if (eregi('Links', $ua)) {
            $navegador="Links";
            eregi('(([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
 
        $array=Array($navegador, $versao, $plataforma);
        return $array;
    }
 
    /* Função para determinar o país do visitante
     * "SI_determineCountry()", do Shortstat, bem modificada por mim.
     */
    function DeterminarPais($ip) {
        global $BASE;
        $ip=sprintf("%u", ip2long($ip));
 
        $db=new $BASE['TYPE'];
        $db->Conecta();
        $db->Query("SELECT nome, codigo FROM ".$BASE['TABELA_PAISES']." WHERE ip_from < = $ip AND ip_to >= $ip");
        $array=$db->FetchRow();
 
        $db->Desconecta();
 
        /* Agora um monte de linhas por causa da incompetência do PHP 5.0.5... Hehehe... */
        $tmp1=preg_replace("/([A-ZxC0-xDF])/e", "chr(ord('\1')+32)", $array[0]);
        $tmp2=ucwords($tmp1);
        $array[0]=trim($tmp2);
 
        return $array;
    }
 
    /* Função para "increase stats"
     * O arquivo "inc.stats.php" do Shortstat, bem modificado por mim.
     */
    function IncStats() {
        global $BASE;
        $this->ip=$this->IpReal();
        list($this->pais, $this->codigopais)=$this->DeterminarPais($this->ip);
        $this->referer=$_SERVER["HTTP_REFERER"];
        $this->url=parse_url($this->referer);
        $this->dominio=eregi_replace("^www", "", $this->url["host"]);
        $this->resource=$_SERVER["REQUEST_URI"];
        $this->useragent=$_SERVER["HTTP_USER_AGENT"];
        list($this->navegador, $this->versaonavegador, $this->plataforma)=ParseUserAgent($this->useragent);
        $this->unixtime=time();
 
        $db=new $BASE['TYPE'];
        $db->Conecta();
        $db->Query("INSERT INTO ".$BASE['TABELA_ESTATISTICAS']." (ip, pais, codigopais, dominio,
        referer, resource, useragent, plataforma, navegador, versao, unixtime) VALUES ('{$this->ip}',
        '{$this->pais}', '{$this->codigopais}', '{$this->dominio}', '{$this->referer}', '{$this->resource}',
        '{$this->useragent}', '{$this->plataforma}', '{$this->navegador}', '{$this->versaonavegador}',
        '{$this->unixtime}')");
        $db->Desconecta();
    }
}
?>

Bom… Esses dois códigos estão em desenvolvimento ainda, mas acho que com o tempo vão melhorando. Tem umas coisas na parte de Regex que eu queria tornar mais simples mas ainda não descobri como! :blink: Quem quiser sugerir, sinta-se a vontade.

Troca de Servidor e “Semantic Blog”

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Em primeiro lugar, quero pedir desculpa a quem entrou no meu site hoje e teve algum problema. Acontece que acabo de trocar de servidor. Depois de ver uma propaganda no Tableless.com.br, acessei o site da NerdHost e gostei dos preços e da qualidade do serviço. Por causa desses fatos e por eles estarem incentivando os padrões web (dão um mês gratuito pra quem desenvolve em tableless), fechei o contrato com eles no dia em que eu vi. :) Esse servidor usa CPanel, que eu acho bem melhor que o painel de controle da Metaweb e tem vantagens como um SSH que funciona SCP (acreditem! O da Metaweb não funcionava!), subdomínios ilimitados, PHP 5, MySql 4… Foi uma excelente troca! :D E ainda peguei o plano mais barato (limpei o servidor, consegui deixá-lo com 60mb), que custa R$ 5,67 (incrível a precisão do valor… hehehe).

Em segundo lugar: Eu, o Hélio e o Gustavo começamos a desenvolver um sistema de blog, em cima de classes, bastante parecido com o meu mas mais simples que tem como objetivo ser leve e possuir apenas o que é necessário. Ele já vai vir com um Shortstat bem modificado pra dar várias estatísticas (tipo, comentários por visitante, umas paradas assim) e com o GeSHi Highlighter. Os posts vão usar BBCodes e o blog vai ser baseado em templates. Resolvemos dar o nome “Semantic Blog”. Gostou? Deixe um comentário pra eu saber! Não gostou? Deixe um comentário também! :p Hehehe… Se você tiver qualquer sugestão de recurso interessante que ele deve ter, também fique a vontade para postar um comentário!

Mudanças no Site e Código do Blog

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Ultimamente fiz várias alterações no site. Refiz quase que todas as páginas e deixei tudo um pouco mais leve e mais fácil para mudar depois. :D Depois de conhecer a POO, me viciei nela no final de semana e converti meu site inteiro para classes. E agora, que seu script tá um pouco melhor organizado, vou colocar aqui para quem quiser copiar, usar alguma idéia, saber como eu estou indo em POO, ver as besteiras que eu faço enquanto programo, etc. :lol: resolvi disponibilizar todo o código de meu blog aqui.

Já que meu blog tem alguns bugs (known bugs de pouca importância, como o caso de se alguém escreve CHARESPC no meio de um comentário ele deve criar um &;), peço somente que ninguém destrua-o sabendo disso. Se alguém descobrir algum bug, pode me enviar um e-mail que ficarei bastante grato. :)

Já que não passei a sessão de administração para POO não vou publicá-la aqui, mas depois de resolver alguns bugzinhos pretendo disponibilizar o código completo, inclusive com um arquivo de instalação que cria as tabelas no banco de dados, para todos poderem usar um sisteminha de blog simples e prático (só que acho que vai ser algo mais voltado a programadores, porque tem vantagens como o uso do GeSHi, e desvantagens como eu publicar todos os posts escrevendo em HTML – isso mesmo, até os & que eu escrevo são &amp; que são &amp;amp; *e um loop infinito pela frente). Hmmm, aliás, quem quiser me ajudar a fazer parte desse projeto para tornar o meu blog um software livre, sinta-se livre para me mandar um e-mail também. :p

Então, uma última observação é que eu substituí todos os <code (note a ausência do > ) por tag code e todos os </code> por tag /code, porque senão minhas expressões regulares do código dariam bug (quer saber por que? Então leia os códigos!)

Funções e classes “includadas” em todos os arquivos

<?php
session_start();
 
// Syntax Highlight - GeSHi
if (!class_exists(GeSHi)) {
	include("geshi.php");
}
 
// Objeto de conexão do MySql
class MySql {
	var $host="servidor";
	var $usuario="usuario";
	var $senha="senha";
	var $db="bancodedados";
	var $conexao;
 
	function conecta() {
		$this->conexao=mysql_connect($this->host, $this->usuario, $this->senha);
		mysql_select_db($this->db);
	}
 
	function desconecta() {
		mysql_close($this->conexao);
	}
}
 
// Classe com as funções de expressões regulares
class Regex {
	function Replace($o, $d, $t, $codes=0) {
		for ($i=0; $i<sizeof($o); $i++) {
			$o[$i]=str_replace('(', '(', $o[$i]);
			$o[$i]=str_replace(')', ')', $o[$i]); 
			$t=eregi_replace($o[$i], $d[$i], $t);
		}
		if ($codes==1) {
			$t="tag /code".$t."tag code";
		} else if ($codes==2) {
			$t.="tag code";
		} else if ($codes==3) {
			$t="tag /code".$t;
		}
		return $t;
	}
 
	function Emoticons() {
		$o[0]=":)";
		$d[0]="feliz";
		$o[1]=":(";
		$d[1]="triste";
		$o[2]=":o";
		$d[2]="bocaaberta";
		$o[3]=":p";
		$d[3]="lingua";
		$o[4]=":angry:";
		$d[4]="raiva";
		$o[5]=":s";
		$d[5]="confuso";
		$o[6]=":blink:";
		$d[6]="inacreditavel";
		$o[7]=";)";
		$d[7]="piscando";
		$o[8]=":lol:";
		$d[8]="rindo";
		$o[9]=":d";
		$d[9]="sorriso";
		$o[10]=":unsure:";
		$d[10]="semgraca";
 
		for ($i=0; $i<sizeof($d); $i++) {
			$d[$i]="<img src="/emoticon/".$d[$i].".gif" alt="".$o[$i]."" />";
		}
 
		if (!ereg("tag code", $texto)) {
			$this->texto=$this->Replace($o, $d, $this->texto);
		} else {
			preg_match_all("/</code>(.+)tag code/sU", $this->texto, $mat1);
			for ($i=0; $i<sizeof($mat1[1]); $i++) {
				$this->texto=str_replace($mat1[1][$i], $this->Replace($o, $d, $mat1[1][$i]), $this->texto);
			}
			preg_match("/^(.+)tag code/sU", $this->texto, $mat2);
			$texto=str_replace($mat2[1], $this->Replace($o, $d, $mat2[1]), $this->texto);
			$rev=strrev($this->texto); //Tenho medo do PHP5.0.5
			preg_match("/^(.+)>edoc/</sU", $rev, $mat3); //Nossa, que código louco!
			$rev=strrev($mat3[1]); //Repito... Tenho medo do PHP5.0.5
			$this->texto=str_replace($rev, $this->Replace($o, $d, $rev), $this->texto); //Agora fuck PHP5.0.5!
		}
	}
 
	function GeshiHighlight($codigo, $linguagem) {
		$geshi=new GeSHi($codigo, $linguagem, "./geshi/");
		return $geshi->parse_code();
	}
 
	function Codigos() {
		preg_match_all("/tag code class="(.*)">(.*)</code>/sU",
			$this->texto,
			$matches);
		for ($i=0; $i<sizeof($matches[1]); $i++) {
			$g=$this->GeshiHighlight($matches[2][$i], $matches[1][$i]);
			if (eregi("MSIE", $_SERVER["HTTP_USER_AGENT"])) {
				$g=ereg_replace("<pre>", "<pre class="alturamaxima">", $g);
			}
			$this->texto=str_replace($matches[0][$i],
				$g,
				$this->texto);
		}
	}
 
	function QuebraLinha() {
		$this->texto=nl2br($this->texto);
	}
}
 
// Objeto "Artigo"
class Artigo extends Regex {
	var $id;
	var $data;
	var $permalink;
	var $titulo;
	var $texto;
	var $comentarios;
 
	function Artigo($identificacao) {
		$this->id=$identificacao;
 
		$mysql=new MySql();
		$mysql->conecta();
 
		$query_post=mysql_query("SELECT data, permalink, titulo, texto FROM artigos WHERE id='{$this->id}'");
		$post=mysql_fetch_row($query_post);
		$this->data=date("d/m/Y", $post[0]);
		$this->permalink=$post[1];
		$this->titulo=$post[2];
		$this->texto=$post[3];
 
		$query_comentarios=mysql_query("SELECT count(id) FROM comentario WHERE idpost='{$this->id}'");
		$comentarios=mysql_fetch_row($query_comentarios);
		$this->comentarios=$comentarios[0];
 
		$mysql->desconecta();
	}
 
	function AppendGoogleAds($ads) {
		$this->texto.="nn".$ads;
	}
 
	function Mostra() {
		echo "<h2><a href="/post/{$this-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>permalink}">{$this->titulo}</a></h2>n";
		echo $this->texto."n";
		echo "<h5>{$this->data} ";
		echo "<a href="/post/{$this-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>permalink}" class="permalink">permalink</a> ";
		echo "<a href="/post/{$this-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>permalink}#comentarios" class="comentarios">";
		echo "{$this->comentarios} comentário(s)</a></h5>n";
	}
 
	function MostraComentarios() {
		if ($_POST["comenta"]&&(!$_SESSION["comentario"]||time()-30>$_SESSION["comentario"])) {
			$_SESSION["comentario"]=time();
			EscreveComentario($_POST["nome"], $_POST["email"], $_POST["texto"], $this->id);
		}
		$comentarios=new Comentarios($this->id);
		$comentarios->Mostra();
	}
}
 
// Objeto Artigos (serve para pegar vários artigos sem eu precisar fazer nada nas outras páginas)
class Artigos {
	var $id;
	var $titulo;
	var $texto;
	var $permalink;
	var $data;
	var $comentarios;
 
	function Artigos($n=20, $start=0, $emoticons=0, $codigos=0, $mostrar=0, $comentarios=0) {
		$mysql=new MySql();
		$mysql->conecta();
		$query=mysql_query("SELECT id FROM artigos ORDER BY data DESC, id DESC LIMIT $start,$n");
		$mysql->desconecta();
		for ($i=0; $array=mysql_fetch_array($query); $i++) {
			$artigo=new Artigo($array["id"]);
			if ($emoticons) {
				$artigo->Emoticons();
			}
			if ($codigos) {
				$artigo->Codigos();
			}
			if ($mostrar) {
				$artigo->Mostra();
			}
			if ($comentarios) {
				$artigo->MostraComentarios();
			}
			$this->id[$i]=$array["id"];
			$this->titulo[$i]=$artigo->titulo;
			$this->texto[$i]=$artigo->texto;
			$this->permalink[$i]=$artigo->permalink;
			$this->comentarios[$i]=$artigo->comentarios;
			$this->data[$i]=$artigo->data;
		}
	}
}
 
// Objeto Comentário
class Comentario extends Regex {
	var $id;
	var $data;
	var $nome;
	var $email;
	var $ip;
	var $useragent;
	var $texto;
	var $numero;
 
	function Comentario($identificacao, $numero) {
		$this->id=$identificacao;
		$this->numero=$numero;
 
		$mysql=new MySql();
		$mysql->conecta();
 
		$query=mysql_query("SELECT data, nome, email, ip, useragent, texto FROM comentario WHERE id='{$this->id}'");
		$comentario=mysql_fetch_row($query);
 
		$this->data=date("d/m/Y", $comentario[0]);
		$this->nome=$comentario[1];
		if ($_SESSION["tiagomadeira"]) {
			$this->email="</small><span style="font-size:10px;"><br />";
			if ($comentario[2]) $this->email.="<strong>E-mail:</strong> ".$comentario[2]."<br />n";
			if ($comentario[3]) $this->ip="<strong>IP:</strong> ".$comentario[3]."<br />n";
			if ($comentario[4]) $this->useragent="<strong>User Agent:</strong> ".$comentario[4];
			$this->useragent.="</span>";
		} else {
			$this->email="</small>";
		}
		$this->texto=$comentario[5];
 
		$mysql->desconecta();
	}
 
	function CharEspc($pos) {
		if ($pos==1) {
			$this->texto=preg_replace("/&([^;]+);/sU", "CHARESPC\1/CHARESPC", $this->texto);
		} else if ($pos==2) {
			$this->texto=preg_replace("/CHARESPC(.+)/CHARESPC/sU", "&\1;", $this->texto);
		}
	}
 
	function Mostra() {
		echo "<div class="comentario" id="com{$this->id}">n";
		echo "t<h4><a href="?PHPSESSID=9ec34c96b02b3755051aa682d1e02001#com{$this->id}">#{$this->numero}</a> | ";
		echo "{$this->nome} ";
		echo "<small>{$this->data}{$this->email}{$this->ip}{$this->useragent}</h4>n";
		echo "<p>{$this->texto}</p>";
		echo "</div>n";
	}
}
 
// Objeto Comentários
class Comentarios {
	var $idpost;
	var $ids;
	var $tamanho;
 
	function Comentarios($idpost) {
		$this->idpost=$idpost;
 
		$mysql=new MySql();
		$mysql->conecta();
 
		$query=mysql_query("SELECT id FROM comentario WHERE idpost='{$this->idpost}' ORDER BY data ASC, id ASC");
		for ($i=1; $array=mysql_fetch_array($query); $i++) {
			$this->ids[$i]=$array["id"];
		}
 
		$this->tamanho=$i;
		$mysql->desconecta();
	}
 
	function Mostra() {
		echo "<h3 id="comentarios">Comentários</h3>n";
		for ($i=1; $i<$this->tamanho; $i++) {
			$comentario=new Comentario($this->ids[$i], $i);
			$comentario->CharEspc(1);
			$comentario->Emoticons();
			$comentario->CharEspc(2);
			$comentario->QuebraLinha();
			$comentario->Mostra();
		}
 
		if ($this->tamanho <= 1) {
			echo "<p>Nenhum comentário cadastrado.</p>n";
		}
 
		FormularioComentario($this->idpost);
	}
}
 
// Função para descobrir IP do visitante
function PegaIP() {
	if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "desconhecido")) {
		$ip=getenv("HTTP_CLIENT_IP");
	} else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "desconhecido")) {
		$ip=getenv("HTTP_X_FORWARDED_FOR");
	} else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "desconhecido")) {
		$ip=getenv("REMOTE_ADDR");
	} else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "desconhecido")) {
		$ip=$_SERVER['REMOTE_ADDR'];
	} else {
		$ip="desconhecido";
	}
 
	return($ip);
}
 
// Função que escreve o formulário para envio de comentário
function FormularioComentario($idpost) {
	$mysql=new MySql();
	$mysql->conecta();
	$query=mysql_query("SELECT permalink FROM artigos WHERE id='$idpost'");
	$row=mysql_fetch_row($query);
	$permalink=$row[0];
	$mysql->desconecta();
?>
 
<h3>Escreva um comentário</h3>
 
<form action="/post/<?=$permalink;?><input type="hidden" name="PHPSESSID" value="9ec34c96b02b3755051aa682d1e02001" />#comentarios" method="post">
	<ul>
		<li><label for="nome">Seu nome:</label>
			<input type="text" name="nome" id="nome" />
		</li>
		<li><label for="email">Seu e-mail<strong>*</strong>:</label>
 
			<input type="text" name="email" id="email" />
		</li>
		<li class="textarea"><label for="texto">Comentário:</label>
			<textarea name="texto" id="texto" cols="20" rows="15"></textarea>
		</li>
	</ul>
	<p><strong>*</strong> - Ele não aparecerá em público. Serve apenas para eu te contatar,
	caso queira responder seu comentário.</p>
 
	<p><input type="submit" name="comenta" value="Comentar" /></p>
</form>
<?php
}
 
// Função que cadastra um comentário
function EscreveComentario($nome, $email, $texto, $idpost) {
	$ip=PegaIP();
	$useragent=$_SERVER["HTTP_USER_AGENT"];
	$nome=purifica($nome);
	$email=purifica($email);
	$texto=purifica($texto);
	$data=time();
	$mysql=new MySql();
	$mysql->conecta();
	mysql_query("INSERT INTO comentario (id, idpost, nome, email, texto, data, ip, useragent) VALUES
		('', '$idpost', '$nome', '$email', '$texto', '$data', '$ip', '$useragent')") or die(mysql_error());
	$mysql->desconecta();
	$email=($email)?$email:"contato@tiagomadeira.net";
	$mensagem="No post de id $idpost, o $nome ($email) comentou em ".date("d/m/Y", $time)." dizendo:";
	$mensagem.="nn";
	$mensagem.="$texto";
	mail("contato@tiagomadeira.net", "[tiagomadeira.net] Novo Comentário!", "$mensagem", "From: $nome <$email>");
}
 
// Função que cria escreve o título das seções
function titulo($titulo) {
	$tit="$titulo [tiagomadeira.net]";
	echo "<script type="text/javascript">n";
	echo "ttop.document.title="$tit";n";
	echo "</script>n";
}
 
// Função para purificar os comentários depois do envio
function purifica($texto) {
	$t=ereg_replace("&", "&amp;", $texto);
	$t=ereg_replace("%", "&#37;", $t);
	$t=ereg_replace("<", "&lt;", $t);
	$t=ereg_replace(">", "&gt;", $t);
	$t=ereg_replace("[", "&#91;", $t);
	$t=ereg_replace("]", "&#93;", $t);
	$t=ereg_replace(""", "&quot;", $t);
	return $t;
}
 
// Função para editar artigos
function pra_textarea($texto) {
	$texto=ereg_replace("&", "&amp;", $texto);
	$texto=ereg_replace("<", "&lt;", $texto);
	$texto=ereg_replace(">", "&gt;", $texto);
	$texto=ereg_replace(""", "&quot;", $texto);
	return $texto;
}
 
?>

E os arquivos que usam essas funções e classes…

/artigos (ou /blog)

<?php
	$artigosporpagina=10; //Artigos Por Página
	$p=($_GET["pg"])?$_GET["pg"]:1; //Página Atual
 
	$mysql=new MySql();
	$mysql->conecta();
	$query=mysql_query("SELECT count(id) FROM artigos");
	$row=mysql_fetch_row($query);
	$np=ceil($row[0]/$artigosporpagina);
	$mysql->desconecta();
 
	$paginacao="";
	for ($i=1; $i<=$np; $i++) {
		$paginacao.="<a href="/artigos/$i"";
?PHPSESSID=9ec34c96b02b3755051aa682d1e02001
		if ($i==$p) $paginacao.=" style="font-weight:bold; color:#c00;"";
		$paginacao.=">$i</a> ";
	}
	$paginacao="nn<p style="text-align:center;"><span style="color:#aaa; font-size:11px;">Ir para página:</span> $paginacao</p>nn";

	echo $paginacao;
 
	$artigos=new Artigos($artigosporpagina, ($p-1)*$artigosporpagina);
	echo "<ul>n";
	for ($i=0; $i<count($artigos->id); $i++) {
		echo "<li><a href="/post/{$artigos-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>permalink[$i]}">{$artigos->titulo[$i]}</a><br />";
		echo "<small>{$artigos->data[$i]} ";
		echo "<a class="comentarios" href="/post/{$artigos-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>permalink[$i]}#comentarios">{$artigos->comentarios[$i]} comentário(s)</a>";
		if ($_SESSION["tiagomadeira"]) {
			echo " <a href="/admin-edita&amp;id={$artigos-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>id[$i]}">[editar]</a>";
			echo " <a href="/admin-exclui&amp;id={$artigos-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>id[$i]}">[excluir]</a>";
		}
		echo "</small></li>n";
	}
	echo "</ul>n";
 
	echo $paginacao;
?>

/ (ou /ultimos)

<?php
	$artigos=new Artigos(5, 0, 1, 1, 1);
?>

Para finalizar… .htaccess

RewriteEngine On
 
#Diretórios
RewriteRule ^link/?$ http://tableless.tiagomadeira.net
RewriteRule ^post/?$ http://tableless.tiagomadeira.net/blog
RewriteRule ^script/?$ http://tableless.tiagomadeira.net/scripts
RewriteRule ^downloadscript/?$ http://tableless.tiagomadeira.net/scripts
 
#Blog: A grande excessão
RewriteRule ^blog/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=blog&pg=$1
RewriteRule ^/link/blog/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=blog&pg=$1
RewriteRule ^artigos/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=blog&pg=$1
RewriteRule ^/link/artigos/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=blog&pg=$1
 
#Links
RewriteRule ^link/(.+)$ http://tableless.tiagomadeira.net/index.php?l=$1
RewriteRule ^([^/.]+)$ http://tableless.tiagomadeira.net/index.php?l=$1
 
#Posts
RewriteRule ^post/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=artigo&id=$1
RewriteRule ^post/(.+)$ http://tableless.tiagomadeira.net/index.php?l=artigo&permalink=$1
 
#Scripts
RewriteRule ^script/(.+)$ http://tableless.tiagomadeira.net/index.php?l=script&script=$1
RewriteRule ^downloadscript/(.+)$ http://tableless.tiagomadeira.net/downloadscript.php?script=$1
 
#Feeds
RewriteRule ^feed.rss$ http://tableless.tiagomadeira.net/rss.php
RewriteRule ^rss.xml$ http://tableless.tiagomadeira.net/rss.php
RewriteRule ^index.rss$ http://tableless.tiagomadeira.net/rss.php
RewriteRule ^sitemap.xml$ http://tableless.tiagomadeira.net/sitemap.php

Samba em Prelúdio

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

GeSHi Highlight funcionando! Página “oficial” de testes…

#include <stdio.h>
int main() {
   printf("Eu sem você");
}
program continuacao;
 
begin
   write('Não tenho porquê.');
end.
<?php
   echo "Porque sem você...";
?>
<html>
   <head>
      <title>Continuação</title>
   </head>
 
   <body>
      <p>Não sei nem chorar...</p>
   </body>
</html>
#!/bin/bash
 
echo "Sou chama sem luz..."
.jardim {
   sem:luar;
   luar:sem amor;
   amor:sem se dar;
}
document.write("Eu sem você...");
print 'Sou só desamor.'
INSERT INTO musica (letra) VALUES ('Um barco sem mar...');
<%
response.write("Um campo sem flor.");
%>
<?xml version="1.0">
 
<window id="janela" title="Continuação em XUL" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<text id="resto" value="Tristeza que vai, tristeza que vem" />
</window>

E por aí vai… Heheh…

Novo site!

ATENÇÃO: Este conteúdo foi publicado há 12 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Deixei o site fora do ar por dois dias para acabar de fazer esse design. E não refiz só o design. Refiz os bancos de dados, textos (links), adicionei a seção Portifólio e reprogramei todo o site. Agora eu cadastro posts em HTML, fazendo com que eu possa abusar mais de formatação nos artigos. Posso postar várias imagens tipo as da minha biografia (aliás, enchi minha biografia de fotos). Também fiz bastante mudanças nas expressões regulares do site.

GeSHi

Estou usando o GeSHi para sintaxe colorida dos códigos que posto aqui. O “teste oficial” é o post Samba em Prelúdio que traz trechos dessa música, do Vinicius de Moraes e Baden Powell, escritos em várias linguagens, de várias formas diferentes, com sintaxe colorida do GeSHi.

Ainda não tá pronto!

Já publiquei tudo aqui como oficial, mas o site ainda não está completamente pronto. Ainda não fiz o feed (embora ele esteja declarado no cabeçalho da página), não acabei a seção Portifólio e nem o sistema de emoticons aqui dos posts e comentários. Eu tinha feito, mas o problema é que tava colocando emoticons nos códigos… Por isso, ainda tô tentando descobrir como eu faço para só o que tá fora dos code passar pela função de emoticons e espero que tudo se normalize em breve.

Eu também não copiei todos os posts antigos para cá, mas estou fazendo isso, pela ordem da visualização e comentários dos posts. Os posts mais linkados em outros locais já foram copiados, como a falha no Fotolog.net, posts sobre permutação, etc.

Avaliação

Postei o site em alguns fóruns para ser avaliado. Ele é totalmente baseado em CSS, então eu posso vir a alterar alguns detalhes. Agora ele tá bem mais semântico e bem escrito do que o antigo, o que facilita essas mudanças. Postem suas críticas e sugestões aí nos comentários! ;)

Espero que gostem!

Demonstrações matemáticas, IE 7, Bash, GeSHi

ATENÇÃO: Este conteúdo foi publicado há 13 anos. Eu talvez nem concorde mais com ele. Se é um post sobre tecnologia, talvez não faça mais sentido. Mantenho neste blog o que escrevo desde os 14 anos por motivos históricos. Leia levando isso em conta.

Ultimamente não tenho me dedicado muito a resolução de problemas lógicos utilizando algoritmos e não tenho programado em C, mas andei estudando um pouco LaTeX e demonstrando teoremas matemáticos. Quarta-feira, o professor Vavá sugeriu ao nosso grupo de estudo da Olimpíada de Matemática provar 10 teoremas da matemática (entre eles, a fórmula de Bhaskara, o Teorema de Pitágoras, Relação Fundamental da Trigonometria, etc.) e estou tentando demonstrá-los com até q.e.d. no fim… :D

Bom, já que estava estudando LaTeX e o objetivo era provar de forma clara os teoremas, acabei transformando alguns em PDF.

  • Provar que, dentre todos os retângulos de perímetro constante, o de maior área é o quadrado
  • Provar, a partir de um quadrado de lado “a”, o famoso Teorema de Pitágoras.

Atualizado em 2012: esses arquivos — area-quadrilatero.pdf e teorema-pitagoras.pdf — foram perdidos no servidor.

O Ivo me falou sobre a fórmula de Bhaskara e eu consegui provar que o produto de dois números pares é necessariamente um número par (essa é totalmente ridícula). Tem duas propriedades logaritmicas que há algum tempo eu sabia demonstrar, mas agora não lembro. E algumas outras coisas que ainda não faço idéia de como provar…

Quarta-feira, antes do encontro de matemática, minha banda (Zibian) ensaiou (foi um ensaio totalmente precário, mas fazia tempo que a gente não ensaiava).

Sexta-feira (ontem), fui num dos melhores shows da minha vida. Yamandu Costa, Paulo Moura, Armandinho (pelo amor de Deus, não é o cara do reggae) e Robertinho Silva tocaram no CIC em Florianópolis interpretando obras de Tom Jobim em homenagem aos 10 anos desde a morte desse grande compositor. Foi muito bom. Os caras tocando música instrumental de primeira com as lindas músicas do Tom.

Ontem também li sobre um artigo na página do Bruno Torres falando sobre os developers do IE 7 implementando no novo navegador (se é que aquilo é digno de ser chamado de navegador) uma engine da Gecko (do Mozilla) modificada. “Um engenheiro da microsoft, do time que está trabalhando no desenvolvimento da nova versão de seu pseudo-browser do ícone azul, afirmou extra-oficialmente que ele e seus pares estão trabalhando em uma adaptação de um engine open-source de renderização HTML e CSS, o gecko (lagartixa em português, por isso comendo mosca), usado pelos navegadores mozilla e firefox, além do Netscape.” (trecho do artigo). É uma pena que depois tenha descoberto que se tratava apenas de uma brincadeira de primeiro de abril e o nome do engenheiro era “Adrem Resworb” que ao contrário fica “Browser Merda”.

Tenho criado alguns scripts em Bash para resolver grandes problemas (é incrível a utilidade desses pequenos scripts!) e estou refazendo o QueimaCD, agora em dialog para o Sinapx (a distro que eu e um grupo de pessoas estamos desenvolvendo no SOSPHP).

Andei testando o GeSHi (é um syntax highlighter – um programinha pra deixar os códigos coloridos na página) e estou pensando em colocar aqui na página (mesmo antes de trocar de site, porque aquele novo design tava muito apagado e por isso, vou deixar a página assim mesmo até ter uma idéia melhor). É legal ele ter opções de várias linguagens e fica bonitinho… :)

Nos últimos dias, também li alguns trechos do “Algoritmos: Teoria e Prática”. Esse livro é bem complicadinho… No fim, tem 70 páginas (da 820 a 890) somente falando sobre propriedades das somatórias! Mas é totalmente bem explicado e tem muito conteúdo. Acho que foi uma ótima coisa ter comprado ele. Acho que o custo-benefício dele tá ótimo.

Hoje configurei o Slackware inteiro do Héliton via SSH (ainda bem que a internet tava boa nos dois lados), toquei um pouco de pandeiro (oO, tô quase igual o Robertinho Silva…), respondi alguma coisa em fóruns, ouvi música, assisti televisão… No fim, fiquei cheio de trabalho de escola pra fazer amanhã.

Bom… Mês que vem é a prova da OBI, o Papa morreu (90000 pessoas no Vaticano!? Alguém quer tentar calcular a densidade demográfica?), houve uma chacina totalmente cruel na Baixada Fluminense, assassinaram a Terri nos EUA… Acontece tanta coisa no mundo! :blink: