Ross Wan's World!

Python, Ajax, PHP and Linux.

批量修改 Firefox 扩展的最大版本号

Posted by Ross Wan 于 2011/08/26

本人一直都是 Firefox Nightbuild 版本的”忠实”使用者,因为可以提前使用最新的功能,性能也有很大的提升,还可以帮 Mozilla 测试新版本,提交 Bugs 报告.尤其现在的 Firefox 9, 在内存方面有很的改进,值得期待.

回归正题, Firefox Nightbuild 版有它的好处, 问题是很多扩展未能兼容, 但有一部分扩展是兼容的,只是它支持的最大版本号未修改过来,这样,就需要人工手动修改其扩展(xpi文件)的install.rdf. (当然,除了修改最大版本号,还有很多方法可以让其兼容,网上都有介绍)

下面的 Python 脚本可以达到批量修改xpi文件的目的:

#!bin/python3
# coding=utf8

import re, zipfile, os, sys

maxversion = 100
ff_maxversion_reg = re.compile(br'(ec8030f7-c20a-464f-9b0e-13a3a9e97384.*?em:maxVersion.*?)([^>< ="/]+)', re.S+re.I)

if __name__ == '__main__':
    if len(sys.argv) > 1:
        maxversion = int(sys.argv[1])
    print('Target Maxversion: %s\n' % maxversion)
    sys.exit()

    for filename in os.listdir():
        print('%s ' % filename, end='')
        if os.path.isdir(filename) or not filename.lower().endswith('.xpi'):
            print('skip.')
            continue
        zin = zipfile.ZipFile(filename)
        rdf = zin.read('install.rdf')
        version = 0
        for item in ff_maxversion_reg.finditer(rdf):
            match_obj = re.search(br'\d+', item.groups()[1])
            if match_obj and int(match_obj.group()) > version:
                version = int(match_obj.group())
        if version >= maxversion:
            zin.close()
            print('skip.')
            continue

        zout = zipfile.ZipFile('new.xpi','w')
        rdf = ff_maxversion_reg.sub(br'\g<1>'+ str(maxversion).encode('utf8'), rdf)
        zout.writestr('install.rdf', rdf)
        for item in zin.infolist():
            if item.filename.lower() == 'install.rdf':
                continue
            else:
                buffer = zin.read(item.filename)
                zout.writestr(item, buffer)
        zin.close()
        zout.close()
        os.remove(filename)
        os.rename('new.xpi', filename)
        print('done!')

将脚本放于 Firefox 配置文件夹的 extensions 目录下运行即可.也可以带1个参数运行,用于指定目标最大版本号,如:

python3 xpi_rdf_batch.py 200

值得注意的是,目前它仅可以修改 xpi 文件, 对于 unpack 的扩展不能修改.

Have fun :)

Posted in Python | Tagged: , , , , , , | 7 Comments »

The Python Challenge Lv.6

Posted by Ross Wan 于 2011/08/25

Lv.6

打开第6关的网页,显示的是一张裤拉链的图片,”拉链”???第一时间,猜想到的是 Python 的 zip 内建方法、zipfile 内建模块,还有就是 zip 格式的文件。

查看网页的源文件,没什么可疑,尝试将网址最后的“html”改为“zip”,下载到“channel.zip”这个压缩文件 :) 用 7-zip 解压缩,发现里面有910个文本文件,一个 readme.txt 文件:

welcome to my zipped list.

hint1: start from 90052
hint2: answer is inside the zip

其它文件的内容大致如下:

Next nothing is xxxxx

这有点像第4关。先验证下那些文件的内容是否一致,是否有一个特殊的(或者答案就直接在那文件里呢):

import re, os

if __name__ == '__main__':
    for filename in os.listdir('channel'):
        filepath = os.path.join('channel', filename)
        if os.path.isfile(filepath) and re.match(r'^\d+\.txt', filename):
            f = open(filepath)
            content = f.read()
            f.close()
            if not re.match(r'^Next nothing is \d+', content):
                print('File: %s\nContent: %s' % (filename, content))

显示如下内容:

File: 46145.txt
Content: Collect the comments.

发现 “46145.txt”文件的内容是不一样的。“注释”?再用 z-zip 打开 channel.zip 这个压缩文件,查看其注释栏,的确压缩包里的部分文件是带注释的。再结合 readme.txt 文件的提示,将注释按顺序打印出来:

#!bin/python3
# coding=utf8

import re, zipfile

if __name__ == '__main__':
    target = '90052'
    z = zipfile.ZipFile('channel.zip')
    while 1:
        target_file = '%s.txt' % target
        print(z.getinfo(target_file).comment.decode('ascii'), end='')
        f = z.open(target_file)
        match_obj = re.match(r'^Next nothing is (\d+)',f.read().decode('ascii'))
        f.close()
        if match_obj:
            target = match_obj.groups()[0]
        else:
            break
    z.close()

显示如下图案:

****************************************************************
****************************************************************
**                                                            **
**   OO    OO    XX      YYYY    GG    GG  EEEEEE NN      NN  **
**   OO    OO  XXXXXX   YYYYYY   GG   GG   EEEEEE  NN    NN   **
**   OO    OO XXX  XXX YYY   YY  GG GG     EE       NN  NN    **
**   OOOOOOOO XX    XX YY        GGG       EEEEE     NNNN     **
**   OOOOOOOO XX    XX YY        GGG       EEEEE      NN      **
**   OO    OO XXX  XXX YYY   YY  GG GG     EE         NN      **
**   OO    OO  XXXXXX   YYYYYY   GG   GG   EEEEEE     NN      **
**   OO    OO    XX      YYYY    GG    GG  EEEEEE     NN      **
**                                                            **
****************************************************************
 **************************************************************

显而易见,下一关的网址正是:http://www.pythonchallenge.com/pc/def/hockey.html

且慢,别高兴太早~~~打开上面的网址,显示:

it’s in the air. look at the letters.

“这仍然是个谜,注意那些字母”,原来谜还未解完呢,留意“HOCKEY”各由什么字母组成——oxygey。答案终于出来了: http://www.pythonchallenge.com/pc/def/oxygen.html

Have fun :)

Posted in Python | Tagged: , , | Leave a Comment »

The Python Challenge Lv.5

Posted by Ross Wan 于 2011/08/24

Lv.5

打开第5关的网页,显示的是一个山丘的图片,提示”pronounce it”???完全没有头绪.再看看网页的源代码,发现一个”可疑”的标签:

<peakhell src=”banner.p”/>

下载到 banner.p 这个文件,用文本编辑器打开,又是一堆字符,似有似无规律的字符.再看看网页源代码里的一行注释:

<!– peak hell sounds familiar ? –>

peak hell 的发音似什么?完全没有头绪……最后,Google到一点提示,确是无奈之举:< 原来关键是 pickle,它的发音跟 ‘peak hell’ 有点相似.真是晕倒~~~既然有这个关键的提示,下面就容易得多了:

import pickle

if __name__ == '__main__':
    f = open('banner.p', 'rb')
    obj = pickle.load(f)
    print('Objcet type: %s\n\n' %type(obj))
    print(obj)
    f.close()

首先,取得的对象是一个 list,而list的元素是由二元表列组成,而且,二元表列的第一个元素是” “或者”#”,第二个元素是数字.可猜测这是一个打印列表:

import pickle

if __name__ == '__main__':
    f = open('banner.p', 'rb')
    obj = pickle.load(f)
    f.close()
    new_file = open('new_file.txt', 'w')
    for line in obj:
        new_file.write(''.join([x*y for x,y in line]))
        new_file.write('\n')
    new_file.close()

上面的代码会将打印的字符写入 “new_file.txt” 这个文件里,不直接显示在系统 console 里主要是因为因某些 console 会自动断行,而显示不到最终的结果.

用编辑器打开(记得关闭编辑器的自动换行),会出现一个漂亮的图形,结果显而易见:

                                                                                              
              #####                                                                      #####
               ####                                                                       ####
               ####                                                                       ####
               ####                                                                       ####
               ####                                                                       ####
               ####                                                                       ####
               ####                                                                       ####
               ####                                                                       ####
      ###      ####   ###         ###       #####   ###    #####   ###          ###       ####
   ###   ##    #### #######     ##  ###      #### #######   #### #######     ###  ###     ####
  ###     ###  #####    ####   ###   ####    #####    ####  #####    ####   ###     ###   ####
 ###           ####     ####   ###    ###    ####     ####  ####     ####  ###      ####  ####
 ###           ####     ####          ###    ####     ####  ####     ####  ###       ###  ####
####           ####     ####     ##   ###    ####     ####  ####     #### ####       ###  ####
####           ####     ####   ##########    ####     ####  ####     #### ##############  ####
####           ####     ####  ###    ####    ####     ####  ####     #### ####            ####
####           ####     #### ####     ###    ####     ####  ####     #### ####            ####
 ###           ####     #### ####     ###    ####     ####  ####     ####  ###            ####
  ###      ##  ####     ####  ###    ####    ####     ####  ####     ####   ###      ##   ####
   ###    ##   ####     ####   ###########   ####     ####  ####     ####    ###    ##    ####
      ###     ######    #####    ##    #### ######    ###########    #####      ###      ######

可见,下一关的网址是: http://www.pythonchallenge.com/pc/def/channel.html

Have fun :)

Posted in Python, Uncategorized | Tagged: , , | Leave a Comment »

The Python Challenge Lv.4

Posted by Ross Wan 于 2011/08/22

Lv.4

打开第4关的网址,得到如下内容:

linkedlist.php

将网址改为 http://www.pythonchallenge.com/pc/def/linkedlist.php, 再打开,终于进入到第4关,看到一张”木偶锯木”的图片,点击它,进入到 http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=12345 页面显示:

and the next nothing is 44827

根据页面提示,将网址最后的nothing参数改为 44827, 打开http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=44827, 又得到提示:

and the next nothing is 45439

再改网址的nothing参数吧, http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=45439,这次终于得到稍有不同的提示了:

Your hands are getting tired and the next nothing is 94485

这算是安慰的说话吗?想一想,这样重复又重复的工作,不正是程序应做的事情吗?!

#!bin/python3
# coding=utf8

import re, urllib.request

if __name__ == '__main__':
    nothing = '94485'
    while 1:
        response = urllib.request.urlopen('http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s' % nothing)
        content = response.read().decode('ascii')
        response.close()
        print(content)
        match_obj = re.match(r'^and the next nothing is (\d+)', content)
        if match_obj:
            nothing = match_obj.groups()[0]
        else:
            break

经过若干次抓取页面之后停住了,提示:

and the next nothing is 16044
Yes. Divide by two and keep going.

意思就是除2再继续,晕~~将上面脚本的 nothing 改为’8022’再次运行.不久,页面又停住了:

and the next nothing is 82682
There maybe misleading numbers in the
text. One example is 82683. Look only for the next nothing and the next nothing
is 63579

提示错误,要从63579再次运行,再次晕倒.那再将上面的脚本中的nothing改为’63579′

再次运行…

and the next nothing is 66831

peak.html

皇天不负有心人,都不知运行多长时间了,终于显示下一关的关键字,真是想哭呀~~~Lv.5:http://www.pythonchallenge.com/pc/def/peak.html

Have fun :~?

Posted in Python | Tagged: , , , | 1 Comment »

The Python Challenge Lv.3

Posted by Ross Wan 于 2011/08/20

Lv.3

One small letter, surrounded by EXACTLY three big bodyguards on each of its sides.

这关跟上一关一样,也是要解密网页源代码里的那一堆字符注释.根据上面的提示,要找出一些特殊的小写字母,它必须左右两边当且只有3个大字母,例如: bXXXaXXXc,字母a就符合要求.利用正则查找出这些字母来:

import re

if __name__ == '__main__':
    with open('mess.txt') as f:
        target_chars = []
        for line in f:
            target_chars.extend(re.findall(r'(?<=[^A-Z][A-Z]{3})[a-z](?=[A-Z]{3}[^A-Z])', '^'+line))
        target = ''.join(target_chars)
        print('Target characters: %s' % target)
        print('Next url: http://www.pythonchallenge.com/pc/def/%s.html' % target)
        f.close()

‘^’+line 在每行开头加上字符”^”(或者其它非大写字母),是为了让正则表达式匹配这个特殊情况,就是行字符串开头如这样:XXXaXXXb…,如果不在行开头加上一个非大写字符,上面的正则表达式是配置不到a字符的.

另外,在论坛区里,有人贴出这样的正则表达式:

r'([^A-Z][A-Z]{3}([a-z])[A-Z]{3}[^A-Z]’

但它会漏掉一些应匹配的小写字符,例如: ‘aXXXbXXXcXXXd’, 上面的正则表达式只匹配到’b’,没有匹配到’c’!(虽然对于本关,它一样可以得出正确的结果 :<)

运行脚本,得到如下结果:

Target characters: linkedlist

Next url: http://www.pythonchallenge.com/pc/def/linkedlist.html

得到下一关的网址: http://www.pythonchallenge.com/pc/def/linkedlist.html

Have fun :>

Posted in Python, Uncategorized | Tagged: , , | Leave a Comment »

VIM: _vimrc for windows

Posted by Ross Wan 于 2011/08/20

用 gVim 好几年时间了,一直在改动其配置文件 _vimrc.现贴贴最新自用的 _vimrc.它是由称为史上最强的 _vimrc 文件(由 amix 编写修护)修改而来.解决了在 Windows 下设置 enc=utf8 后 gVim 菜单乱码的问题.

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" 编码设置,同时解决 Windows 下,当设置enc=utf8时,gvim菜单乱码问题
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set encoding=utf-8
set langmenu=zh_CN.UTF-8
language message zh_CN.UTF-8
set fenc=utf8
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
let $LANG = 'zh_CN.UTF-8'
source $VIMRUNTIME/delmenu.vim
source $VIMRUNTIME/menu.vim
set nobomb

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" MS-Windows 操作方式的剪贴板
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
source $VIMRUNTIME/mswin.vim

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => General
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! MySys()
    return "windows"
endfunction

" set nocompatible

" Sets how many lines of history VIM has to remember
set history=100

" Enable filetype plugin
filetype plugin on
filetype indent on

" Set to auto read when a file is changed from the outside
set autoread

" With a map leader it's possible to do extra key combinations
" like <leader>w saves the current file
let mapleader = ","
let g:mapleader = ","

" Fast saving
nmap <leader>w :w!<cr>
" Fast editing of the .vimrc
map <leader>e :e! D:\Program\ Files\Vim\_vimrc<cr>
" When vimrc is edited, reload it
autocmd! bufwritepost _vimrc source D:\Program\ Files\Vim\_vimrc

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => VIM user interface
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Set 3 lines to the curors - when moving vertical..
set so=3
set wildmenu "Turn on WiLd menu
set ruler "Always show current position
set cmdheight=2 "The commandbar height
set hid "Change buffer - without saving

" Set backspace config
set backspace=eol,start,indent
set whichwrap+=<,>,h,l

" Set serching
set ignorecase "Ignore case when searching
set smartcase
set hlsearch "Highlight search things
set incsearch "Make search act like search in modern browsers
set magic "Set magic on, for regular expressions
set showmatch "???Show matching bracets when text indicator is over them
set mat=2 "How many tenths of a second to blink
set nolazyredraw "???Don't redraw while executing macros 

" No sound on errors
set noerrorbells
set novisualbell
set t_vb=
set tm=500

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Colors and Fonts
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
syntax enable "Enable syntax hl

" Set font according to system
if MySys() == "mac"
  set gfn=Menlo:h14
  set shell=/bin/bash
elseif MySys() == "windows"
  set gfn=Bitstream\ Vera\ Sans\ Mono:h12
elseif MySys() == "linux"
  set gfn=Monospace\ 10
  set shell=/bin/bash
endif

if has("gui_running")
 "set guioptions-=T
  set t_Co=256
  set background=dark
  colorscheme darkdevel
  set nu
else
  colorscheme darkdevel
  set background=dark
  set nonu
endif

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Files, backups and undo
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Turn backup off, since most stuff is in SVN, git anyway...
set nobackup
set nowb
set noswapfile

"Persistent undo
try
    if MySys() == "windows"
      set undodir=g:\\Temp
    else
      set undodir=~/.vim_runtime/undodir
    endif
    set undofile
catch
endtry

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Text, tab and indent related
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set expandtab
set shiftwidth=4
set tabstop=4
set smarttab
"
" 智能换行(不在单词中间断行。 设置了这个选项后, 如果一行文字非常长, 无法在一行内显示完的话, 它会在单词与单词间的空白处断开, 尽量不会把一个单词分成两截放在两个不同的行里)
set lbr
set tw=500

set ai "Auto indent
set si "Smart indet
set wrap "Wrap lines

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Moving around, tabs and buffers
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Map space to / (search) and c-space to ? (backgwards search)
map <space> /
map <c-space> ?
map <silent> <leader><cr> :noh<cr>

" Smart way to move btw. windows
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l

" Close the current buffer
map <leader>bd :Bclose<cr>

" Close all the buffers
map <leader>ba :1,300 bd!<cr>

" Use the arrows to something usefull
map <right> :bn<cr>
map <left> :bp<cr>

" Tab configuration
map <leader>tn :tabnew<cr>
map <leader>te :tabedit
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove 

" When pressing <leader>cd switch to the directory of the open buffer
map <leader>cd :cd %:p:h<cr>

command! Bclose call <SID>BufcloseCloseIt()
function! <SID>BufcloseCloseIt()
   let l:currentBufNum = bufnr("%")
   let l:alternateBufNum = bufnr("#")

   if buflisted(l:alternateBufNum)
     buffer #
   else
     bnext
   endif

   if bufnr("%") == l:currentBufNum
     new
   endif

   if buflisted(l:currentBufNum)
     execute("bdelete! ".l:currentBufNum)
   endif
endfunction

" Specify the behavior when switching between buffers
try
  set switchbuf=usetab
  set stal=2
catch
endtry

""""""""""""""""""""""""""""""
" => Statusline
""""""""""""""""""""""""""""""
" Always hide the statusline
set laststatus=2

" Format the statusline
set statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{CurDir()}%h\ \ \ Line:\ %l/%L:%c

function! CurDir()
    let curdir = substitute(getcwd(), '/Users/amir/', "~/", "g")
    return curdir
endfunction

function! HasPaste()
    if &paste
        return 'PASTE MODE  '
    else
        return ''
    endif
endfunction

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Parenthesis/bracket expanding
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
vnoremap $1 <esc>`>a)<esc>`<i(<esc>
vnoremap $2 <esc>`>a]<esc>`<i[<esc>
vnoremap $3 <esc>`>a}<esc>`<i{<esc>
vnoremap $$ <esc>`>a"<esc>`<i"<esc>
vnoremap $q <esc>`>a'<esc>`<i'<esc>
vnoremap $e <esc>`>a"<esc>`<i"<esc>

" Map auto complete of (, ", ', [
inoremap $1 ()<esc>i
inoremap $2 []<esc>i
inoremap $3 {}<esc>i
inoremap $4 {<esc>o}<esc>O
inoremap $q ''<esc>i
inoremap $e ""<esc>i
inoremap $t <><esc>i

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => General Abbrevs
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
iab xdate <c-r>=strftime("%d/%m/%y %H:%M:%S")<cr>

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Editing mappings
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Remap VIM 0
map 0 ^

"Move a line of text using ALT+[jk] or Comamnd+[jk] on mac
nmap <M-j> mz:m+<cr>`z
nmap <M-k> mz:m-2<cr>`z
vmap <M-j> :m'>+<cr>`<my`>mzgv`yo`z
vmap <M-k> :m'<-2<cr>`>my`<mzgv`yo`z

if MySys() == "mac"
  nmap <D-j> <M-j>
  nmap <D-k> <M-k>
  vmap <D-j> <M-j>
  vmap <D-k> <M-k>
endif

"Delete trailing white space, useful for Python ;)
func! DeleteTrailingWS()
  exe "normal mz"
  %s/\s\+$//ge
  exe "normal `z"
endfunc
autocmd BufWrite *.py :call DeleteTrailingWS()

set guitablabel=%t

""""""""""""""""""""""""""""""
" => Python section
""""""""""""""""""""""""""""""
let python_highlight_all = 1
au FileType python syn keyword pythonDecorator True None False self

au BufNewFile,BufRead *.jinja set syntax=htmljinja
au BufNewFile,BufRead *.mako set ft=mako

au FileType python inoremap <buffer> $r return
au FileType python inoremap <buffer> $i import
au FileType python inoremap <buffer> $p print
au FileType python inoremap <buffer> $f #--- PH ----------------------------------------------<esc>FP2xi
au FileType python map <buffer> <leader>1 /class
au FileType python map <buffer> <leader>2 /def
au FileType python map <buffer> <leader>C ?class
au FileType python map <buffer> <leader>D ?def 

""""""""""""""""""""""""""""""
" => JavaScript section
"""""""""""""""""""""""""""""""
"au FileType javascript call JavaScriptFold()
au FileType javascript setl fen
au FileType javascript setl nocindent

au FileType javascript imap <c-t> AJS.log();<esc>hi
au FileType javascript imap <c-a> alert();<esc>hi

au FileType javascript inoremap <buffer> $r return
au FileType javascript inoremap <buffer> $f //--- PH ----------------------------------------------<esc>FP2xi

function! JavaScriptFold()
    setl foldmethod=syntax
    setl foldlevelstart=1
    syn region foldBraces start=/{/ end=/}/ transparent fold keepend extend

    function! FoldText()
    return substitute(getline(v:foldstart), '{.*', '{...}', '')
    endfunction
    setl foldtext=FoldText()
endfunction

""""""""""""""""""""""""""""""
" => Vim grep
""""""""""""""""""""""""""""""
let Grep_Skip_Dirs = 'RCS CVS SCCS .svn generated'
set grepprg=/bin/grep\ -nH

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => MISC
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Remove the Windows ^M - when the encodings gets messed up
noremap <Leader>m mmHmt:%s/<C-M><cr>//ge<cr>'tzt'm

"Quickly open a buffer for scripbble
map <leader>q :e ~/buffer<cr>
au BufRead,BufNewFile ~/buffer iab <buffer> xh1 ===========================================
map <leader>pp :setlocal paste!<cr>
map <leader>bb :cd ..<cr>

au BufWinLeave ?* mkview
au BufWinEnter ?* silent loadview

set winaltkeys=no
map <A-n> :tabnew<CR>
map <A-.> :tabn<CR>
map <A-,> :tabp<CR>
map <A-c> :close<CR>
map <F2> <Esc><Esc> :NERDTree
map <F3> <Esc><Esc> :NERDTreeClose<CR>
map <F4> :TlistToggle<CR>
" F9 自动删除行末的空格
map <F9> :%s/\s\+//<CR>

Posted in gVim | Tagged: , , , , , | 1 Comment »

The Python Challenge Lv.2

Posted by Ross Wan 于 2011/08/19

Lv.2

recognize the characters. maybe they are in the book, but MAYBE they are in the page source.

上面是第2关的提示.看看这网页的源代码,就知道究竟什么回事.网面源码最后有一大段的注释,一堆的标点符号.提示说”recognize the characters”,就是说这堆标点符号里有有意义的字母,推理方向对了就行.下面是 Python 代码,用正则的方式查找字母出来:

import re

if __name__ == '__main__':
    with open('mess1.txt') as f:
        mess = f.read()
        f.close()
        target = ''.join(re.findall(r'[a-zA-Z0-9]', mess, re.S))
        print('Target characters: %s' % target)
        print('Next url: http://www.pythonchallenge.com/pc/def/%s.html' % target)

mess.txt 是那源代码标点符号注释复制下来保存的文件.下面是输出结果:

Target characters: equality
Next url: http://www.pythonchallenge.com/pc/def/equality.html

可见,下一关的网址就是 http://www.pythonchallenge.com/pc/def/equality.html


Have fun :)

Posted in Python | Tagged: , , , | Leave a Comment »

利用 CSS 实现标签 pre 内容自动换行

Posted by Ross Wan 于 2011/08/19

兼容 IE ,Firefox, Chrome 等浏览器 :)

pre{
    display: block;
    overflow: auto;
    word-wrap:break-word;
    white-space: pre-wrap;
}

Posted in CSS | Tagged: , , , | 1 Comment »

reStructuredText: 自动处理 rst2html

Posted by Ross Wan 于 2011/08/19

因为经常都会使用到 reStructuredText,文档,Blog…等等.所以写了个自动处理 rst2html 的脚本myrst2html.py(Python 3.2):

#!/bin/python3
# coding=utf8

from docutils.core import publish_string
import sys, os, getopt

def get_last_modified_rst(path='.'):
    real_path = os.path.split(path)[0]
    last_modified_rst = ''
    last_modified = -1
    for rst in (x for x in os.listdir(path) if os.path.isfile(os.path.join(real_path,x)) and os.path.splitext(x)[1].lower()=='.rst'):
        rst = os.path.join(real_path, rst)
        rst_modified = os.path.getmtime(rst)
        if rst_modified > last_modified:
            last_modified = rst_modified
            last_modified_rst = rst
    return  last_modified_rst

def rst2html(rst_filename, target_filename=None):
    print(rst_filename)
    rst_file = open(rst_filename)
    print(1)
    source = rst_file.read()
    print(2)
    rst_file.close()
    print('Source: %s' % rst_filename)
    target_filename = target_filename and target_filename or os.path.splitext(rst_filename)[0]+'.html'
    target_file = open(target_filename, 'w')
    print('Target: %s' % target_filename)
    target_html = publish_string(
        source=source,
        writer_name='html',
        settings_overrides={'output_encoding': 'unicode'}
    )
    target_file.write(target_html)
    target_file.close()
    print('Done!')

def main():
    try:
        optlist, args = getopt.getopt(sys.argv[1:], '')
        rst_filename, target_filename = None, None
        if not args:
            last_rst = get_last_modified_rst()
            rst_filename = last_rst
        else:
            rst_filename, target_filename = (args + [None])[:2]
        rst2html(rst_filename, target_filename)
    except Exception as e:
        print(e)

if __name__ == '__main__':
    main()

执行方式:

python3 myrst2html.py [rst_file] [target_file]

参数 rst_file 和 target_file 分别是要转换的 rst 文件和转换的目标 html 文件.如果没提供 target_file, 则自动以 rst_file 命名目标文件;如果两个参数都不提供,则自动查找当前目录最后修改的 rst 文件,然后进行转换 :>

Have fun :)

Posted in Python, Uncategorized | Tagged: , , , | Leave a Comment »

The Python Challenge Lv.1

Posted by Ross Wan 于 2011/08/18

Lv.1

根据图片:

K->M

O->Q

E->G

可以猜到规律,就是将字母右移2位进行影射解密.字符影射翻译,Python str本身就提供了这方法: translate.

import string

mess = “””g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr’q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj. “””

translation = mess.translate(str.maketrans(string.ascii_letters, string.ascii_lowercase[2:]+’ab’+string.ascii_uppercase[2:]+’AB’))

print(translation)

得到以下译文:

“i hope you didnt translate it by hand. thats what computers are for. doing it in by hand is inefficient and that’s why this text is so long. using string.maketrans() is recommended. now apply on the url. “

根据译文的提示,对网页的 url 进行上面的字符影射翻译:

map -> ocr

得到下一关地址:

http://www.pythonchallenge.com/pc/def/ocr.html

Python 字符串提供的 translate 是相当方便的,假如不用这内置的方法,也是有很多办法解决的,毕竟这是有规律的字符影射:

for char in mess:
    print(ord(‘a’)<=ord(char)<=ord(‘z’) and chr((ord(char)+2-ord(‘a’))%26+ord(‘a’)) or char, end=”)

:) 这样这可以打印出上面的译文.

Have fun~~

Posted in Python, Uncategorized | Tagged: , , , | Leave a Comment »