2007年03月23日

在公司,同事之间交流一直使用飞鸽,自从转到mac下,osx版的飞鸽一直存在乱码问题而无法使用。本寄希望能google到国人改好的版本,怎奈一直未果。
今天下午,用了点时间研究了一下源码,最终解决了这个问题,现在终于可以在mac下完全无障碍地使用飞鸽了。
由于原始的代码组织的非常好,因此即使对于我这个已经有10年没接触过C的人,发现需要改动的地方也不是什么难事。不过由于从来没有使用过xcode环境,而且源代码又是在旧环境下开发的,因此如何让代码成功编译结果成了最大的难题。

说实话,xcode真的很不错,很难想象是随系统免费的。

程序下载

ps: 我在osx版下给windows下的中文版飞鸽发lock的信息,win下版本只要cancle两下就可以读取了,而win发给osx下的lock信息,osx始终提示密码错,不知到问题在那里,有时间再看看吧。

新修正日志乱码问题

2005年12月29日

呵呵,又是后放一放还真有效果。
  中午吃过饭决定再看一下这个已经有20几天没动过的问题,没想到2分钟就搞定了。
  15题从编程角度来说没有什么特别的,通过分析给出的线索,通过计算可以获得一个年份列表(符合条件的不多)。剩下的就是考验搜索技巧以及耐心的的问题了。
  给后来这一些小提示:
  1、看看日历上的该年份有什么特别之处(注意看看右下角另一个月的信息)
  2、被抹掉的可能并不是一位数而是两位数
  3、最终的年份结果距离今天挺远的
  4、他很有名气是一位艺术家
  不能再说了,否则就太简单了。

2005年12月21日

自从2天前update django的新代码后出现了一个很大的问题。当使用django内置的web 服务机制后会不断的重起。这个问题xiaoping.tang也发现了,并和我一同研究,希望找出其中的答案。
  值得注意的事,如此大的一个bug竟然在django论坛上没人提出来过。到底是我们自己的问题,还是django的代码真的出错了呢?
  研究发现,django将需要监视的文件mtime数据都写入字典中,通过比较mtime是否发生改变而产生重起动作。在没有任何改变的情况下,当进行一次访问后,django代码通过stat.st_mktime获得的数据确发生了变化,这个起初让我完全无法理解。
  不过,如果仔细查看以下变化的情况就会发现其中的奥秘。 

time.ctime(1135012483) 'Tue Dec 20 01:14:43 2005' time.ctime(1134983683) 'Mon Dec 19 17:14:43 2005'


  相差八个小时:)
  再通过代码分析,应该是环境变量里的TZ设置没有被认可。
  将settings.py中的TIME_ZONE = ‘Asia/Shanghai PRC’ 改成 TIME_ZONE = ‘CCT’ 即可。
  看来django改变了tz的判断,只支持最基本的tz描述了。呜呼哀哉。

2005年12月06日

python-cn上一个朋友提出的问题,自己以前也没想过,恰巧django中有一个middleware是做gzip处理的,看了一下它的代码,了解到可以通过StringIO的方式,将字符串以文件的形式来进行处理。
StringIO应该是一个非常有用的模块,因为很多函数都是只支持文件的,使用它后就没有问题了。



import urllib2
import cStringIO
import gzip

f=urllib2.urlopen('http://www.gzip.com/aaaxxx') #gzip url
zbuf=cStringIO.StringIO(f.read())
print gzip.GzipFile(fileobj=zbuf,mode='rb').read()



2005年12月05日

这关如果单纯从编程角度来说可以说没有任何深奥的技巧。只用了很短的时间,我就用获取的线索写好的程序,并且获得了时间列表。用基本的判断尝试,我几乎可以肯定获得了一个“唯一”的时间数据。
通过google、维基百科,我自信获得了一个完全满足剩余线索的人物名称,不过却始终无法获得正确的url。头痛!先放一放,正好这两天事多,忙过去再来看看,或许能有新的发现。

2005年12月03日

第14题:


    从这关起就不打算直接把答案写出来了,记录一写自己在解题时的心得吧。
    如果你正饿得时候做这道题不知道是好还是坏。屏幕上一个香喷喷的面包正诱惑着我,下面那个类似条码的便签好像告诉我还没过保质期新鲜着呢。屏幕上的一切将我本已经混乱的思路转得更找不到北。
    按照惯常思路,马上将Title、页面显示内容、page source逐个看了一便。
    title的意思很明确,其和面包之间的内在联系将信息明确的表述了出来。
    page source中的东西着实让我有些烦,莫非又要做一道类似前面的数列规律分析题?如果仅从其中提供的等式来看,即使对于我这样的数学白痴来讲得出正确的解也没什么难度。ok。一定是重要线索,保留之。
    面包和条码的文件名都没什么特别的规律可以去发挥,不过条码文件的名字确实与其图案扣题。至此,我又找不到北了。该如何继续进行下去?

    中国有句老话——车到山前必有路。如果你感到实在没有进一步思路的情况下,那就说明我们还没走到山前,肯定还有不少线索没有找到。
    在整个解题中,我觉得有几个辅助工具非常有帮助,一个十六进制代码分析、修改软件以及一个适手的图像处理软件。
    还记得前面几关所说的认真吗?那就再认真点。通过使用上面的工具,我很快就在所谓的条码图片上有所突破,并且明确的发现其中隐藏的一些不同寻常的纯彩色色像素。
    现在我们手中有了一幅看似没有规律的图片数据、一个美味的面包、一组看似有规律的等式。注意还有两点你看看条码在页面上的显示横纵向分辨率是否和等式前面有所关系?
    还记得11题中我们所使用的技巧吗?我是只像素的控制,好像在前面画牛头的时候也用过。统合一下,你应该能有所收获!

    如果你得到下面的图片,首先恭喜你。你已经在正确的思路上了,不过还有些问题,顺着获得的提示继续下去,答案就在不远处。

   
   

    外面正在下着大雪,这样的天气真适合解谜:) 不过还是要出去一趟,感觉天一半时好不了,准备点存货已被不时之需!

2005年12月02日

第13题:邪个没完了!

    屏幕上出现一盘电话。
    title 提示:call him  ( 他是谁?)
    屏幕下方
phone that evil

   
答案很明显—— Bert!
    不过如果在上一关没有继续找寻下去发现bert is evil,恐怕就要晕了。
    电话上的按键5可以点击,进入一个phonebook.php页面。页面显示一个xml文件信息,大意是错误!
    其中的关键在于<string>XML error: no element found at line 1</string>
    google了一下,关于这句有很多解释,单绝大多数的含义就是xml解析错误。注意,不是客户端的错,是服务器端的错!
    难道要用其他的方法调用?
    最初我直接想到了soap。由于python本身没有内置的soap支持,就去找了SOAPpy来研究了一番。经过一番测试之后宣告方向错误,转换思路。
    xmlrpc!
    python内置了队其的支持,而且这又是一种更古老更通用的手段。说干就干!
    程序可以说简单的很,但却尝试了非常的可能性。由于并不知道其xmlrpc服务器方的方法名称,唯一的办法就是瞎猜、乱试。感谢上天的眷顾,只用了不到10分钟就测试出来了。


import xmlrpclib
server = xmlrpclib.ServerProxy('http://www.pythonchallenge.com/pc/phonebook.php')

server.phone('Bert')


    
最初,也差点由于大小写的原因与正确答案失之交臂,不过总结了上一关的经验,不放过任何蛛丝马迹,最终顺利的找到了答案!
      ‘555-ITALY’
      答案:  italy
      下关入口:http://www.pythonchallenge.com/pc/return/italy.html

    说实话,由于12关的遭遇,实在没有想到13关会如此的顺利。

第12题:将邪恶进行到底!

    首先说明一下,这关是目前为止我遇到的最大挑战,共用了2天半时间才完成。其中需要完成很多步骤并且会碰到不少误导。做完这关后,我对于认真二字又有了更进一步的认识。

    屏幕上显示出一幅发扑克的图片。
    Title上提示 dealing evil (可能有发牌作弊的意思)
    察看page source 你会发现这幅图的文件名很有意思是 evil1.jpg 。也就是说后面有编号

   

    在前面的谜题中曾经碰到这样的问题因此推断 可以通过改变后面的编号获取更多的信息。果然通过改变编号可以获得 evil2.jpg


        有点意思吧,上面说不是 jpg 而是 gfx 。什么意思?hehe,继续尝试。此处要兵分两路,一边继续尝试 evil3.jpg (bingo! 确实有),另一边我们要尝试 evil2.gfx (bingo !! 如果双色球我这么准就好了)。gfx文件目前还看不出什么特别的,下面再研究。


    什么?没有了,难道邪恶如此容易的没有?如果你此时没有探索精神的话,那可就惨了。因为接下来找到的线索是下一关解密的关键,如果你没有找到,可以明白的告诉你你的解谜历程到此就结束了。还好,我坚持了下来。继续尝试 evil4.jpg
    这个地方要特别说明一下,如果你使用的是ie的话,你将直接看到如下一段话:Bert is evil! go back! (注意是文本,不是图片)。假如你使用的是firefox的话,屏幕上显示的是evil4.jpg的url,你需要在source code中才能看到这段话。
    至此下一关所需的线索我们已经获得了。不过如果你像我一样富有不屈不挠的探索精神的话,还可以继续尝试,bert.html  (bingo!! 有中了)

    到这里,已经没有办法再继续追查下去了,我回过头来研究evil2.gfx文件。
    说实话,这个文件研究了1天。直到我得到提示,研究一下magic bytes。所谓magic bytes就是就是各种文件格式所具有的一些独特的标示字节,通过这些字节你可以很容易的辨认出文件的类型。不过gfx文件表面上你找不到任何这方面的特征。没关系,研究呗。jpg格式有一个非常容易辨认的特征就是在文件头包含jfif。呵呵终于被我发现了!gfx文件第一个字节后每个5个字节如果你仔细察看就会发现其与jpg的头文件非常吻合,原来藏在这里。ok!提取!


import sys
f2=open('./python challenge/evil2.gfx','rb')

bingobytes=''
sourcebytes = f2.read()
for i in range(0,len(sourcebytes),5):
    bingobytes+=sourcebytes[i]
f3 = open('./python challenge/evil2_end1.jpg','wb')
print >> f3,bingobytes

     哈哈,我终于获得了需要的线索,jpg图像现身了!


    没错应该就是dis+xxx什么的,我感觉到自己离答案已经一步之遥,但现在我才陷入真正的噩梦!
    我尝试了各种线索与dis之间的联系,但始终得不到正确的答案。然后我开始认真研究起dis 以及 bert来。Dis 冥神,如果不查字典,我只会以为他就是一个前缀。 bert is evil .98年就建立起来的一个网站。站点的主人认为芝麻街的主人公bert对小朋友没有正面地教育意义,因此建立了网站广为散播他的观点,这个观点曾经相当的受人注目。好像还获得过98年的特别网站奖什么的。至此,我已经更进一步的陷入了误区,开始研究芝麻街。查看了芝麻街的人物介绍,一个叫count的家伙特别的引起了我的注意。他的名字叫count 或 count von count ,是一个吸血鬼(感觉上非常吻合dis 以及 evil的特质),ok,就从他入手。我开始尝试各种dis+count等等组合,后来考虑到count求和方面的作用,开始对已有的线索进行各种求和。。。。。。。又一天过去了。。。。。我就要崩溃了。。
    抛掉之前所有的假设,重新再来一遍!

    其实我曾经离答案是那么的近,但由于自己的不认真及自大,让答案就那样轻易的从身边溜走了!
    当过再次仔细的研究过gfx 文件后,终于得到了1天半前就应该得到的答案。
    gfx文件就像前面说的那样,里面隐藏了图形文件,不过隐藏的不是一个而是5个!我仅仅提取了一个就匆忙罢手才导致上面的严重错误。5个文件是按照1、2、3、4、5个字节顺序排列的,也就是说从第二个字节起每个5个获取一个,组成一个文件,以此类推。不过其中有3幅是gif文件,研究一下gif的magic byte其实很容易就可以想到。
    ok,程序类似上面的。接连获得如下4个图片:


这幅图在firefox下看是一半的,因为最后的数据有点问题,不过在看图软件下就是正常的。

    至此,此题告破!当然如果你像我一样,英语都已经还给了可爱的老师,那么我们还要费心的再查查字典,看看如何组合:)   ity 都已经划掉了,当然就不用考虑了。
   答案: disproportional
   下关入口:http://www.pythonchallenge.com/pc/return/disproportional.html

    最后再多说两句,之所以12关写了这么长并把图也给附上实在是因为耗费了太多的心力,不过转念想想,也不错,如果不是到处乱撞我也不会有心研究芝麻街:)
    再补充一点:最初获得evil1.jpg时还被它给好顿骗。因为这幅图有两个jfif头部分,所以造成看起来很怪,其结果导致我研究了好一番信息夹带,考虑从它身上榨取些信息。呵呵,福兮祸兮。
  

第11题:邪魔现身


    Title 提示 odd even (奇 偶)
    屏幕上的图片在gimp下查看可以看出也是经过特殊处理的。规律是 偶行上的奇列 以及 奇行上的偶列 都有着明显的图像数据痕迹。其他的点,视觉上看起来几乎都是黑色的。
    然而所有的秘密恰恰隐藏在这些黑色的点中。
    用pil将所有看似有颜色数据的点涂黑。


import Image
im = Image.open('./python challenge/cave.jpg')

length,width = im.size
for x in range(1,length+1):
    for y in range(1,width+1):
        if (x % 2 == 0 and y % 2 !=0) or (x%2 !=0 and y %2 ==0):
            im.putpixel((x-1,y-1),(0,0,0))
im.show()

    邪魔现身!得到答案 evil.
    下关入口 http://www.pythonchallenge.com/pc/return/evil.html
     做过了这道题后,我看了一下其他一些解法,其中有一种令人啼笑皆非同时也非常实用——改变亮度。随便通过一款图像处理软件对图片进行亮度、对比度处理后,evil同样可以清晰看到。不过这样也恰恰说明了这个挑战的趣味性及多样性。
    PS: 如果你仅仅通过观看答案而感觉挑战没有什么难度的话,我个人严重推荐您亲自完成其中的谜题。并非要证明其难度,主要是你可以在解密中获得真正的乐趣。
    现在感觉说出了谜底的我也是 EVIL 的!

第6题: zip 模块

 
    title提示是一对。
    源代码中出现〈!– 〈– zip –〉字样
    从http://www.pythonchallenge.com/pc/def/channel.zip 下载zip文件
    (提示够变态吧)
    打开zip文件中的readme.txt 可以看到
    welcome to my zipped list.

    hint1: start from 90052
    hint2: answer is inside the zip
    感觉解题思路基本上和上面那个反复调用url的题一样 

r=re.compile(r'(\d+)$')
nextnothing='90052'
while(1):
    try:
        f=open('./python challenge/%s.txt' % nextnothing)
        result=f.read()
        f.close()
        print result
        oldnextnothing=nextnothing
        nextnothing=r.search(result).group()
    except:
        break


    执行后最后显示 collect the comments

    有点昏吧,哪里来的comments。其实就在zip文件里。这道题最后还是需要用zip模块来完成

 
import re
r=re.compile(r’(\d+)$’)

import zipfile
comment=[]
nextnothing=’90052′
f=zipfile.ZipFile(‘./python challenge/channel.zip’)
while(1):
    try:
        comment.append(f.getinfo(‘%s.txt’ % nextnothing).comment)
        nextnothing=r.search(f.read(‘%s.txt’ % nextnothing)).group()
    except:
        print ”.join(comment)
        break


    运行屏幕显示一个由字符组成的图片,可以看出图案是HOCKEY
    进入http://www.pythonchallenge.com/pc/def/hockey.html
    什么?还没结束!
    上面显示it’s in the air. look at the letters.
    此时,再次注意观察前面出现的hockey图片发现,每个字母的图案都是由一个单独的字母组成,得到最终答案oxygen
    下题入口http://www.pythonchallenge.com/pc/def/oxygen.html

第7题: pil出场。颜色拾取

 
    屏幕上显示一幅图,图片的中间部分是由规律的灰度块组成。猜测信息应该是由这些灰度提供。
    通过gimp进一步分析可获得整个区域灰度块长度为608,除第一小块外,其他间隔都是7个象素点。也就是说每隔7个点可以获得一个颜色数据。由于图片是彩色的(RGBA模式),而只有灰度的颜色数据应该是255级以内,推测可能会是ascii。


import Image
im = Image.open(‘./python challenge/oxygen.png’)
ilist = im.convert(‘L’).getdata() #将色彩转换为灰度,这样只获得一个值
result=[]
for i in range(0,608,7):
    result.append(chr(ilist[im.size[0]*50+i]))
print ”.join(result)


    果然,运行程序显示:smart guy, you made it. the next level is [105, 110, 116, 101, 103, 114, 105, 116, 121]
    再次处理可得到答案


hint=[105, 110, 116, 101, 103, 114, 105, 116, 121]
answer=[]
for c in hint:
    answer.append(chr(c))
print ”.join(answer)


    最终答案:integrity
    下题入口:http://www.pythonchallenge.com/pc/def/integrity.html

第8题:bz2解码

 
    屏幕显示一个蜜蜂图片。查看页面源代码可以看到里面提示有加过密的用户名、密码。
    点击蜜蜂可进入一个需要输入口令的页面,说明此题应该就是解开用户名、密码
    说实话,这道题我始终没有找到破解加密算法的思路,直到看到网上有人说google一下BZh91AY。这个字符串时用户名和密码最开始相同的部分。google后可以看到介绍python bz2模块,得到解题思路。


import bz2

un = ‘BZh91AY&SYA\xaf\x82\r\x00\x00\x01\x01\x80\x02\xc0\x02\x00 \x00!\x9ah3M\x07<]\xc9\x14\xe1BA\x06\xbe\x084′
pw = ‘BZh91AY&SY\x94$|\x0e\x00\x00\x00\x81\x00\x03$ \x00!\x9ah3M\x13<]\xc9\x14\xe1BBP\x91\xf08′

un=bz2.decompress(un)
pw=bz2.decompress(pw)

print un
print pw


    运行得到答案
    huge
    file
    登录即可进入下题

    下题入口http://www.pythonchallenge.com/pc/return/good.html

第9题:pil再度出马,描点

 
    屏幕上显示一幅风景画,上面有很多小黑点。
    title提示,连接点
    page source中可以看到两组数据 first second 并提示 first+second=?
    起初我真的在gimp上把图片上面的点用画笔描了起来,看看是否有什么提示,不过一无所获。
    后来观察first和second的数据,发现其值均在该图片的x,y size之内,并且两组数据的个数都为偶数,获得灵感是否是坐标数


import Image
first=[
146,399,163,403,170,393,... snip]
second=[
156,141,165,135,169,...snip]
im=Image.open('./python challenge/good.jpg')
f=[]
for i in range(0,len(first),2):
f.append((first[i],first[i+1]))
print f
for xy in f:
im.putpixel(xy,(255,0,0))

f=[]
for i in range(0,len(second),2):
f.append((second[i],second[i+1]))
print f
for xy in f:
im.putpixel(xy,(255,0,0))
im.show()


    呵呵,可以隐约在图片上面由红色的点组成了一头牛的图案。
    first是外缘轮廓,second是头的轮廓
    赶紧进入http://www.pythonchallenge.com/pc/return/cow.html
    结果发现提示hmm. it’s a male.
    唉,分得还挺细。。
    得到最后结果:bull
    下题入口:http://www.pythonchallenge.com/pc/return/bull.html

第10题: 数字列表

 
    屏幕下方提示 :len(a[30]) = ?
    点击图片可获得数据:
    a = [1, 11, 21, 1211, 111221,
    知道应该是根据这个提示找出规律,扩充列表获得答案。
    不过规律何在?解此题。。。。耗时超过2小时。。。。主要是笨呀。
    最后终于明白值之间的规律。就是每个值都是对前一个值得文字描述。
    什么?文字描述,不错,念起来就知道了
    比如说第一个是 1
    第二个就是 1个1 (11)
    第三个就是 2个1 (21)
    第4个就是 1个2 1个1 (1211)
    第5个就使 1个1 1个2 2个1 (111221)
    以次类推。。。。说实话,开始总是想数字之间是否有什么数学运算上的关系,所以总也推算不出。

x="1"
for each in range(30):
    x="".join([str(len(i+j))+i for i,j in re.findall(r"(\d)(\1*)", x)])
print len(x)


    得到答案:5808
    下题入口:http://www.pythonchallenge.com/pc/return/5808.html