Thursday, July 28, 2011

Wildcard in CSP

For certain rules, you can set "*" to allow all. When you do so, be sure to delete any other statements, or else they would narrow down the search, making "*" ineffective.

More details

Wednesday, July 27, 2011

discovered ~/.bash_aliases :) bash command shortcuts

wow this could have saved me so much time

Python Check.py!

pip install -e git://github.com/jbalogh/check.git#egg=check

Pip Install Django Debug Toolbar

pip install django-debug-toolbar

So you get to do python manage.py debugsqlshell and have a debug sidebar.

It's awesome

Pypi

Tuesday, July 26, 2011

Randomizing in Django QuerySet and Python List

Django QuerySet:

my_queryset.order_by('?')

Python List:

import random

random.shuffle(my_list)


And then you can use slice to just keep n elements, e.g.
n = 5
my_queryset.order_by('?')[:n]

Sunday, July 24, 2011

Django get user object in views.py

In views.py
def index(request):
    # get user
    try:
        the_user = User.objects.get(username = request.user)
    except User.DoesNotExist:
        return HttpResponse("Invalid username")

Saturday, July 23, 2011

How adopted-kitsune Django upload works.

0. forms.py
class ImageAttachmentUploadForm(forms.Form):
    """Image upload form."""
    print "############################in form"
    image = forms.ImageField(error_messages={'required': MSG_IMAGE_REQUIRED,
                                             'max_length': MSG_IMAGE_LONG},
                             max_length=settings.MAX_FILENAME_LENGTH)


1. views.py

for fileupload page if request.method == 'POST':
    form = forms.ImageAttachmentUploadForm(request.POST, request.FILES)
    if form.is_valid()

2. playdoh/vendor/src/django/django/forms/fields.py

class ImageField(FileField):
    def to_python(self, data):

        """
        Checks that the file-upload field data contains a valid image (GIF, JPG,
        PNG, possibly others -- whatever the Python Imaging Library supports).
        """

Thursday, July 21, 2011

Cannot shutdown Ubuntu, always restarts

Solution:
sudo shutdown -h now

MySQL Dump Database

Dump:

1. mysqldump -u root -p database_name > db_backup.sql

2. somehow get db_backup.sql to the machine where you want to dump, and make sure you can see db_backup.sql from ls

3. mysql -u root -p

4. use database_you_want_to_dump_name

5. source db_backup.sql

6. show tables;

Yay!

source

Ubuntu pip install record

MozSecWorld$ sudo pip install -r requirements/compiled.txt 
Downloading/unpacking py-bcrypt==0.2 (from -r requirements/compiled.txt (line 7))
  Running setup.py egg_info for package py-bcrypt
Downloading/unpacking hashlib==20081119 (from -r requirements/compiled.txt (line 6))
  Running setup.py egg_info for package hashlib
    Using OpenSSL version 0x009080ff from
     Headers: /usr/include
     Library: /usr/lib/libssl.so
    no previously-included directories found matching 'build'
    no previously-included directories found matching 'dist'
    no previously-included directories found matching 'RCS'
    no previously-included directories found matching 'CVS'
    no previously-included directories found matching '.svn'
Downloading/unpacking Jinja2==2.5.5 (from -r requirements/compiled.txt (line 2))
  Running setup.py egg_info for package Jinja2
    warning: no previously-included files matching '*' found under directory 'docs/_build'
    warning: no previously-included files matching '*.pyc' found under directory 'jinja2'
    warning: no previously-included files matching '*.pyc' found under directory 'docs'
    warning: no previously-included files matching '*.pyo' found under directory 'jinja2'
    warning: no previously-included files matching '*.pyo' found under directory 'docs'
Downloading/unpacking MySQL-python==1.2.3c1 (from -r requirements/compiled.txt (line 1))
  Running setup.py egg_info for package MySQL-python
    sh: mysql_config: not found
    Traceback (most recent call last):
      File "", line 14, in 
      File "/home/haoqili/Desktop/MozSecWorld/build/MySQL-python/setup.py", line 15, in 
        metadata, options = get_config()
      File "setup_posix.py", line 43, in get_config
        libs = mysql_config("libs_r")
      File "setup_posix.py", line 24, in mysql_config
        raise EnvironmentError("%s not found" % (mysql_config.path,))
    EnvironmentError: mysql_config not found
    Complete output from command python setup.py egg_info:
    sh: mysql_config: not found

Traceback (most recent call last):

  File "", line 14, in 

  File "/home/haoqili/Desktop/MozSecWorld/build/MySQL-python/setup.py", line 15, in 

    metadata, options = get_config()

  File "setup_posix.py", line 43, in get_config

    libs = mysql_config("libs_r")

  File "setup_posix.py", line 24, in mysql_config

    raise EnvironmentError("%s not found" % (mysql_config.path,))

EnvironmentError: mysql_config not found

----------------------------------------
Command python setup.py egg_info failed with error code 1
Storing complete log in /home/haoqili/.pip/pip.log

and then python manage.py runserver still gives "ImportError: No module named bcrypt" error.

so sudo pip install py-bcrypt worked

Set up SSH

sudo aptitude install openssh-server openssh-client

Wednesday, July 20, 2011

Preparing to Set up MozSecWorld on Linux

Since the permanent host for MozSecWorld will be on linux.

1. Install libapache2-mod-wsgi. This is a Python apache!
sudo apt-get install libapache2-mod-wsgi

2. Install Apache2. /etc/init.d/apache2 status should say that "Apache2 is running"

3. Configure Apache2.

4. clone repository git clone https://github.com/haoqili/MozSecWorld

5. Get the vendor. cd MozSecWorld/vendor and then git clone --recursive git://github.com/mozilla/playdoh-lib.git .
follow the Setup Section until
python manage.py runserver does not complain about any missing modules

Getting Image Upload to work on Django

Learned form r1cky that jpeg and PIL are packages that need to be recompiled for other people, especially those on different operating systems

haoqili: how can I tell if a package needs to be recompiled on the VM or not?
r1cky: hmm, that is a good question. if it is only .py source files then it doesnt need compiling
r1cky: but some libraries have C in them
r1cky: the ones that we use that need compiling are
r1cky: MySQL-python, Jinja2, PIL, lxml
r1cky: and the jpeg one
r1cky: those are installed separately (not copied into the repository)

1. Install PIL into my vendor-local

playdoh (master)$  pip install -I --install-option="--home=`pwd`/vendor-local" pil
Downloading/unpacking pil
  Downloading PIL-1.1.7.tar.gz (506Kb): 506Kb downloaded
  Running setup.py egg_info for package pil
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    
Installing collected packages: pil
  Running setup.py install for pil
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    --- using frameworks at /System/Library/Frameworks
    building '_imaging' extension
    /usr/bin/cc -fno-strict-aliasing -O3 -w -pipe -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_LIBZ -I/System/Library/Frameworks/Tcl.framework/Headers -I/System/Library/Frameworks/Tk.framework/Headers -IlibImaging -I/Users/haoqili/.virtualenvs/playdoh/include -I/usr/local/include -I/usr/include -I/usr/local/Cellar/python/2.7.1/include/python2.7 -c _imaging.c -o build/temp.macosx-10.4-x86_64-2.7/_imaging.o
    ...
    /usr/bin/cc -L/usr/local/Cellar/readline/6.2.1/lib -bundle -undefined dynamic_lookup -L/usr/local/Cellar/readline/6.2.1/lib build/temp.macosx-10.4-x86_64-2.7/_imagingmath.o -L/usr/local/lib -L/Users/haoqili/.virtualenvs/playdoh/lib -L/usr/lib -o build/lib.macosx-10.4-x86_64-2.7/_imagingmath.so
    --------------------------------------------------------------------
    PIL 1.1.7 SETUP SUMMARY
    --------------------------------------------------------------------
    version       1.1.7
    platform      darwin 2.7.1 (r271:86832, Jun  6 2011, 13:57:48)
                  [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
    --------------------------------------------------------------------
    --- TKINTER support available
    *** JPEG support not available
    --- ZLIB (PNG/ZIP) support available
    *** FREETYPE2 support not available
    *** LITTLECMS support not available
    --------------------------------------------------------------------
    To add a missing option, make sure you have the required
    library, and set the corresponding ROOT variable in the
    setup.py script.
    
    To check the build, run the selftest.py script.
    changing mode of build/scripts-2.7/pilconvert.py from 644 to 755
    changing mode of build/scripts-2.7/pildriver.py from 644 to 755
    changing mode of build/scripts-2.7/pilfile.py from 644 to 755
    changing mode of build/scripts-2.7/pilfont.py from 644 to 755
    changing mode of build/scripts-2.7/pilprint.py from 644 to 755
    
    changing mode of /Users/haoqili/dev/playdoh/playdoh/playdoh/vendor-local/bin/pilconvert.py to 755
    changing mode of /Users/haoqili/dev/playdoh/playdoh/playdoh/vendor-local/bin/pildriver.py to 755
    changing mode of /Users/haoqili/dev/playdoh/playdoh/playdoh/vendor-local/bin/pilfile.py to 755
    changing mode of /Users/haoqili/dev/playdoh/playdoh/playdoh/vendor-local/bin/pilfont.py to 755
    changing mode of /Users/haoqili/dev/playdoh/playdoh/playdoh/vendor-local/bin/pilprint.py to 755
Successfully installed pil
Cleaning up...

2. Trying to get JPEG to be supported:
playdoh/vendor-local (master)$ brew install jpeg
Warning: Xcode is not installed! Builds may fail!
==> Downloading http://www.ijg.org/files/jpegsrc.v8c.tar.gz
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/jpeg/8c --disable-dependency-tracking
==> make install
/usr/local/Cellar/jpeg/8c: 17 files, 1.6M, built in 13 seconds

3. Rebuild PIL
)$ pip install PIL==1.1.7 --upgrade
Downloading/unpacking PIL==1.1.7
  Downloading PIL-1.1.7.tar.gz (506Kb): 506Kb downloaded
  Running setup.py egg_info for package PIL
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    
Installing collected packages: PIL
  Found existing installation: PIL 1.1.7
    Uninstalling PIL:
      Successfully uninstalled PIL
  Running setup.py install for PIL
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    WARNING: '' not a valid package name; please use only.-separated package names in setup.py
    --- using frameworks at /System/Library/Frameworks
    building '_imaging' extension
    /usr/bin/cc -fno-strict-aliasing -O3 -w -pipe -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DHAVE_LIBJPEG -DHAVE_LIBZ -I/System/Library/Frameworks/Tcl.framework/Headers -I/System/Library/Frameworks/Tk.framework/Headers -IlibImaging -I/Users/haoqili/.virtualenvs/playdoh/include -I/usr/local/include -I/usr/include -I/usr/local/Cellar/python/2.7.1/include/python2.7 -c _imaging.c -o build/temp.macosx-10.4-x86_64-2.7/_imaging.o
    ...
    /usr/bin/cc -L/usr/local/Cellar/readline/6.2.1/lib -bundle -undefined dynamic_lookup -L/usr/local/Cellar/readline/6.2.1/lib build/temp.macosx-10.4-x86_64-2.7/_imagingmath.o -L/usr/local/lib -L/Users/haoqili/.virtualenvs/playdoh/lib -L/usr/lib -o build/lib.macosx-10.4-x86_64-2.7/_imagingmath.so
    --------------------------------------------------------------------
    PIL 1.1.7 SETUP SUMMARY
    --------------------------------------------------------------------
    version       1.1.7
    platform      darwin 2.7.1 (r271:86832, Jun  6 2011, 13:57:48)
                  [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)]
    --------------------------------------------------------------------
    --- TKINTER support available
    --- JPEG support available
    --- ZLIB (PNG/ZIP) support available
    *** FREETYPE2 support not available
    *** LITTLECMS support not available
    --------------------------------------------------------------------
    To add a missing option, make sure you have the required
    library, and set the corresponding ROOT variable in the
    setup.py script.
    
    To check the build, run the selftest.py script.
    changing mode of build/scripts-2.7/pilconvert.py from 644 to 755
    changing mode of build/scripts-2.7/pildriver.py from 644 to 755
    changing mode of build/scripts-2.7/pilfile.py from 644 to 755
    changing mode of build/scripts-2.7/pilfont.py from 644 to 755
    changing mode of build/scripts-2.7/pilprint.py from 644 to 755
    
    changing mode of /Users/haoqili/.virtualenvs/playdoh/bin/pilconvert.py to 755
    changing mode of /Users/haoqili/.virtualenvs/playdoh/bin/pildriver.py to 755
    changing mode of /Users/haoqili/.virtualenvs/playdoh/bin/pilfile.py to 755
    changing mode of /Users/haoqili/.virtualenvs/playdoh/bin/pilfont.py to 755
    changing mode of /Users/haoqili/.virtualenvs/playdoh/bin/pilprint.py to 755
Successfully installed PIL
Cleaning up...

Tuesday, July 19, 2011

My Project's Packages

Todo:

1. update my own vendor with git clone --recursive git://github.com/mozilla/playdoh-lib.git ./vendor from playdoh doc

2. clean up my imports

3. clean up my vendor-local from virutal enviorments below from /Users/haoqili/.virtualenvs/playdoh/lib/python2.7/site-packages


haoqili@host-3-248:15:44:10:~/.virtualenvs/playdoh/lib/python2.7/site-packages$ ls -l
total 1016
drwxr-xr-x  11 haoqili  staff     374 Jun 15 10:39 Crypto
drwxr-xr-x   4 haoqili  staff     136 Jun 30 09:41 Django-1.3-py2.7.egg
drwxr-xr-x  10 haoqili  staff     340 Jun  6 14:58 Jinja2-2.5.5-py2.7.egg-info
drwxr-xr-x   7 haoqili  staff     238 Jun  6 14:58 MySQL_python-1.2.3c1-py2.7.egg-info
drwxr-xr-x  15 haoqili  staff     510 Jun  6 14:58 MySQLdb
drwxr-xr-x  12 haoqili  staff     408 Jun 15 11:44 OpenSSL
drwxr-xr-x   4 haoqili  staff     136 Jun 15 10:09 Twisted-11.0.0_r32122-py2.7-macosx-10.4-x86_64.egg
-rwxr-xr-x   1 haoqili  staff   18328 Jun  6 14:58 _hashlib.so
-rwxr-xr-x   1 haoqili  staff   70072 Jun  6 14:58 _mysql.so
-rw-r--r--   1 haoqili  staff    2306 Jun  6 14:57 _mysql_exceptions.py
-rw-r--r--   1 haoqili  staff    4559 Jun  6 14:58 _mysql_exceptions.pyc
drwxr-xr-x   5 haoqili  staff     170 Jun 14 16:40 backports
drwxr-xr-x   7 haoqili  staff     238 Jun 14 16:40 backports.ssl_match_hostname-3.2a3-py2.7.egg-info
drwxr-xr-x   5 haoqili  staff     170 Jun  6 14:54 bcrypt
-rw-r--r--   1 haoqili  staff      48 Jun 13 12:00 bleach.egg-link
-rw-r--r--   1 haoqili  staff    6032 Jul  6 13:44 django_csp-1.0.1-py2.7.egg
-rw-r--r--   1 haoqili  staff    6854 Jun 30 09:41 django_ratelimit-0.1-py2.7.egg
drwxr-xr-x   7 haoqili  staff     238 Jun 29 19:46 django_registration-0.7-py2.7.egg-info
-rw-r--r--   1 haoqili  staff     509 Jul  6 13:44 easy-install.pth
drwxr-xr-x   7 haoqili  staff     238 Jun  6 14:58 hashlib-20081119-py2.7.egg-info
-rw-r--r--   1 haoqili  staff    4993 Jun  6 14:58 hashlib.py
-rw-r--r--   1 haoqili  staff    4452 Jun  6 14:58 hashlib.pyc
drwxr-xr-x   9 haoqili  staff     306 Jun  6 14:58 hmac-20101005-py2.7.egg-info
-rw-r--r--   1 haoqili  staff    4531 Jun  6 14:57 hmac.py
-rw-r--r--   1 haoqili  staff    4892 Jun  6 14:58 hmac.pyc
drwxr-xr-x  24 haoqili  staff     816 Jun 13 12:00 html5lib
drwxr-xr-x   7 haoqili  staff     238 Jun 13 12:00 html5lib-0.90-py2.7.egg-info
drwxr-xr-x  49 haoqili  staff    1666 Jun  6 14:58 jinja2
drwxr-xr-x   4 haoqili  staff     136 Jun  6 14:23 pip-1.0.1-py2.7.egg
drwxr-xr-x   8 haoqili  staff     272 Jun 15 11:44 pyOpenSSL-0.12-py2.7.egg-info
drwxr-xr-x   7 haoqili  staff     238 Jun  6 14:54 py_bcrypt-0.2-py2.7.egg-info
-rw-r--r--   1 haoqili  staff     629 Jun 15 10:46 pycrypto-2.0.1-py2.7.egg-info
-rw-r--r--   1 haoqili  staff    8399 Jun 29 20:31 recaptcha_client-1.0.6-py2.7.egg
drwxr-xr-x  18 haoqili  staff     612 Jun 29 19:46 registration
-rw-r--r--   1 haoqili  staff  332005 Jun  6 14:12 setuptools-0.6c11-py2.7.egg
-rw-r--r--   1 haoqili  staff      30 Jun 15 10:09 setuptools.pth
drwxr-xr-x   4 haoqili  staff     136 Jun 15 10:09 zope.interface-3.6.3-py2.7-macosx-10.4-x86_64.egg

Regex Combine lines

takes any end whitespace and combine with starting whitespace of next line
:%s/\s*$\n\s*/ /g

Django Playdoh Package Locations

I was confused when reading how to add packages and seeing that packages live in different locations.

jsocol clarified:

/packages is old-and-busted, use lib/python for non-git things
but you can't put any libraries with compiled components into the vendor lib (it means vendor can't contain anything with c/c++ components)
it's just a question of installing via git (or, well, pip install vcs+vcs://) or using PyPI and the name (e.g. "pip install foo")


pip install foo gives vendor-local/lib/python/foo

using git to install foo gives vendor-local/src/foo



This is what I did, with help from groovecoder. :D

playdoh (master)$ pip install --no-install --build=vendor-local/packages --src=vendor-local/src -I cef
Downloading/unpacking cef
  Downloading cef-0.2.tar.gz
  Running setup.py egg_info for package cef
    
Successfully downloaded cef

And then I found that cef is inside vendor-local/packages. :D

Now I need to add this path to vendor.pth. Groovecoder told me that "*.pth files are automatically included by the python interpreter"

playdoh/vendor-local (master)$ cat vendor.pth 
packages/cef

Now I can use cef!
playdoh (master)$ python manage.py shell
...
>>> from cef import log_cef
>>>

I could also have done
/playdoh (master)$ pip install -I --install-option="--home=`pwd`/vendor-local" cef
Downloading/unpacking cef
  Downloading cef-0.2.tar.gz
  Running setup.py egg_info for package cef
    
Installing collected packages: cef
  Running setup.py install for cef
    
Successfully installed cef
Cleaning up...
and have
playdoh/vendor-local/lib/python (master)$ ls
cef-0.2-py2.7.egg-info cef.py                 cef.pyc

Django urls, best practice

First iteration:
template html:
<a href="/msw/{{ page.slug }}/">back</a><



Second iteration:
template html:
<a href="{{ url('detail', 'richtext_and_safe_url') }}">back</a>
with
urls.py:
url(r'^(?P<input_slug>\w+)/$', views.detail, name='detail')


Third (best) iteration
template html:
<h1><a href="{{ page.reverse_url() }}">back</a></h1>
in models.py:
class Page(models.Model):
    slug = models.SlugField() # another way
    ....
    def reverse:_url(self):
        return reverse('detail', args=[self.slug])
        #return reverse('detail', args=['richtext_and_safe_url']) # hard coded way
be sure to pass in "page" in your views.py

inspiration

Sunday, July 17, 2011

jQuery hosting

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>

I am tired of going to my site every time and get it from its source.

Friday, July 15, 2011

MySQL Update

update table_name set col_name='val_new' where col_name='val_indicator';

Where MySQL .frm files are located

1. Get into your mysql prompt

2. mysql> SHOW VARIABLES LIKE 'datadir';

go to the location of the value and cd into your database as the directory

Or you can use find!!

find -name . *.frm

Read more

Thursday, July 14, 2011

Wednesday, July 13, 2011

Django shell add user permissions and group permissions

Django doc

1. Start the shell, go to your maange.py
>>> python manage.py shell


2. Get the user

Either load one ...
>>> from django.contrib.auth import authenticate
>>> user = authenticate(username="johndoe", password="yourpw")

Or create one ...
>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user(username='johndoe', email="",  password="yourpw")
Django should silently automatically save it, and you should see it under Users in your admin page. But if you want save it yourself, do:
>>> user.is_staff = False
>>> user.save


3. Check the user's permissions
user.get_all_permissions()
or
user.user_permissions.all()



1. Start the shell, go to your maange.py
>>> python manage.py shell

2. Create the group
>>> from django.contrib.auth.models import Group
>>> group = Group(name="GroupName")
>>> group.save()

NOTE that Django pre-made permissions are only suggestions, they only go as far as their string names. YOU have to implement them if you want to use them.

Python Lambda Function

Really nice article with nice examples.

Monday, July 11, 2011

Django reference/link to media/js from apps/myapp/views.py

I had to change a javascript file in media/js/my.js on every refresh of a page (apps/myapp/views.py), the path to open that js file is: f = open('media/js/my.js', 'r+').

See a live demo of this here.

Google recaptcha with CSP, hosting javascript locally

I display google's recaptcha from google's recaptcha javascript hosted on my own server after a little manipulation (since I have CSP turned on, I have to bypass the in-body script and setInterval). But I still need to ping google every time for a new challenge.

1. So I saved my domain's equivalent of the RecaptchaState javascript medai/js/google/recState.js.

2. Refresh this file in views.py's by calling this function:
def recaptchaRefresh():
    # get the Recaptcha state.
    url = "https://www.google.com/recaptcha/api/challenge?k=%s" % settings.RECAPTCHA_PUBLIC_KEY
    resock = urllib.urlopen(url)
    data = resock.read()
    resock.close()

    # extract the recaptcha state part of the string
    docloc = data.find("document.write")

    recaptchaState = data[:docloc]

    f = open('media/js/google/recState.js', 'r+')
    f.write(recaptchaState)
    f.close()

3. Copy paste recaptcha.js and make the following changes for CSP compatibility:

3.1 CSP blocks setIntervals that takes string parameters, so change it into a function:
//Recaptcha.timer_id = setInterval("Recaptcha.reload('t');", (a.timeout - 300) * 1E3) 
// -->
Recaptcha.timer_id = setInterval( function() {Recaptcha.reload('t'); }, (a.timeout - 300) * 1E3)

3.2 CSP blocks in-body javascript, host it externally
//} else document.write('<div id="recaptcha_widget_div" style="display:none"></div>'), document.write('<script>Recaptcha.widget = Recaptcha.$("recaptcha_widget_div"); Recaptcha.challenge_callback();<\/script>');
// -->
} else document.write('<div id="recaptcha_widget_div" style="display:none"></div>'), document.write('<script src="http://haoqili.scripts.mit.edu/js/test3.js"><\/script>');

where http://haoqili.scripts.mit.edu/js/test3.js has "Recaptcha.widget = Recaptcha.$("recaptcha_widget_div"); Recaptcha.challenge_callback();"

4. and in your template.html include the javascript from step 2 and 3.

5. Change your settings.py's CSP policies to have "http[s]://www.google.com" allowed in many places. See example

Recaptcha Hunt

The hunt to figure out how to do recaptcha with CSP is on its 4th day. A few things learned:

--> don't assume anything. I could have figured out the CSP_REPORT_ONLY if I actually tried amo's settings word by word.
--> copy paste the entire chunk

--> read and try to make sence of error messages. think about them.

Vim comment/uncomment block of lines with commands

Vim comment/uncomment block of lines with commands

working on lines 24 to 314

comment:
:24,314s/^/#/g

uncomment:
:24,314s/^#//g

Javascript indentation with beautifier

So useful!!!

Javascript comma!

The comma operator evaluates both of its operands (from left to right) and returns the value of the second operand.

as seen in Google recaptcha's js:

if (RecaptchaOptions.theme == "custom") {
    if (RecaptchaOptions.custom_theme_widget) Recaptcha.widget = Recaptcha.$(RecaptchaOptions.custom_theme_widget);
    Recaptcha.challenge_callback()
} else 
    document.write('<div id="recaptcha_widget_div" style="display:none"></div>'),
    document.write('<script>Recaptcha.widget = Recaptcha.$("recaptcha_widget_div"); Recaptcha.challenge_callback();<\/script>');

Sunday, July 10, 2011

How ReCaptcha should not work with in-body script

Big Question: Why doesn't my ReCaptchaField show up while AMO's ReCaptcha show up if our ReCaptchaField stuff matches exactly, including the parts that displays the in-body javascript? Issue on github

Skip to solution

How an In-Body Javascript is ultimately introduced in Google Recaptcha:

1. Your Django Form has ReCaptchaField. e.g. File: apps/users/forms.py
import captcha.fields

class UserRegisterForm(happyforms.ModelForm, PasswordMixin):
    passwords ...  
               
    recaptcha = captcha.fields.ReCaptchaField()

    ... irrelevent stuff ...

2. captcha.fields.ReCaptchaField() in zamboni/vendors (not shown on zamboni github), but it's on Mozilla's django-recaptcha
from django.conf import settings
from django import forms
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _

from recaptcha.client import captcha

from captcha.widgets import ReCaptcha

class ReCaptchaField(forms.CharField):

    default_error_messages = {
        'captcha_invalid': _(u'Invalid captcha')
    }

    def __init__(self, *args, **kwargs):
        self.widget = ReCaptcha
        self.required = True
        super(ReCaptchaField, self).__init__(*args, **kwargs)

    def clean(self, values):
        super(ReCaptchaField, self).clean(values[1])
        recaptcha_challenge_value = smart_unicode(values[0])
        recaptcha_response_value = smart_unicode(values[1])
        check_captcha = captcha.submit(recaptcha_challenge_value,
            recaptcha_response_value, settings.RECAPTCHA_PRIVATE_KEY, {})
        if not check_captcha.is_valid:
            raise forms.util.ValidationError(
                    self.error_messages['captcha_invalid'])
        return values[0]

3. from captcha.widgets import ReCaptcha
from django import forms
from django.utils.safestring import mark_safe
from django.conf import settings
from recaptcha.client import captcha

class ReCaptcha(forms.widgets.Widget):
    recaptcha_challenge_name = 'recaptcha_challenge_field'
    recaptcha_response_name = 'recaptcha_response_field'

    def render(self, name, value, attrs=None):
        use_ssl = False
        if 'RECAPTCHA_USE_SSL' in settings.__members__:
            use_ssl = settings.RECAPTCHA_USE_SSL
        return mark_safe(u'%s' %
                         captcha.displayhtml(settings.RECAPTCHA_PUBLIC_KEY,
                                             use_ssl=use_ssl))
     ...

4. from recaptcha.client (which is from Python's recaptcha client) import captcha
API_SSL_SERVER="https://api-secure.recaptcha.net"
API_SERVER="http://api.recaptcha.net"

def displayhtml (public_key,
                 use_ssl = False,
                 error = None):
    """Gets the HTML to display for reCAPTCHA

    public_key -- The public api key
    use_ssl -- Should the request be sent over ssl?
    error -- An error message to display (from RecaptchaResponse.error_code)"""

    error_param = ''
    if error:
        error_param = '&error=%s' % error

    if use_ssl:
        server = API_SSL_SERVER
    else:
        server = API_SERVER

    return """<script type="text/javascript" src="%(ApiServer)s/challenge?k=%(PublicKey)s%(ErrorParam)s"></script> # this src contains in-body script!!

<noscript>
  <iframe src="%(ApiServer)s/noscript?k=%(PublicKey)s%(ErrorParam)s" height="300" width="500" frameborder="0"></iframe><br />
  <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
  <input type='hidden' name='recaptcha_response_field' value='manual_challenge' />
</noscript>
""" % { 
        'ApiServer' : server,
        'PublicKey' : public_key,
        'ErrorParam' : error_param,
        }   

5. The src directs to (key varies for host, content is the same) https://www.google.com/recaptcha/api/challenge?k=6LcCCsYSAAAAACm9eF4n2ttYMU4TFbDMXMO-Bw2q


6. Which then directs to https://www.google.com/recaptcha/api/js/recaptcha.js that contains an in-body script:
document.write('<script>Recaptcha.widget = Recaptcha.$("recaptcha_widget_div"); Recaptcha.challenge_callback();<\/script>');

SOLVED!!!: click to see commit 2 break throughs, 1 question:

BT1: change into amo register's custom RecaptchaOptions to avoid in-body script.
BT2: have to allow setInterval like 'CSP_OPTIONS = ("eval-script",)'.
Q1: How come amo register does not have "setInterval blocked by CSP" problem even without CSP_OPTIONS?

BT1: In-body script is skipped with a custom RecaptchaOptions
as seen in Google recaptcha's js, note the javascript comma:
if (RecaptchaOptions.theme == "custom") {
    if (RecaptchaOptions.custom_theme_widget) Recaptcha.widget = Recaptcha.$(RecaptchaOptions.custom_theme_widget);
    Recaptcha.challenge_callback()
} else 
    document.write('<div id="recaptcha_widget_div" style="display:none"></div>'),
    document.write('<script>Recaptcha.widget = Recaptcha.$("recaptcha_widget_div"); Recaptcha.challenge_callback();<\/script>');
So the entire "else", which contains the in-body javascript, is skipped!

BT2: Make CSP policy allow setInterval
add CSP_OPTIONS = ("eval-script",) into settings.py
solves the "call to setInterval blocked by CSP" issue (seen in Firebug).

Q1: Why doesn't amo have this issue?

Solved: because amo has CSP_REPORT_ONLY, meaning that CSP is not actually enforced, but only reported!

---------

Have to get around setInterval(). CSP only blocks setInterval if it's called with a string argument.

So let's call it with a function!

Continued on this post.

How Add-ons Mozilla does ReCaptcha

Firefox add-ons register

Code comments are potentially mine.

1. def register in apps/users/views.py
@anonymous_csrf
def register(request):
    if request.user.is_authenticated():
        messages.info(request, _("You are already logged in to an account."))
        form = None
    elif request.method == 'POST':

        form = forms.UserRegisterForm(request.POST) # Always have recaptcha

        if form.is_valid(): # is_valid() does all the form clean()
            ... [save form stuff] ...
    else:
        form = forms.UserRegisterForm()
    return jingo.render(request, 'users/register.html', {'form': form, })

2. UserRegisterForm has ReCaptchaField. File: apps/users/forms.py
import captcha.fields

class UserRegisterForm(happyforms.ModelForm, PasswordMixin):
    passwords ...  
               
    recaptcha = captcha.fields.ReCaptchaField()

    ... irrelevent stuff ...

3. captcha.fields.ReCaptchaField() in zamboni/vendors (not shown on zamboni github), but it's on Mozilla's django-recaptcha
from django.conf import settings
from django import forms
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _

from recaptcha.client import captcha

from captcha.widgets import ReCaptcha

class ReCaptchaField(forms.CharField):

    default_error_messages = {
        'captcha_invalid': _(u'Invalid captcha')
    }

    def __init__(self, *args, **kwargs):
        self.widget = ReCaptcha
        self.required = True
        super(ReCaptchaField, self).__init__(*args, **kwargs)

    def clean(self, values):
        super(ReCaptchaField, self).clean(values[1])
        recaptcha_challenge_value = smart_unicode(values[0])
        recaptcha_response_value = smart_unicode(values[1])
        check_captcha = captcha.submit(recaptcha_challenge_value,
            recaptcha_response_value, settings.RECAPTCHA_PRIVATE_KEY, {})
        if not check_captcha.is_valid:
            raise forms.util.ValidationError(
                    self.error_messages['captcha_invalid'])
        return values[0]

Which, btw is exactly what I have for my ReCaptchaField. The ReCaptcha widget will ultimately introduce an in-body javascript.
Click to read more about ReCaptcha and In-Line Javascript / CSP

So the only difference in reCaptcha is how it's displayed on the html page. Let's investigate.

4. Register page template: apps/users/templates/users/register.html, taken from step 1 views.py
{% block js %}{% include("amo/recaptcha_js.html") %}{% endblock %}
...
{% if settings.RECAPTCHA_PRIVATE_KEY %}
    {{ recaptcha(form) }}
{% else %}
    <p>
       Welcome Robots, ReCaptcha has been disabled for your convenience.
       Spam at Wil.
     </p>
{% endif %}
The apps/amo/templates/amo/recaptcha_js.html has:
{% if request.user.is_anonymous() %}
  <script type="text/javascript" src="{{ settings.RECAPTCHA_URL }}"></script>
{% endif %}
where
# in settings.py
RECAPTCHA_PUBLIC_KEY = "blah"
RECAPTCHA_PRIVATE_KEY = "blah"
RECAPTCHA_URL = ('https://www.google.com/recaptcha/api/challenge?k=%s' %
                 RECAPTCHA_PUBLIC_KEY)

Unless you have the private key (which bots don't), you can see the recaptcha form.


5. def recaptcha() in apps/amo/helpers.py
Read about the inclusion_tag
@register.inclusion_tag('amo/recaptcha.html')
@jinja2.contextfunction
def recaptcha(context, form):
    d = dict(context.items())
    d.update(form=form)
    return d

6. recaptcha.html lives in apps/amo/templates/amo/recaptcha.hhtml"
{% from 'includes/forms.html' import required %}
<label for="recaptcha_response_field">
  {{ _('Are you human?') }} {{ required() }}
</label>
{% trans %}
  <p>
    Please enter <strong>both words</strong> below,
    <strong>separated by a space</strong>.
  </p>
  <p>
    If this is hard to read, you can
    <a href="#" id="recaptcha_different">try different words</a> or
    <a href="#" id="recaptcha_audio">listen to something</a> instead.
  </p>
{% endtrans %}
<div id="recaptcha_image"></div>
<p>
  <input type="text" name="recaptcha_response_field"
         id="recaptcha_response_field" size="30" />
</p>
<p><a href="#" id="recaptcha_help">{{ _("What's this?") }}</a></p>
{{ form.recaptcha.errors }}

7. div ids link to function in javascript here: media/js/zamboni/users.js
// Recaptcha
var RecaptchaOptions = { theme : 'custom' };

$('#recaptcha_different').click(function(e) {
    e.preventDefault();
    Recaptcha.reload();
});

$('#recaptcha_audio').click(function(e) {
    e.preventDefault();
    Recaptcha.switch_type('audio');
});

$('#recaptcha_help').click(function(e) {
    e.preventDefault();
    Recaptcha.showhelp();
});
These Recaptcha's functions are defined in Google's recaptcha.

Saturday, July 9, 2011

Find where a module is

Run python manage.py shell.
Import captcha.fields
help(captcha.fields) or captcha.__file__ or captcha.fields shown below
    In [3]: import captcha.fields
     
    In [4]: captcha.fields?
    Type:      module
    Base Class:     <type 'module'>
    String Form:    <module 'captcha.fields' from '/Users/jbalogh/dev/zamboni/vendor/src/django-recaptcha/captcha/fields.pyc'>
    Namespace:      Interactive
    File:      /Users/uname/dev/zamboni/vendor/src/django-recaptcha/captcha/fields.py
    Docstring:
        <no docstring> 

It's actually here: django-recaptcha already done before!!, not here. I wish I had know that the django-recaptcha existed before I did this.

Friday, July 8, 2011

Where to see CSP Policy

x-content-security-policy... policy-uri /path/to/policy

and then go to www.domain.name/path/to/poloice

How Django form calls clean() method

I was reading the Django docs on forms which says:
Validation of a Form is split into several steps ... [calls]
- [1] to_python()
- [2] validate()
- [3] run_validators()
- [4] clean()
- [5] clean_()


This is how these things work in the source code:

1. each field's clean() method takes care of the first 3 items

# src/django/django/forms/fields.py, comments mine

    class Field(object):
        ...
        def clean(self, value):
            """
            Validates the given value and returns its "cleaned" value as an
            appropriate Python object.

            Raises ValidationError for any errors.
            """
            value = self.to_python(value)    # [1]
            self.validate(value)             # [2]
            self.run_validators(value)       # [3]
            return value

2. aoeu

# src/django/django/forms/fields.py, comments mine

    class BaseForm(StrAndUnicode):
        ...
        def full_clean(self):
            """
            Cleans all of self.data and populates self._errors and
            self.cleaned_data.
            """
            self._errors = ErrorDict()
            if not self.is_bound: # Stop further processing.
                return
            self.cleaned_data = {}
            # If the form is permitted to be empty, and none of the form data has
            # changed from the initial data, short circuit any validation.
            if self.empty_permitted and not self.has_changed():
                return
            self._clean_fields()
            self._clean_form()
            self._post_clean()
            if self._errors:
                del self.cleaned_data

        def _clean_fields(self):
            for name, field in self.fields.items():
                # value_from_datadict() gets the data from the data dictionaries.
                # Each widget type knows how to retrieve its own data, because some
                # widgets split data over several HTML fields.
                value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
                try:
                    if isinstance(field, FileField):
                        initial = self.initial.get(name, field.initial)
                        # calls step 1's stuff
                        value = field.clean(value, initial) 
                    else:
                        value = field.clean(value)
                    self.cleaned_data[name] = value
                    if hasattr(self, 'clean_%s' % name):
                        value = getattr(self, 'clean_%s' % name)()
                        self.cleaned_data[name] = value
                except ValidationError, e:
                    self._errors[name] = self.error_class(e.messages)
                    if name in self.cleaned_data:
                        del self.cleaned_data[name]

... calls some alias ...
figure it out yourself

Thursday, July 7, 2011

Wednesday, July 6, 2011

When you can't onclick() in html

Change:

<button onclick="myFunction()">Click me</button>

To one of:
way 1 with .onclick with anonymous function
<body>
    <button id="myButton">Click me</button>
    <script>document.getElementById("myButton").onclick = function(){ stuff };</script>
</body>

way 2 with .onclick with named function
<body>
    <button id="myButton">Click me</button>
    <script>function myFunction() { stuff };
    document.getElementById("myButton").onclick = myFunction;</script>
</body>

way 3 with .addEventListener() with named function
<body>
    <button id="myButton">Click me</button>
    <script>document.getElementById("myButton").addEventListener('click', myFunction, false);</script>
</body>

Remember to put the addEventListener script after you have created the button. If you have to put it in the head, put the line of script inside a jQuery ready like
<!-- try not to do this though -->
<head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            document.getElementById("myButton").addEventListener('click', myFunction, false);
        }
</script>
</head> 

<body>
    <button id="checkButton">Click me</button>
</body>

But it's better practice to put js right before the closing of the body tag.



If your function has arguments...

Change:

<button onclick="myFunction('arg1')">Click me</button>

To
<body>
    <button id="myButton">Click me</button>
    <script>document.getElementById("myButton").addEventListener('click', function(){ myFunction('arg1') }, false);</script>
</body>

Where to put JS

I learned that JS is executed as soon as its parsed. So it's best to put <script> right before the </body> closing tag. For example: http://support.mozilla.com/en-US/home 

Tuesday, July 5, 2011

SQL Query for Top 500 Passwords

It's actually 499 because "0" was repeated. Source.

insert into table_name (password_column) values ("123456"),("porsche"),("firebird"),("prince"),("rosebud"),("password"),("guitar"),("butter"),("beach"),("jaguar"),("12345678"),("chelsea"),("united"),("amateur"),("great"),("1234"),("black"),("turtle"),("7777777"),("cool"),("pussy"),("diamond"),("steelers"),("muffin"),("cooper"),("12345"),("nascar"),("tiffany"),("redsox"),("1313"),("dragon"),("jackson"),("zxcvbn"),("star"),("scorpio"),("qwerty"),("cameron"),("tomcat"),("testing"),("mountain"),("696969"),("654321"),("golf"),("shannon"),("madison"),("mustang"),("computer"),("bond007"),("murphy"),("987654"),("letmein"),("amanda"),("bear"),("frank"),("brazil"),("baseball"),("wizard"),("tiger"),("hannah"),("lauren"),("master"),("xxxxxxxx"),("doctor"),("dave"),("japan"),("michael"),("money"),("gateway"),("eagle1"),("naked"),("football"),("phoenix"),("gators"),("11111"),("squirt"),("shadow"),("mickey"),("angel"),("mother"),("stars"),("monkey"),("bailey"),("junior"),("nathan"),("apple"),("abc123"),("knight"),("thx1138"),("raiders"),("alexis"),("pass"),("iceman"),("porno"),("steve"),("aaaa"),("fuckme"),("tigers"),("badboy"),("forever"),("bonnie"),("6969"),("purple"),("debbie"),("angela"),("peaches"),("jordan"),("andrea"),("spider"),("viper"),("jasmine"),("harley"),("horny"),("melissa"),("ou812"),("kevin"),("ranger"),("dakota"),("booger"),("jake"),("matt"),("iwantu"),("aaaaaa"),("1212"),("lovers"),("qwertyui"),("jennifer"),("player"),("flyers"),("suckit"),("danielle"),("hunter"),("sunshine"),("fish"),("gregory"),("beaver"),("fuck"),("morgan"),("porn"),("buddy"),("4321"),("2000"),("starwars"),("matrix"),("whatever"),("4128"),("test"),("boomer"),("teens"),("young"),("runner"),("batman"),("cowboys"),("scooby"),("nicholas"),("swimming"),("trustno1"),("edward"),("jason"),("lucky"),("dolphin"),("thomas"),("charles"),("walter"),("helpme"),("gordon"),("tigger"),("girls"),("cumshot"),("jackie"),("casper"),("robert"),("booboo"),("boston"),("monica"),("stupid"),("access"),("coffee"),("braves"),("midnight"),("shit"),("love"),("xxxxxx"),("yankee"),("college"),("saturn"),("buster"),("bulldog"),("lover"),("baby"),("gemini"),("1234567"),("ncc1701"),("barney"),("cunt"),("apples"),("soccer"),("rabbit"),("victor"),("brian"),("august"),("hockey"),("peanut"),("tucker"),("mark"),("3333"),("killer"),("john"),("princess"),("startrek"),("canada"),("george"),("johnny"),("mercedes"),("sierra"),("blazer"),("sexy"),("gandalf"),("5150"),("leather"),("cumming"),("andrew"),("spanky"),("doggie"),("232323"),("hunting"),("charlie"),("winter"),("zzzzzz"),("4444"),("kitty"),("superman"),("brandy"),("gunner"),("beavis"),("rainbow"),("asshole"),("compaq"),("horney"),("bigcock"),("112233"),("fuckyou"),("carlos"),("bubba"),("happy"),("arthur"),("dallas"),("tennis"),("2112"),("sophie"),("cream"),("jessica"),("james"),("fred"),("ladies"),("calvin"),("panties"),("mike"),("johnson"),("naughty"),("shaved"),("pepper"),("brandon"),("xxxxx"),("giants"),("surfer"),("1111"),("fender"),("tits"),("booty"),("samson"),("austin"),("anthony"),("member"),("blonde"),("kelly"),("william"),("blowme"),("boobs"),("fucked"),("paul"),("daniel"),("ferrari"),("donald"),("golden"),("mine"),("golfer"),("cookie"),("bigdaddy"),("king"),("summer"),("chicken"),("bronco"),("fire"),("racing"),("heather"),("maverick"),("penis"),("sandra"),("5555"),("hammer"),("chicago"),("voyager"),("pookie"),("eagle"),("yankees"),("joseph"),("rangers"),("packers"),("hentai"),("joshua"),("diablo"),("birdie"),("einstein"),("newyork"),("maggie"),("sexsex"),("trouble"),("dolphins"),("little"),("biteme"),("hardcore"),("white"),("0"),("redwings"),("enter"),("666666"),("topgun"),("chevy"),("smith"),("ashley"),("willie"),("bigtits"),("winston"),("sticky"),("thunder"),("welcome"),("bitches"),("warrior"),("cocacola"),("cowboy"),("chris"),("green"),("sammy"),("animal"),("silver"),("panther"),("super"),("slut"),("broncos"),("richard"),("yamaha"),("qazwsx"),("8675309"),("private"),("fucker"),("justin"),("magic"),("zxcvbnm"),("skippy"),("orange"),("banana"),("lakers"),("nipples"),("marvin"),("merlin"),("driver"),("rachel"),("power"),("blondes"),("michelle"),("marine"),("slayer"),("victoria"),("enjoy"),("corvette"),("angels"),("scott"),("asdfgh"),("girl"),("bigdog"),("fishing"),("2222"),("vagina"),("apollo"),("cheese"),("david"),("asdf"),("toyota"),("parker"),("matthew"),("maddog"),("video"),("travis"),("qwert"),("121212"),("hooters"),("london"),("hotdog"),("time"),("patrick"),("wilson"),("7777"),("paris"),("sydney"),("martin"),("butthead"),("marlboro"),("rock"),("women"),("freedom"),("dennis"),("srinivas"),("xxxx"),("voodoo"),("ginger"),("fucking"),("internet"),("extreme"),("magnum"),("blowjob"),("captain"),("action"),("redskins"),("juice"),("nicole"),("bigdick"),("carter"),("erotic"),("abgrtyu"),("sparky"),("chester"),("jasper"),("dirty"),("777777"),("yellow"),("smokey"),("monster"),("ford"),("dreams"),("camaro"),("xavier"),("teresa"),("freddy"),("maxwell"),("secret"),("steven"),("jeremy"),("arsenal"),("music"),("dick"),("viking"),("11111111"),("access14"),("rush2112"),("falcon"),("snoopy"),("bill"),("wolf"),("russia"),("taylor"),("blue"),("crystal"),("nipple"),("scorpion"),("111111"),("eagles"),("peter"),("iloveyou"),("rebecca"),("131313"),("winner"),("pussies"),("alex"),("tester"),("123123"),("samantha"),("cock"),("florida"),("mistress"),("bitch"),("house"),("beer"),("eric"),("phantom"),("hello"),("miller"),("rocket"),("legend"),("billy"),("scooter"),("flower"),("theman"),("movie"),("6666"),("please"),("jack"),("oliver"),("success"),("albert");

ReCaptcha on Django

These steps are a simplified/less-hassle version of marcofucci's directions. Thank you marcofucci for helping me setting up recaptcha initially.

1. Get your public and private recaptcha keys

2. Add keys to your settings: settings_local.py, or settings.py if you don't have your code in public
        RECAPTCHA_PUBLIC_KEY = 'insert your public key'
        RECAPTCHA_PRIVATE_KEY = 'insert your private key'

3. Download Python's Recaptcha-client
        1. cd to the directory, e.g. recaptcha-client-x.x.x
        2. python setup.py install

Click for alternative steps 3 and 4
3. pip or easy_install to get Python's Recaptcha-client

4. don't copy anything

5. all the same except the line
from your_app.captcha import submit, displayhtml
is changed into
from captcha import submit, displayhtml

4. Copy captcha.py to your app folder: cp recaptcha-client-x.x.x/recaptcha/client/captcha.py path_to_your_django/apps/your_app So now you should see that this exists: path_to_your_django/apps/your_app/captcha.py

5. Add ReCaptchaField into your forms Differences to marcofucci's step 4 are highlighted.
#add to path_to_your_django/apps/your_app/forms.py

from django.conf import settings
from django import forms
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext_lazy as _
from django.utils.safestring import mark_safe

from your_app.captcha import submit, displayhtml

class ReCaptchaField(forms.CharField):
    default_error_messages = {
        'captcha_invalid': _(u'Invalid captcha')
    }

    def __init__(self, *args, **kwargs):
        self.widget = ReCaptcha
        self.required = True
        super(ReCaptchaField, self).__init__(*args, **kwargs)

    def clean(self, values):
        super(ReCaptchaField, self).clean(values[1])
        recaptcha_challenge_value = smart_unicode(values[0])
        recaptcha_response_value = smart_unicode(values[1])
        check_captcha = submit(recaptcha_challenge_value,
            recaptcha_response_value, settings.RECAPTCHA_PRIVATE_KEY, {})
        if not check_captcha.is_valid:
            raise forms.util.ValidationError(self.error_messages['captcha_invalid'])
        return values[0]

class ReCaptcha(forms.widgets.Widget):
    recaptcha_challenge_name = 'recaptcha_challenge_field'
    recaptcha_response_name = 'recaptcha_response_field'

    def render(self, name, value, attrs=None):
        return mark_safe(u'%s' % displayhtml(settings.RECAPTCHA_PUBLIC_KEY))

    def value_from_datadict(self, data, files, name):
        return [data.get(self.recaptcha_challenge_name, None),
            data.get(self.recaptcha_response_name, None)]

6. Put it in my form! In contrast to, marcifucci's version, I use the built-in forms.
#add to path_to_your_django/apps/your_app/forms.py

from django.contrib.auth import forms as auth_forms

class UserCreationForm(auth_forms.UserCreationForm):
    recaptcha = ReCaptchaField(label="I'm a human")

class AuthenticationForm(auth_forms.AuthenticationForm):
    recaptcha = ReCaptchaField(label="I'm a human")

7. See my examples on github:
- step 4 copied in captcha.py
- step 5, 6 forms.py

8. If you have more questions, feel free to email me.

Sunday, July 3, 2011

Django Authentication / Login

It's a mess to learn this. The best way is to follow someone's example and pick out pieces (login, register, logout) that you need.
Examples:
- TODO: insert my simple example here
zabmoni's users


Tutorial:
Django Book's big chapter on Authentication, Users and Registration. A little bit of everything.  I would consider this to be a good intro, if you have the patience to read through it all thoroughly.


Django User Authentication
- user fields
user methods
built-in forms
- group and permission stuff.


Django Sessions
important SESSIONS settings (see this blog post about my bad session experience)
session (dictionary) methods

---

 The Django Book's Forms.

Solved - Django "Your Web browser doesn't appear to have cookies enabled."

If you get this error message on your Django login-page:


     Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in.

and you have made sure that your browser DOES have cookies enabled, then you should check your settings.py's SESSION_* configurations very carefully.

Maybe you have the SESSION_COOKIE_SECURE set to True accidentally when you don't have SSL.
Maybe you have the SESSION_COOKIE_DOMAIN set to a domain that's actually not your domain.

#settings.py

# If not SSL, should be false
SESSION_COOKIE_SECURE = False
# Check other SESSION_* settings too

bashrc improvements for git

show which brach on
git auto complete

PS1='${debian_chroot:+($debian_chroot)}\[\033[01;34m\]\u@\h\[\033[00m\]:\[\033[01;33m\]\t\[\033[ 00m\]:\[\033[01;32m\]\w\[\033[00m\]$(__git_ps1 " (%s)")\$ '


source /usr/local/etc/bash_completion.d/git-completion.bash

Friday, July 1, 2011

Google Prettify

Languages from stack overflow.

Put on blogger.

PHP concat variable name with str/string

In PHP, concatenate variable names with strings by using curly brackets {}.

The Shorter version
<?php
       // setting every $nvar* to ":)"
       $nameArray = array("Alice", "Bob", "Charlie");
       foreach ($nameArray as $name) {
           ${ "nvar" . $name } = ":)"; 
       }
?>

and

The Longer version
<?php
       // setting every $nvar* to ":)"
       $nameArray = array("Alice", "Bob", "Charlie");
       foreach ($nameArray as $name) {
           $nameVar = "nvar" . $name;
           ${ $nameVar } = ":)"; 
       }   
?>

are the same as

The Brute-force version
<?php
       // setting every $nvar* to ":)"
       $nvarAlice = ":)";
       $nvarBob = ":)";
       $nvarCharlie = ":)";
?>

Read documentations here.