Blog

  • Adorable google

    adorable google
    adorable google

    我是google的忠实用户,今天才第一次用桌面版的Gtalk,惭愧。

    我关心了一下Gtalk的扩展功能,比如翻译机器人,加一个zh2en@bot.talk.google.com,它就能中文翻英文;加一个en2zh@bot.talk.google.com,它就能英文翻中文。

    有一些小错误,只要是google犯的,我觉得也挺可爱的。比如,“我家宝宝最可爱”给硬生生翻成了”I am the most adorable baby at home” ;”I am the most adorable baby at home”再翻成中文,就成了“我最可爱的孩子在家里”。

    google真是太可爱了!

  • Microsoftware is getting less usable

    今天要不是为了和msn上的联系人通话,我也不会去安装msn messenger。The process of installing msn messenger turned out very frustrating.

    It did not take me to Msn messenger download page straightly. Only after 5 clicks then could I find the link of download. However, because I was in a hurry, I clicked the link before I read it carefully. Only after I installed it, I found what I installed was a shortcut to Live Home. What the hell they are doing! Then I spent a few more seconds to find another link to download. And this time I installed msn messenger. After installation, there were two icon in Windows Live program group, Windows Live Call and Windows Live Messenger, but they were both pointing to the same program! Is microsoft mad?

    Moreover, all I wanted was msn messenger, but I had been asked 3 questions 3 times:

    • Search from any browser address bar using Live Search
    • Set my browser home page to MSN.com (if your homepage isn’t already set to a Live or MSN page)
    • Help us improve our software by allowing Microsoft to collect data about your installation. If you have chosen to install Windows Live Toolbar, we will also collect data about your system, how you use our software, and the web sites you visit.

    How bad the marketing it is! Of course I say No, no, no 3 times.

    Last but the most important, after I installed msn messenger and run it, it would not let me voice chat and file transfer to my contact. I got the error messages like these:

    • (contact nickname) is using a version of Messenger that does not have improvements to support a Computer Call.  Please ask your contact to upgrade to the latest version of Messenger and try your call again.
    • The invitation to start File Transfer could not be sent because (contact nickname) is using an older version of Windows Live Messenger.

    Terrible! How can all my contacts use the same version as mine? Backwards compatible – does microsoft know it?

    Finally, I had to finish the conversion with my contact using Gtalk – a far better program leaving msn messenger behind.

  • Bank of China

    中国银行的网站终于改进了一下。以前外汇牌价网页在非中文平台上总显示乱码,现在用上了utf-8,这才有点像个”中国银行-全球门户网站”

  • Managing Innovation

    上大学有门课,叫Managing Innovation,是University of Brighton的教授来上的。这门课太深奥,我从来没听懂过。今天凑巧看到老板也在看managing innovation的讲义(不奇怪,他是University of Brighton某小组成员),难道managing innovation能拯救危机?

    英国人挺喜欢把innovation挂在口头,但我总觉得managing innovation可操作太弱,我喜欢step by step的东西。

  • Magento user defined attributes in product list

    Magento内置的产品属性与自定义的产品属性可访问范围不同。默认设置下,自定义的产品属性只能在product view取值,如在product view以外则取不到值;内置的产品属性则没有这种限制。

    为了让自定义产品属性能在Magento前端(比如product list, product new, 或者自己写一个product featured)随意取值,至少有三种方法可以更改默认设置。

    最简单的办法是创建一个config.xml(文件名任意),放在app/etc/modules/下:

    <?xml version="1.0"?>
    <config>
        <frontend>
            <product>
                <collection>
                    <attributes>
                        <attributeyouwant/>
                    </attributes>
                </collection>
            </product>
        </frontend>
    </config>
    

    以后有空再讲其他两种办法。记得一定要刷新Magento cache才能让设置生效!

  • Clear Magento cache is essential after layout xml update

    说来懊恼,为了让Magento product list能够显示自定义属性的值,我查看了magento wiki 和 forum 上几十个帖子,众说纷纭,我也不知道哪个是对的,或者哪个针对当前1.1.8可用。一个个实验下来,排列组合了不下100种可能,比如:

    • 有人说layout add this line: my_attribute,另有人说是my_attribute
    • 有人说要用$_product->getMyAttribute(),也有人说用$_product->getAttribute(‘my_attribute’),也有人说用$_product->getData(‘my_attribute’),也有人说用$_product->getAdditionalData(‘my_attribute’),还有人说用$_product->getResource()->getAttribute(‘my_attribute’)->getFrontend()->getValue($_product))
    • 还有人说Create separate module for your customization, Name it ‘Mycustomization’
      (can be changed).
      Then do this:
      1. Create file app/etc/modules/Mycustomization.xml

      <?xml version="1.0"?>
      <config>
      <modules>
      <Mycustomization>
      <active>
      true
      </active>
      <codePool>
      local
      </codePool>
      </Mycustomization>
      </modules>
      </config>
      

      2. Create folder app/code/local/Mycustomization and inside it app/code/local/Mycustomization/etc/

      3. Create file
      app/code/local/Mycustomization/etc/config.xml

      <?xml version="1.0"?>
      <config>
      <modules>
      <Mycustomization>
      <version>
      0.0.1
      </version>
      </Mycustomization>
      </modules>
      <frontend>
      <product>
      <collection>
      <attributes>
      <designer/>
      </attributes>
      </collection>
      </product>
      </frontend>
      </config>
      

      Once done on the frontend in all product collections you will have designer attribute loaded automatically.

    • 还有Create a file app/etc/modules/category_product_attributes.xml with the following:
      <?xml version="1.0"?>
      <config>
      <frontend>
      <product>
      <collection>
      <attributes>
      <attributeyouwant/>//This is your attribute
      </attributes>
      </collection>
      </product>
      </frontend>
      </config>
      
    • 等等

    最后发现所有组合都不起作用,除非清除magento cache 让 layout xml 生效。

  • Email encoder for not being spidered

    我用Email encoder很久了。以前总是去别人网站上运算一下,拿来就用。如今觉得加密算法很多,我应该筛选一下,并作一个适合我自己的常用的工具。

    因为跟javascript 字符串加解密有关,我首先找到一段程序,试运行了一下,相当不错,据说还支持中文字符串加密以及中文密码。

    function Encrypt(str, pwd) {
    if(str=="")return "";
    str = escape(str);
    if(!pwd || pwd==""){ var pwd="1234"; }
    pwd = escape(pwd);
    if(pwd == null || pwd.length <= 0) {
    alert("Please enter a password with which to encrypt the message.");
    return null;
    }
    var prand = "";
    for(var i=0; i<pwd.length; i++) {
    prand += pwd.charCodeAt(i).toString();
    }
    var sPos = Math.floor(prand.length / 5);
    var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos*2) + prand.charAt(sPos*3) + prand.charAt(sPos*4) + prand.charAt(sPos*5));
    var incr = Math.ceil(pwd.length / 2);
    var modu = Math.pow(2, 31) - 1;
    if(mult < 2) {
    alert("Algorithm cannot find a suitable hash. Please choose a different password. \nPossible considerations are to choose a more complex or longer password.");
    return null;
    }
    var salt = Math.round(Math.random() * 1000000000) % 100000000;
    prand += salt;
    while(prand.length > 10) {
    prand = (parseInt(prand.substring(0, 10)) + parseInt(prand.substring(10, prand.length))).toString();
    }
    prand = (mult * prand + incr) % modu;
    var enc_chr = "";
    var enc_str = "";
    for(var i=0; i<str.length; i++) {
    enc_chr = parseInt(str.charCodeAt(i) ^ Math.floor((prand / modu) * 255));
    if(enc_chr < 16) {
    enc_str += "0" + enc_chr.toString(16);
    }else
    enc_str += enc_chr.toString(16);
    prand = (mult * prand + incr) % modu;
    }
    salt = salt.toString(16);
    while(salt.length < 8)salt = "0" + salt;
    enc_str += salt;
    return enc_str;
    }
    
    function Decrypt(str, pwd) {
    if(str=="")return "";
    if(!pwd || pwd==""){ var pwd="1234"; }
    pwd = escape(pwd);
    if(str == null || str.length < 8) {
    alert("A salt value could not be extracted from the encrypted message because it's length is too short. The message cannot be decrypted.");
    return;
    }
    if(pwd == null || pwd.length <= 0) { 
    alert("Please enter a password with which to decrypt the message.");
    return;
    }
    var prand = "";
    for(var i=0; i<pwd.length; i++) {
    prand += pwd.charCodeAt(i).toString();
    }
    var sPos = Math.floor(prand.length / 5);
    var mult = parseInt(prand.charAt(sPos) + prand.charAt(sPos*2) + prand.charAt(sPos*3) + prand.charAt(sPos*4) + prand.charAt(sPos*5));
    var incr = Math.round(pwd.length / 2);
    var modu = Math.pow(2, 31) - 1;
    var salt = parseInt(str.substring(str.length - 8, str.length), 16);
    str = str.substring(0, str.length - 8);
    prand += salt;
    while(prand.length > 10) {
    prand = (parseInt(prand.substring(0, 10)) + parseInt(prand.substring(10, prand.length))).toString();
    }
    prand = (mult * prand + incr) % modu;
    var enc_chr = "";
    var enc_str = "";
    for(var i=0; i<str.length; i+=2) {
    enc_chr = parseInt(parseInt(str.substring(i, i+2), 16) ^ Math.floor((prand / modu) * 255));
    enc_str += String.fromCharCode(enc_chr);
    prand = (mult * prand + incr) % modu;
    }
    return unescape(enc_str);
    }

    转念一想,我把问题搞复杂了,对自己没什么好处。我的Email encoder用得着这么复杂吗?毕竟我想保护的又不是名人的Email address。所以我改用我自己的方式——采用双重url encode,在第二重url encoding时,encode全部字符(含字母和数字)。

  • 让浏览主控服务器从幕后走到台前

    可以用nbtstat -a (computer name or ip address) 命令查看该计算机是否浏览主控服务器。如果是,则会出现“..__MSBROWSE_.”字样。

    浏览主控服务器不一定非是选举产生,是可以指定的。

    只要在希望成为浏览主控服务器的电脑上打开注册表,在[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Browser/Parameters]一项中把IsDomainMaster的值改为“True”即可。这样,这台电脑就会成为一个浏览主控服务器。这台电脑启动时,如果网络中已经有了浏览主控服务器,那么它会发起一个新的选举,在这个选举中它常常会赢得选举。当然,如果其它电脑也做了同样的设置,那么它们之间的竞争就要按正常的选举规则了。

    另:如不想让某台电脑永远不成为浏览主控服务器,可以在注册表中的[HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Browser/Parameters]一项中把MaintainServerList的值改为“NO”,即可,这样这台电脑将不会成为浏览列表提供者,同时该电脑的Computer Browser服务也将无法启动,如强行启动会出现错误提示。

  • My view of Liverpool

    在我到过的英国城市中,我最喜欢利物浦。利物浦号称欧洲的文化名城,我只在利物浦停留过一天,还没时间探究她的文化底蕴。我说我喜欢,说白了,就是喜欢她的外观。如果在英国投资物业,如果不考虑工作因素,我首选利物浦。为什么我把利物浦推崇到如此高度?我自己也觉得奇怪,仔细想来,大概是因为我喜欢上海,在英国这么年,到过的城市也不少了,没见过哪个城市有点上海气息,利物浦是个例外。

    为了证明我的感觉是正确的,我归纳一下:

    • 利物浦也是个港口城市,构局也有点像上海,一条默西河(Mersey)仿似黄浦江把利物浦分为东西两部分,目前是利物浦东比利物浦西热闹,毕竟利物浦东位于内陆。
    • 阿尔伯特码头(Albert Dock)可以隔江远眺利物浦西。阿尔伯特码头于1846年由阿尔伯特亲王主持开港典礼而得名。该码头由约克郡设计师杰斯·哈特利设计,占地约2.8公顷,所属仓库用于储存来自远东地区的茶叶、丝绸、烟草和烈性酒。经旧城改造,阿尔伯特码头现已发展为旅游商业区,位列利物浦首要旅游景点,十足的上海外滩。
    • 利物浦步行街规模庞大,英国其他城市的步行街根本无法与之相比。利物浦步行街在历史建筑群基础上往外扩建,我把它分外新旧两部分,新的部分像徐家汇,时尚而尖端;旧的部分仿佛上海南京路,可以充分满足购物和欣赏建筑的双重愿望。

    我事后了解到1999年10月18日,上海和利物浦结为友好城市,我衷心希望她们世世代代友好下去。

    (两个月前拜访的利物浦,现在才写完观感,惭愧)

  • No deplicate posts any more in WordPress

    刚用上WordPress后,我发现WordPress一个不足之处——同一个post_id的post,可以用不同的url来访问。

    以此blog为例,我设置permanent link structure为/%post_id%/%postname%/。我认为post_id查询最快,postname又是meaningful string,最有利seo,所以我把两者结合起来了(后来据说顶层目录的文件最利于seo,所以我更喜欢设置permanent link structure为/%postname%_%post_id%.html,但据说Google不吃这一套,那我就没必要为一些小引擎去劳师动众修改现有的blog,扯远了)。

    当permanent link structure存在post_id和postname两个参数时,post_id起决定作用。早期版本会完全忽略postname,造成只要post_id是正确的,任何杜撰的postname都会被承认。设想一下,如果我发布了一个post以后修改了postname,搜索引擎读到不同url上的相同内容,肯定会降低对此blog的评价。

    所以,当时我想改一下WordPress程序逻辑,当post_id存在但url中的postname不等于数据库中的postname时,返回404页。但是我还没来得及做这个修改,今天惊喜发现WordPress 2.6 (可能更早的版本已经实现了这个修改) 已经会把/(post_id)/(incorrect_postname) 301跳转到 /(post_id)/(postname),这应该比我设计的方案更完好,我非常喜欢WordPress的体贴。