2009.5 in Dalian

June 11th, 2009

2009indalian

2008.11 in Beijing

June 11th, 2009

2008inbeijing

生活的意义在哪里?

February 8th, 2009

毕业8个月了,算一算,工作了也有一年半了,自己想想过去的8个月,一年半,或者所有这些离开家的日子,我有点迷茫,失去了太多却又感觉自己没有得到什么。

有时候总是在想,每天这样的生活到底为了什么?想来想去也没有结果,不在家人的身边,没有朋友,不再有那么多的同学了,到底为了什么?仿佛今天这样的生活只是为了明天依然过着这样的生活,当然这不是我想要的结果,但毕竟事实就是这样的。

以前一直觉得没有梦想的生活很可笑,所以每天不停的追寻着那虚无缥缈的东西,后来终于发现这样的生活是无法追到所谓的梦想的,但想改变现在的生活,说实话,太难了。要是以前,我可能会觉得现在的想法太可笑,但是现在才发现,可笑的是以前的无知与懵懂,生活是很现实的。

以前有过很多目标,黑客,兼职程序员,淘宝掌柜,web2.0站长等等等等吧,我现在却有点很满足于现状,可能是虚荣心作祟,和身边的同龄人来比的话,我应该算很自豪了,有时候也会有冲动去改变现在的生活,但每次都不了了之。以前总是认为现在这样的生活挺可怕的,没想到现在就这么可怕的活着,原来生活就是最大的玩笑。

有时候总会和朋友开玩笑说:“大学毕业了之后,这一辈子就只能找个事业,找个媳妇儿,生个孩子了。”仔细想想,的确啊,这辈子就省这点事儿了,我的妈呀,我的人生啊,梦想啊,未来啊,就浓缩在这点事儿上了。

实在无聊,上来发发牢骚,冒个泡泡证明我还健在,其实说了这么多,什么都改变不了,明天依然还是这样平淡的活着,我只希望明天会更好一点,一点就好。

生活仍在继续

December 29th, 2008

被和谐差不多两个月了, 电脑坏掉了加上最近工作比较忙, 所以这么久才把新域名弄好, 赶紧写点什么, 证明我还建在。

10月末被和谐的, 原因嘛, 不说了, 怪郁闷的, 说点实话比啥都难。 以前被和谐几次换个ip就ok了, 没想到这次换啥都不灵了, 只能把米换了,这次有机记性了, 以后敏感话题一律都不对外发表。

六月份买的电脑莫名其妙总死机, 折腾几个月了, 也没修出什么名堂, 拿维修站检测说死也不死机, 拿回来不到10分钟就死的一塌糊涂, 后来更过分, 只在windows下死再ubuntu下一切正常, 后来没辙把电脑搬单位去了, 最近忙也没时间研究, 只能先放着, 过年家里没人免得丢了。

最近两个月够忙活的, 11月初赶上上个项目结束, 日本老板来国内, 那个压力呀, 天天忙活, 天天赶进度还加班。 11月末去了趟北京, 逛了4天感触颇深, 北京也不过如此, 现在这个情况让我挺犹豫的, 我所看到的再加上最近经济不景气各大公司大量裁员造成的就业压力, 合同马上到期了我正考虑明年是不是出去发展, 其实很多东西还是让我挺留恋的。

从北京回来公司开始用symfony做新项目, 最近一个月学到了不少东西, 作为世界顶尖的开发框架, 果然非同凡响, 项目质量和效率都直线上升, 估计把symfony吃透得用个一年左右, 吃透这个最少也能折腾个三五年, 作为一个php开发人员, 对于php和symfony的前景, 我还是相当有信心的。

最近和两个同事一起转移到ubuntu阵营了, 这次都做的比较绝, 彻底干掉了windows, 半个多月下来, 感觉还是挺好的, 除了不能用支付宝, 其他一切ok, 工作效率上的提升的确是可以看到的, 所以以后会一直坚持下去, 向更深层次发展。

电脑坏了之后晚上就没有什么用电脑的机会了, 所以最近休息的不错, 白天也不怎么困了, 晚上回去看看电视, 打打扑克, 锻炼锻炼身体就到睡觉点了。 仔细算一算, 除了上网查资料和再淘宝买东西, 有快五十天没在网上露过面了, 最近项目收尾, 工作比较琐碎, 今天上了会儿QQ, 真的是好久不见了, 真没想到会又这么多朋友和我打招呼, 以前天天挂着都是不说话的, 寒暄上两句真让我挺感动的。

再过两天就元旦了, 又是新的一年, 一转眼工作一年多了, 真不可思议, 昨天买了元旦的火车票, 3个月没回家了, 回去看看爸妈。

使用php生成网站缩略图

October 17th, 2008

今天bobhero要我看一下关于这个问题的解决方案, 其实这个问题以前也有想过,不过最后没有找到解决的方法, 今天在网上搜的时候发现这样一段代码。

<?php
// 调用IE
$browser = new COM(”InternetExplorer.Application”);
$handle = $browser->HWND;
// 前台执行
$browser->Visible = true;
// 全屏
$browser->Fullscreen = true;
$browser->Navigate(”http://www.m4ker.net”);

/* Still working? */
while ($browser->Busy) {
com_message_pump(4000);
}
// imagegrabwindow是对窗口进行截图
$im = imagegrabwindow($handle, 0);
// 关闭浏览器
$browser->Quit();
// 生成图片
$new_img = imagecreatetruecolor(200,150);
imagecopyresampled($new_img,$im,0,0,0,0,200,150,1024,768);
imagejpeg($new_img , ‘image/’.time().’.jpg’,100);
imagedestroy($new_img);

?>

很神奇竟然真的好用, 不过只限Windows, 原理也就是调用IE的COM, 打开网站然后截图这样。

url重写后的路径问题

October 17th, 2008

以前用FleaPHP的url_rewrite模式一直有一个很头痛的问题, 就是页面上相关资源的路径问题.

问题大概是这样的, 为了让url更加友好我们使用apache的mod_rewrite将类似

http://localhost/?controller=default&action=index&a=1

这样的路径重写成

http://localhost/default/index/a/1

或者

http://localhost/default/index/a/1.html

这样, 但是如果是这样那么浏览器请求页面相关资源的基地址就发生了改变, 从原来的documentroot下变成了documentroot/default/index/a, 如果你要在页面上显示一个图片 1.jpg, 那么原来本来应该在documentroot/1.jpg下找到的文件却变成了documentroot/default/index/a/1.jpg, 那结果肯定是找不到的.

为了解决这个问题以前用过很多方法, 用的最多的就是使用绝对路径来解决这个问题, 这是有一个前提的, 就是程序一定要放在虚拟机的根目录下, 这样在html中要将所有的资源都是用/开头, /的意思是从根目录下开始寻找, 在localhost下的任何一个程序在任何目录中使用/1.jpg都会被指向documentroot/1.jpg, 这里再强调一个概念, “./”是当前目录, “../”是上级目录, “/”是根目录.

上面这个方法实际上已经可以解决这个问题了, 但是有局限, 就是程序的目录是固定的, 一定要在虚拟机根目录下, 这样或多或少会带来一些麻烦, 至少我觉得调试不方便. 于是又有了第二个解决方案, 也就是上面方案的升级版. 我们在全局定义一个常量 define(’PRE_DIR’, ‘/’); 这样的话要将程序中所有的资源路径都写成类似 <?php echo PRE_DIR;?>dir/filename.jpg, 这样的话资源会被定为到 /dir/filename.jpg, 如果要将程序放在二级目录 test/下的话, 只要将PRE_DIR的值改成’/test/’就可以了.

其实在这之后又有了升级版, 但是不打算介绍太多, 因为这不是重点, 在手动改目录之后大家就想到要程序自动检测当前目录, 这个以前有做过, 是个不错的想法, 代码不少, 但是找不到了.

还有个东西我觉得比较神奇的, smarty有一个自动替换的插件, 可以自动在所有模板的资源链接前面加前缀, 当然前提是你已经定义了这个前缀, 插件名不记得了, 太久不用找不到了.

还是说重点吧, 昨天bobhero给我提供了一个新的思路, 利用mod_rewrite重新对资源进行定向, 后来到网上找相关的资料, 没有找到, 只找到了一些mod_rewrite的教程什么的. 研究了一下午也没研究出来, 因为url太复杂了, 很多情况都要考虑进去, 正则说什么就写不明白了, 今天早上终于搞定了.

_________.htaccess_____________________

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^.]*)(\.html)?$ index.php/$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*)/(.*\..*)$ $2

________end of .htaccess_____________

起作用的其实就这些东西,  可能还会有错误, 不过的确生效了.简单解释一下, RewriteCond %{REQUEST_FILENAME} !-f是条件语句, 意思是说如果请求的文件不存在下面的规则才生效. 第一条规则RewriteRule ^([^.]*)(\.html)?$ index.php/$1 [L]是FLEAPHP的重写规则.

下面两条才是为了解决路径问题的, RewriteRule ^([^/]*)/(.*\..*)$ $2的作用大概是这样, 比如url是这样controller/action/page/1,那么该页的style/css.css可能变成了controller/action/page/style/css.css, 这条语句就是要将controller/action/page/style/css.css指向action/page/style/css.css, 而由于某种机制请求每更换一次目录就会再执行一次根目录下的.htaccess中的重写规则, 由于action/page/style/css.css也不存在所以又被定向到page/style/css.css, 同理page/style/css.css也不存在, 再向上 style/css.css, 由于文件存在而不再执行重写规则, 向用户返回style/css.css的内容.

总的来说最后的这个方法除了apache受点累还是很完美的, 这样大概可能每个资源请求都会被重定向4次以上, 目前还不清楚对执行效率有多大的影响.

参考资料:

竹笋炒肉:Apache的Mod_rewrite学习

识别用户是否是通过手机访问

October 9th, 2008

今天花了些时间研究这个问题, 不过目前为止没有找到比较完美的解决方案, 简单说说吧.

现在网上一般有这样几种方法:

第一种是根据浏览器发送的HTTP_USER_AGENT来判断用户是否是通过手机访问网站. 这种方法比较普遍, 可以通过匹配关键字适应大多数手机, 但由于HTTP_USER_AGENT格式并没有标准规范并且不是HTTP协议必须的参数, 所以无法适应所有手机或者所有浏览器, 有些手机甚至不发送HTTP_USER_AGENT.

注: 可以在网上搜到别人搜集的各型号手机和浏览器的HTTP_USER_AGENT

第二种方法是根绝浏览器发送的HTTP_ACCEPT, HTTP_ACCEPT可以判断浏览器支持哪些格式的页面, 比如WAP, HTML, XHTML, XML等, 但对于判断用户是否通过手机访问并不是非常准确, 因为HTTP_ACCEPT不是同样必须的, 多数浏览器并不会在HTTP_ACCEPT中进行过多的描述, 比如一个浏览器如果声明了自己支持wml那它可能支持wml, 但是如果不声明wml并不代表就一定不支持wml.

比如Firefox3的HTTP_ACCEPT是这样的:

text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8 

而黑莓8800的HTTP_ACCEPT是这样的

application/vnd.rim.html, text/html, application/vnd.wap.xhtml+xml, text/vnd.sun.j2me.app-descriptor, image/vnd.rim.png,image/jpeg, application/x-vnd.rim.pme.b, application/vnd.rim.ucs, image$1.gif;anim=1, application/vnd.rim.jscriptc;v=0-8-8, application/x-javascript, application/vnd.rim.css;v=1, text/css;media=handheld, application/vnd.wap.wmlc;q=0.9, application/vnd.wap.wmlscriptc;q=0.7, text/vnd.wap.wml;q=0.7, */*;q=0.5 

还有一种方法有人说可以判断用户的IP, 原理也简单, 因为在国内GPRS上网是通过代理连接的, 所以用户的IP可能是固定的几个, 但是我并不确定手机不能够通过其他方式上网, 比如3G, 或者说我用手机模拟器登录的时候就有可能出错, 或者说如果我用手机当猫那么会将我通过电脑进行的访问当作手机来处理.

还有一种方法我觉得很不错, 如果浏览器支持javascript的话, 可以判断显示器的尺寸, 没有人会用一个19寸大的手机吧?

说来说去, 还是没有找到完美的解决方法, 不过综合这几种方法写了一个函数.

/**
 * 是否是通过手机访问
 *
 * @return bool 是否是移动设备
 */
function isMobile()
{
    // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
    if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
        return true;
    }

    $keywords = array('nokia', 'sony', 'ericsson', 'mot',
        'samsung', 'sgh' ,'lg', 'sie-',
        'philips', 'panasonic', 'alcatel', 'lenovo',
        'cldc', 'midp', 'wap', 'mobile');
    // 从HTTP_USER_AGENT中查找手机浏览器的关键字
    if (preg_match("/(" . implode('|', $keywords) . ")/i",
        strtolower($_SERVER['HTTP_USER_AGENT']))) {
        return true;
    }

    if (isset($_SERVER['HTTP_ACCEPT'])) {
        // 如果只支持wml并且不支持html那一定是移动设备
        // 如果支持wml和html但是wml在html之前则是移动设备
        if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false)
        && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false
        || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml')
        < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
            return true;
        }
    }

    return false;
}

好陌生

September 12th, 2008

颠簸了一晚, 终于到家了, 我已经半年多没回来了, 这次回来, 不再是一个大学生了, 成了一个漂泊在外的打工仔, 在外面的时候总是想着, 可回来了又感觉好陌生。

今早刚下火车, 车站门口是一帮出租车司机和旅店的人在拉客, 我拿了好多东西, 虽然很重, 但是我没有打车, 家离车站不是很远, 五六百米的样子。

刚走出车站就发现变化好大, 家附近的楼房拆了不少, 又在盖新的了, 回家的小路依然是那么安静, 走进家门, 已经3点10分了, 好累, 在车上一直不敢休息, 身边那个人刚上车没多久钱就被偷了, 但是到家了又好兴奋, 和妈妈聊了一会就睡了。

一下子就睡到了11点, 以前的同学们都还没有毕业, 这次回来没有朋友, 没有死党, 只能家看看电视, 洗洗衣服, 和妈妈聊聊天。

 吃完晚饭, 出来逛逛, 变化好大, 走出没多远就发现都是各种陌生的店面, 老字号也是有的, 还是那么红火, 家里附近的路边都堆着地砖, 好像在修路, 沿着最繁华的街道走, 才发现整条路都在施工, 地上好大个坑, 好像是要建地下商场。

路过广场, 那里好冷清, 感觉怪怪的, 现在这个季节好像不应该是这样的, 天气好冷, 街上的人都穿着外套。

一直走到以前上高中的地方, 从娱乐场所比较多的地方走过, 发现真的不一样了, 可能是初中高中错过了太多的东西, 看着身边穿着时尚的年轻人, 感觉我不属于这里。

街上人好少, 路过了好多我走了之后才开的网吧, 每家网吧都那么热闹, 里面的年轻人玩着各种各样的游戏, 想想自己的过去, 真的好多感慨, 如果当初能懂事一点, 现在一定不是这个样子。

昨天在车上看了一路的书, symfony, 感觉前面的路好长, 好迷茫, 回到这个陌生的地方, 让我不知何去何从。 除了朋友和家人, 好像这里已经没有什么值得我留恋的了, 一切都这么陌生, 与我的世界格格不入。 外面的生活好艰难, 每件事仿佛都不是那么如意, 我属于哪里? 我该去哪里?

使用PHP收发邮件

September 9th, 2008

这两天都在测试邮件, 搞得头都大了, 现在技术问题都已经解决了, 记录一下.

发送邮件一直都是一个难题, 以前没用过mail函数, 因为多数的环境下都不支持, 曾经改写过Discuz的邮件类, 也用过像PHPMailer这样的邮件发送库来解决邮件发送的问题, 但实际上用的都是SMTP. 昨天bobhero在公司内网服务器上配置了sendmail, 简单配置了之后可以使用smtp, imap和pop3. 但按照网上的教程配置了之后php的mail()函数一直都无法发送邮件, 在搜索引擎上寻找很久没有结果, 最后bobhero重新编译了配置文件, 终于成功.

编译命令

make -C /etc/mail

收邮件要比发邮件复杂的多, 网上资源巨少, 好不容易有几篇英文的帖子和我情况类似也没有解决办法.

接受邮件使用php的imap库, 遇到的问题主要在imap_open()上

连接163使用

imap_open("{pop3.163.com:110/pop3}INBOX", $username, $password);

取得的7bit数据使用imap_qprint()解码.

连接gmail使用

imap_open("imap.gmail.com:993/imap/ssl", $username, $password);

最难弄的就是连接本地的imap服务器, Outlook是可以从服务器上收取邮件的, 但是php就是收不到并返回错误Certificate failure for 102.com: Self-signed certificate or untrusted authority: OU=IMAP server, CN=imap.example.com, E=postmaster@example.com, 使用telnet链接也没有问题, 从昨天下午研究到今天中午也没解决这个错误, 网上搜不到解决办法, 最后实在没办法了, 用IP Sniffer截php.exe的数据包, 然后用telnet进行模拟, 发现php.exe在和imap服务器链接成功之后使用了TLS(一个什么传输安全协议), 刚想放弃就在php.net上看到原来imap_open()还有一个参数是/notls, 我的天, 终于得救了.

imap_open("{localhost:143/imap/notls}INBOX", $username, $password);

研究期间发现telnet很好玩, 可以用telnet检查某项服务是否开启, 比如smtp, telnet 192.168.1.102 25, 如果服务是开启的就会建立一个连接, 可以用指令进行smtp 的相关操作, 而指令内容也就是smtp协议的相关内容, 其他协议pop, imap等等都可以这么玩.

相关端口:

smtp 协议 25端口

imap 协议 143端口

imap/ssl 993端口

imap/ssl/novalidate-cert 995端口

nntp协议 119端口

相关资源:

中国协议分析网 http://www.cnpaf.net/

RFC文档 http://www.faqs.org/rfcs/

保留用户输入的错误数据

September 6th, 2008

最近公司项目比较闲, 所以很多时间都在整理代码, 这几天就又有了一个这样的需求, 当用户提交了错误的信息, 提示错误并保留用户输入的数据。

起初第一个想法就是使用COOKIE, 后来又考虑使用$_SESSION, 其实两者无明显区别,大概流程是这样的, 每个请求的前面都加入下面的逻辑:

if(有保存的数据){

    if(数据是不是本动作产生的){

        如果是则取得数据

    }

    清空保存的数据

}

if(是一个POST请求){

    保存用户的请求数据

}

这样处理的话消息处理需要中间页跳转,就是说错误提示是一个单独的页面,这样基本可以做到将数据保存到下一个请求。这个方法后来在显示上比较麻烦,就是需要判断有没有取得的数据,有的话输出没有的话不输出, 如果使用模板引擎的话处理起来更加复杂, 于是又提出了另一种解决方案。

将表单和处理程序放在一起(可能是一个function , MVC中应该是一个action中),这样的话需要显示表单或者处理数据要准备一套结构相同的数据传给页面,然后由本页显示错误消息, 不需要使用COOKIE.

function actionCreate(){

    if(是POST请求){

        过滤数据

        验证数据并生成错误

        if(没有错误){

            向数据库插入数据

        }else{

            将错误数据提交给显示层

        }

    }else if(是GET请求并且必要参数正确){

        从数据库取得显示数据提交给显示层

    }else{
        返回一个参数错误
    }

    $this->display('create.html');

}

可以说这个方法是比较完美的, 目前来说没有什么不足之处, 但是有很多细节是需要注意的, 比如form的action要提交给自身并且携带参数, 虽然参数无作用, 但可以用来刷新页面(window.location.href=window.location.href), 显示层刷新页面的功能是必须的, 因为如果是修改操作那么输入错误之后将会保留错误的信息。

接下来还可以通过控制错误消息的结构识别错误是由哪一个表单项产生的, 如果需要还可以对错误进行自动修改等等。