avatar

Derek Zeng

A programmer

a few problems

by coderek

今天一整天基本上都在 fix bugs.

email graph的那个问题已经弄了好久了,将近一个月吧。昨天submit了我的第n个fix,但今天却还是被告知fail,真的有些不爽的。问题是这样的:用户可以通过前几个月的报告数据生成一个图表,这个图表是php生成的一个jpeg图片。它的地址是以绝对路径存储在数据库里的(这里先不说不该用绝对路径)。我们在给用户一个软件的安装程序的时候(一个tar.gz2的drupal文件),会预制一些这种图表+地址放在数据库里面。这些其实是demo的图片,主要是想让用户知道有这个东西。然后他们自己生成第一个graph的时候会overwrite这个demo的。最后,这个生成的图表可以被设定通过邮件发送,这个是用户自己的设置。

问题出在哪里呢,那些demo图片的地址是hard coded进去的,而且是错的。可是我们的系统会被很多不同的domain使用,所以,他们用邮件发送的图片当然发不出去。发送邮件的这个问题涉及到一个cron job的问题。邮件不是立刻发的,而是每天有定点的程序发送。之前的fix是用$_SERVER['HTTP_HOST'] +drupal 在服务器的文件夹名生成一个base url来替换掉原来错误的地址,也就是只是换掉domain+root folder的那个part。 这种方法理论上是work的,在localhost和server上都测试没问题。我们测试的方法是,直接在浏览器里放systemCron.php的服务器地址。邮件也发的很好,没问题。然后提交fix后,很快就被告知fail了。根据这个思路我也是过好几个tweak,也都是在我这边测试没问题,到用户那边就出问题。通过log发现,每次都是domain不对,也就是说$_SERVER['HTTP_HOST']没有被读到。

后来google了一下,发现$_SERVER['HTTP_HOST']在http/1.0里是没有defined。于是就怀疑用户的机器是http/1.0,但很快发现他们的用的是http/1.1是没有问题的。

问题到底出在哪里呢?我测试都可以,到他那边就不行。问什么呢?后来就想到这个cron task上面去了,想了一下cron task到底是怎么invoke的。去bluehost 上看了一下,恍然大悟。原来,那些所谓的script是用php cli来run的。php cli用的是文件在本地的路径,跟服务器没有任何关系,也就不会有想’HTTP_HOST’这种variable了。var_dump了一下$SERVER,发现没有任何服务器信息。我的测试之所以能work是因为,我是直接在browser里面run,发送了http request。实际情况并不是这样。

于是,我现在的fix是,在app 的setttings.php 里面define一个常数:BASE_ADDRESS。在下一个update或install的时候set它的值到正确的地址比如 https://eccc.com/gma 。 这样cron job run的时候include_once一下这个settings.php就可以直接用这个BASE_ADDRESS了。 Set 这个BASE_ADDRESS需要用get_file_content()+strpo+strconcat, 因为define了的值不能在php里面改动。我fgets的时候遇到了一个小问题,不能读取setttings.php里面的string。后来上了stackoverflow,上面说要用htmlspecialchars()这个function。果然,php echo 不能读special character like “”,必须要转换一下。其实我不需要print out, 因为在buffer里面的string是没有问题的。直接找到那行代码,两头一切,然后中间插一个从$_SERVER得到的地址就行了。

现在的fix应该可以了,因为问题的本质已经在那里的。之前老是弄不对是因为没有办法replicate的bug。总以为fix是对的,其实还是经验不足的体现。

今天还弄了一个ssl的问题。

我们做的网站有用ssl。那个东西就是把client, server发出去的东西encrypt一下,保护通讯安全。具体的workflow就是:

client request secure connection  
->  
server send its public key and certificate to client   
->   
client verify and generate session key using server’s public key and send to server   
->   
server can decrypt the message using its private key   
->   
then both side use the session key to encrypt and decrypt the message  

server需要support ssl,像apache有mod_ssl。然后需要有一个有效的有CA signed 的certificate,然后每次request把http换成https,就可以用了。我遇到的问题是,网站的某个网页ssl失效。也就是浏览器无法确定网页的安全性,于是就有一个https被红线划掉的标志。我挑查了一下,发现浏览器其实是可以读到他的certificate的,而且是证明有效的,但现实的是partially verified。我打开firebug一看,原来,这个page load了很多resource像,css, js, jpeg等等,都是指向port 443。但其中有一个resource找不到,显示是红色的。就是这个找不到的resource影响了网站的安全性。然后我把那个resource拿掉,就没有问题了。

(End of article)