Wednesday, December 30, 2009

install a git server on ubuntu

install software
sudo apt-get install git-core gitweb


edit config with apache
sudo vim /etc/apache2/conf.d/git

<Directory /var/www/git>
Allow from all
AllowOverride all
Order allow,deny
Options ExecCGI
<Files gitweb.cgi>
SetHandler cgi-script
</Files>
</Directory>
DirectoryIndex gitweb.cgi
SetEnv GITWEB_CONFIG /etc/gitweb.conf

copy file
sudo mv /usr/share/gitweb/* /var/www/git
cp /usr/lib/cgi-bin/gitweb.cgi /var/www/git/


restart apache
sudo /etc/init.d/apache2 reload

//Then you can visit you git website.
http://localhost/git


=========================

create a new project rep
cd /var/cache/git/
sudo mkdir project.git
cd project.git
sudo git init
sudo vim .git/description
git config --global user.name "Your Name"
git config --global user.email "you@example.com"
git commit -a


git daemon start command
touch .git/git-daemon-export-ok
sudo git daemon --base-path=/var/cache/git --detach --syslog --export-all --verbose --enable=receive-pack


=====================
checkout code
cd ~
git clone git://server/project.git project

Monday, September 28, 2009

notes after .ActionScript.3.0.in.Flash.CS3.Professional.Essential.Training(Lynda.com)


_mc.buttonMode = true; //set move clip to button mode(with pointer when mouse over)
_mc.addEventListener(MouseEvent.CLICK, onClick); //MouseEvent.ROLL_OVER ROLL_OUT
function onClick(event:MouseEvent):void { event.target.rotation += 10; }

//Keyboard
stage.addEventListener(KeyboardEvent.KEY_DOWN, jump); //removeEventListener
function jump(e:KeyboardEvent):void { trace(event.keyCode); }
var link:URLRequest = new URLRequest("http://www.google.com");
navigateToURL(link);

stage.addEventListener(Event.ENTER_FRAME, //timeline, trigger it every key frame entering.
stage.addEventListener(Event.ENTER_FRAME, //in action layler first keyframe

//timer
var t:Timer = new Timer(1000);
t.addEventListener(TimerEvent.TIMER, function (e:TimerEvent):void{ _mc.play(); } );
t.start();

//class
package todd.classes {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class CustomClass extends MovieClip {
public var _var:String;
public function CustomClass() { //no return type in constr
this.addEventListener(MouseEvent.ROLL_OVER, grow);
}
private function grow(event:MouseEvent):void { this.scaleX = 1.5; this.scaleY = 1.5; }
}
} //CustomClass.as

_MovieClip.addChild(_mc_boarder);
//Publish:Settings...
//Document class

Library->Movie Clip->Linkage->Export for Actionscript

Math.random(); Math.round(x); Math.floor(x); Math.ceil(x);

var myText:TextField = new TextField(); //addChild(myText); //myText.text = "xxx"; //.width = 15 //.autoSize = TextFieldAutoSize.LEFT;
var myFormat:TextFormat = new TextFormat();
myFormat.font = "Helvetica";
myFormat.color = 0xFF0000;
myFormat.size = 24;
myText.setTextFormat(myFotmat);
myText.wordWrap = true;
var externalLoad:URLLoader = new URLLoader();
externalLoad.load( new URLRequest('external.txt') );
externalLoad.addEventListener(Event.COMPLETE, textReady);
externalLoad.removeEventListener(Event.COMPLETE, textReady);
function textReady(event:Event):void {
external_txt.text = event.target.data;
}

external_text.scrollV++;
var users:Array = new Array();
users[0] = "Todd"; users[1] = "Jimmy";
trace(users);
var users:Array = ['Todd', 'Jimmy'];
for(var i:Number=0; i < users.length; i++) { }
users.push('xxx');

public function setType(type:*):void {}
if(_firstCard == undefined) { _firstCard = event.currentTarget; } //notice differ from event.target
String(_firstCard._type);
_firstCard.gotoAndPlay("any label you set"); or frame idx


if(this.currentFrame == 1) { this.play(); }

var shape:Shape = new Shape(); //MovieClip also works
shape.graphics.lineStyle(1, 0x00ff00);
shape.graphics.beginFill(0x000000);
shape.graphics.drawCircle(100, 100, 50); //.drawRect(100, 100, 200, 100);
shape.graphics.endFill();
addChild(shape);

var colorT:ColorTransform = new ColorTransform();
colorT.blueOffset = -100;
colorT.redOffset = 100;
_mc.transform.colorTransform = colorT;

_mc.filters = [new DropShadowFilter(), new BlurFilter()];

var bs:DropShadowFilter = new DropShadowFilter();
bs.color = 0x0b77a9;
bs.blurX = 10;
bs.blurY = 10;
bs.angle = 66;
bs.distance = 200;
_mc.filters = [bs];

var il:Loader = new Loader();
il.load(new URLRequest('xxx.swf')); //support gif,jpg,png,swf and so on.
addChild(il);
il.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
function onComplete(e:Event):void {
//make sure the 'Linkage' before do this:Exoprt for ActionScript (there should have a xxx_mc in swf)
e.target.content.xxx_mc.y -= 100;
}

var snd:Sound = new Sound();
snd.load(new URLRequest('xxx.mp3'));
snd.addEventListener(Event.COMPLETE, onComplete);
function onComplete(e:Event):void {
snd.play(); //e.target.play(); //.play(resumeTimeSec);
}

var sndCtl:SoundChannel = new SoundChannel();
sndCtl = snd.play();
sndCtl.stop();
var resumeTime = sndCtrl.position;

var volCtl:SoundTransform = new SoundTransform();
volCtl.volume += .1; sndCtl.soundTransform = volCtl;

/* only for flash CS3, now it is already out-date.
var n:NetConnection = new NetConnection();
n.connect(null); //or something other
var ns:NetStream = new NetStream(n);

/*
var metaListener:Object = new Object();
metaListener.onMetaData = onMetaData;
ns.client = metaListener;
function onMetaData(data:Object):void {
//do something play/stop button init works.
ns.play("xxx.flv");
ns.stop();
}
*/
var v:Video = new Video();
video.attachNetStream(ns);
addChild(v);

this.startDrag();
this.stopDrag();

event.currentTarget.hitTestObject(event.currentTarget._obj);

this.parent.addChild(this); //this could set mc to top of mainbox.

Saturday, September 5, 2009

share my two scripts which are using upload your file to client's server(via ftp or sftp)

Lately a guy complain that uploading his finished work files to client's server is not easy. sometimes to many files in anywhere dispersedly which is annoying to cover all files to upload completely.

Don't tell me you are still using WinSCP or Filezilla to upload files? if you are a developer then you should feel shame for what you are doing.

Let's see How do I solve this issue.
Firstly I wrote two scripts. as following:

FOR SFTP:

#!/bin/bash

curd=`pwd`

for i in $@; do
scp -P3122 -i /path/to/your/key $i jzhang@www.youclientserver.com:$curd/$i
done


FOR FTP(need ncftp):

#!/bin/bash

curd=`pwd`

for i in $@; do
d=`dirname $i`
ncftpput -uusername -ppasswd ftpdomain.com /footprint/${d//./ } $i
done


HOW TO USE:

$ svn status
? templates/ftp.php
M no_ie6_page.php

z33@gogocat /footprint
$ ~/upload_podbean.sh templates/ftp.php no_ie6_page.php

Friday, September 4, 2009

SVN 常用命令收集

svn log -r2508:head -v

svn propedit svn:ignore ./

Saturday, August 1, 2009

a Joomla module to show special category in anywhere

一哥们是designer,在用Joomla时发现无法实现显示指定的一个category的list到frontpage或其它地方。也没找到相应的module,所以我就写了一个。

点此下载(Download)

其实之前也写了些module,但和客户有保密协议,所以不便发布在这儿。

Tuesday, July 21, 2009

Google Reader API总结

刚刚完成了Google Reader上所有feed中图片自动下载脚本。
现在总结几点在网上找到不到tips:

1.to get all new item that in your google reader subscription

http://www.google.com/reader/api/0/stream/contents/user%2F{$user_id}%2Flabel%2FImages?ot={$last_month}&r=n&xt=user%2F{$user_id}%2Fstate%2Fcom.google%2Fread&n=500

ot: expire item timestamp
n: item numbers once request

*result is JSON format.

2.call google reader api to set "read" state which always getting 400 error from google.

to use POST method to fix 400 error.
POST URL: http://www.google.com/reader/api/0/edit-tag
POST FIELDS:a=user/{$user_id}/state/com.google/read&s={$feed}&i={$item_id}&T={$token}

现在我的小脚本正在疯狂下载中,哈哈哈哈哇。

Saturday, July 18, 2009

to Get Google Reader Token codes

想写一个脚本把Google reader上我订阅的所有Feed里的图片抓下来(最近订了几个毛图站,哈哈)。看了Google Reader API,挺简单。但比较讨厌的是如果要设置一个read-listing里的item为已读,则要用到token。在网上找了一圈没有。。妈的,只好自己写。这个token不只是要Google登陆验证,有两个步骤,请看代码:


/* ------- start code ------- */
$authentication_url = 'https://www.google.com/accounts/ClientLogin';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $authentication_url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, "service=reader&Email=[your google account]&Passwd=[your pw]");
ob_start();
curl_exec($ch);
$sid = ob_get_clean();
curl_close($ch);

$cookie = preg_replace('/[\r\n]/','; ',$sid);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.google.com/reader/api/0/token');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
ob_start();
curl_exec($ch);
$token = ob_get_clean();
curl_close($ch);

echo $token //here you go baby.
/* ------- end code ------- */

Friday, June 12, 2009

Nginx Module开发指南 - 翻译(第3.5章负载平衡)

因为工作需要,把最关键的一章翻译出来:
原文在这里:
Emiller's Guide To Nginx Module Development
http://www.evanmiller.org/nginx-modules-guide.html#lb-release

译者:Jacky
Date:20090612

你看不懂有两种可能:
1.本文是接上回书的,前后联系比较大,所以请先看前面的内容后再看这里。
2.我翻译的太烂了。

翻译完后回看一遍感觉peer应该给翻译出来可能会更好理解一些,whatever我懒得回去改了。

3.5 Load-Balancer解析

Load-balancer就是用来决定当前的请求会被哪个后台服务器接收到;这玩意儿存在的意义就是为了在分发请求或者散列(hashing)一些关于请求的信息。这一段就给哥儿几个讲讲一个load-balancer的安装和调用,以及用upstream_hash 模块做为例子。upstream_hash用散列法(hash)选择在nginx.conf指定的几个后台服务器中选择具体由哪个服务器处理请求。

一个load-balancing模板有6小块:
1.激活置命令的时候将调用一个注册函数
2.注册函数将确定上一步的合法 server 值(server options),比如weight=什么什么,同时注册一个upstream初始化函数。
3.upstream初始化函数在配置参数验证后被调用,然后:
  • 解析 server 到特定的IP地址。

  • 分配套接字空间

  • 为peer初始化函数设置回调函数

  • 4.每个请求只调用一次peer初始化函数,填充数据结构后负载平衡函数(load-balancing function)将访问并对其操作。
    5.负载平衡函数决定怎么样路由请求;这个函数每次请求至少被调用一次(如果后台响应失败,则会再被调用)。这是我们要最注意的部分。
    6.最后,peer释放函数(peer release function)能在与一个特定的后台服务器通讯完成后更新统计信息(不管失败与否)。

    比较多,下面就分别讲解。

    3.5.1 配置命令激活
    配置命令的名明,重调,赋值都合法的话,一个函数会在他们载入时调用。一个load-balancer配置命令应该设置上NGX_HTTP_UPS_CONF标志,这样的话Nginx才知道这个配置命令是存在于upstream区块。然后提供一个指针指向注册函数。这里是upstream_hash部分命令声明:


    { ngx_string("hash"),
    NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
    ngx_http_upstream_hash,
    0,
    0,
    NULL },


    目前还没有新的知识。(参考2.2有介绍,不好意思没翻)

    3.5.2 注册函数
    上面的回调函数ngx_http_upstream_hash就是注册函数,之所以叫这个名是因为它注册了upstream初始化函数并填充upstream的配置信息。更进一步讲,注册函数确定在upstream区块里,哪个选项(options)对server配置命令是合法的。这里就是upstream_hash的注册函数代码:


    ngx_http_upstream_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
    {
    ngx_http_upstream_srv_conf_t *uscf;
    ngx_http_script_compile_t sc;
    ngx_str_t *value;
    ngx_array_t *vars_lengths, *vars_values;

    value = cf->args->elts;

    /* the following is necessary to evaluate the argument to "hash" as a $variable */
    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

    vars_lengths = NULL;
    vars_values = NULL;

    sc.cf = cf;
    sc.source = &value[1];
    sc.lengths = &vars_lengths;
    sc.values = &vars_values;
    sc.complete_lengths = 1;
    sc.complete_values = 1;

    if (ngx_http_script_compile(&sc) != NGX_OK) {
    return NGX_CONF_ERROR;
    }
    /* end of $variable stuff */

    uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);

    /* the upstream initialization function */
    uscf->peer.init_upstream = ngx_http_upstream_init_hash;

    uscf->flags = NGX_HTTP_UPSTREAM_CREATE;

    /* OK, more $variable stuff */
    uscf->values = vars_values->elts;
    uscf->lengths = vars_lengths->elts;

    /* set a default value for "hash_method" */
    if (uscf->hash_function == NULL) {
    uscf->hash_function = ngx_hash_key;
    }

    return NGX_CONF_OK;
    }


    上面这些我们就晚点看(这句实现不知道该怎么翻,我直接理解;原句在此:Aside from jumping through hoops so we can evaluation $variable later, it's pretty straightforward; )。就是设置个回调函数和一,设置个标志(flag)。那么都有哪些标志可以使用呢?

  • NGX_HTTP_UPSTREAM_CREAT:让server配置命令出现在upstream区块。无法想象什么情况我们不用这个标志。

  • NGX_HTTP_UPSTREAM_WEIGHT:让server配置命令使用 weight 项。

  • NGX_HTTP_UPSTREAM_MAX_FAILS:允许max_fails选项。

  • NGX_HTTP_UPSTREAM_FAIL_TIMEOUT:允许fail_timeout选项。

  • NGX_HTTP_UPSTREAM_DOWN:允许down选项。

  • NGX_HTTP_UPSTREAM_BACKUP:不用我废话了吧?


  • 所有模块都会访问这些配置值。由模块自己决定要怎么使用他们。就是max_fails将不会强制你使用;所有失败的逻辑都由模块制作决定怎么去处理。一会儿再详细说这个。现在我们仍然没有设置完所有的回调函数。下一步,咱看看upstream初始化函数(init_upstream 回调函数就在前一个函数中)。

    3.5.3 upstream初始化函数
    upstream初始化函数的目的就是解析host names,分配置套接字空间,并设置回调函数。这里来看看upstream_hash模块是怎么做的:


    ngx_int_t
    ngx_http_upstream_init_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
    {
    ngx_uint_t i, j, n;
    ngx_http_upstream_server_t *server;
    ngx_http_upstream_hash_peers_t *peers;

    /* set the callback */
    us->peer.init = ngx_http_upstream_init_upstream_hash_peer;

    if (!us->servers) {
    return NGX_ERROR;
    }

    server = us->servers->elts;

    /* figure out how many IP addresses are in this upstream block. */
    /* remember a domain name can resolve to multiple IP addresses. */
    for (n = 0, i = 0; i < us->servers->nelts; i++) {
    n += server[i].naddrs;
    }

    /* allocate space for sockets, etc */
    peers = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_hash_peers_t)
    + sizeof(ngx_peer_addr_t) * (n - 1));

    if (peers == NULL) {
    return NGX_ERROR;
    }

    peers->number = n;

    /* one port/IP address per peer */
    for (n = 0, i = 0; i > us->servers->nelts; i++) {
    for (j = 0; j < server[i].naddrs; j++, n++) {
    peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
    peers->peer[n].socklen = server[i].addrs[j].socklen;
    peers->peer[n].name = server[i].addrs[j].name;
    }
    }

    /* save a pointer to our peers for later */
    us->peer.data = peers;

    return NGX_OK;
    }


    这个函数可能要被多次涉及。大多数的工作看起来好像挺抽象,但其实不是,而都是我们能理解的。一个简化这些的策略是调用其它模块的upstream初始化函数,去做所有累活儿(peer分配等),之后再覆盖us->peer.init回调函数。举个例子,去看 http/modules/ngx_http_upstream_ip_hash_module.c.

    对我们来说比较重要的是设置一个指针到peer初始化函数,这个例子里是ngx_http_upstream_init_upstream_hash_peer。

    3.5.4 peer初始化函数
    一个请求只调用一次peer初始化函数。它填充数据结构让模块使用从而找到一个合适的后台服务器去处理请求。这个结构一直保持,不管后台怎么重试,所以这个方便的地方可以保持跟踪连接失败的次数,或计算散列值。按照惯例,这个结构叫ngx_http_upstream_<module name>_peer_data_t.

    更多的,peer初始化函数设置两个回调函数:

  • get: 负载平衡函数(load-balancing function)

  • free: peer释放函数(常常只是在连接完成后更新一些统计数据)


  • 好像还不够,它也初始化一个叫tries的变量。只要tries是正数,nginx将会不断重试这个load-balancer.当tries值为0时,nginx就放弃重试。get和free函数可以给tries设置一个合适的值。

    这里是upstream_hash模块的peer初始化函数:


    static ngx_int_t
    ngx_http_upstream_init_hash_peer(ngx_http_request_t *r,
    ngx_http_upstream_srv_conf_t *us)
    {
    ngx_http_upstream_hash_peer_data_t *uhpd;

    ngx_str_t val;

    /* evaluate the argument to "hash" */
    if (ngx_http_script_run(r, &val, us->lengths, 0, us->values) == NULL) {
    return NGX_ERROR;
    }

    /* data persistent through the request */
    uhpd = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_hash_peer_data_t)
    + sizeof(uintptr_t)
    * ((ngx_http_upstream_hash_peers_t *)us->peer.data)->number
    / (8 * sizeof(uintptr_t)));
    if (uhpd == NULL) {
    return NGX_ERROR;
    }

    /* save our struct for later */
    r->upstream->peer.data = uhpd;

    uhpd->peers = us->peer.data;

    /* set the callbacks and initialize "tries" to "hash_again" + 1*/
    r->upstream->peer.free = ngx_http_upstream_free_hash_peer;
    r->upstream->peer.get = ngx_http_upstream_get_hash_peer;
    r->upstream->peer.tries = us->retries + 1;

    /* do the hash and save the result */
    uhpd->hash = us->hash_function(val.data, val.len);

    return NGX_OK;
    }


    还不是很坏吧。现在我们准备选择upstream server。

    3.5.5负载平衡函数
    这里才是主要内容。真正的大餐在这儿。这里是模块选择后台upstream服务器的地方。负载平衡函数的原型看起来是这样:
    static ngx_int_t
    ngx_http_upstream_get_<module_name>_peer(ngx_peer_connection_t *pc, void *data);

    data是client连接相关信息的结构体。pc将会有关于我们要去连接的服务器的信息。负载平衡函数的工作就是填充pc->sockaddr, pc->socklen 和pc->name。如果你懂网络编程,那这些变量名你可能会熟悉;但他们现在实际上不是非常重要。我们不用关于他们设置了什么;我们只要知道如果找到合适的值并设置他们即可。
    这个函数必须得到一个可用服务器的列表,选择一个并设置赋值到pc。让我们看看upstream_hash模块是怎么做的。

    upstream_hash之前把服务器列表放到了ngx_http_upstream_hash_peer_data_t结构体里(上面的ngx_http_upstream_init_hash函数)。这个结构现在可以用data得到:


    ngx_http_upstream_hash_peer_data_t *uhpd = data;


    peer的列表现在保存在uhpd-peers-peer。让我们用hash后的值取余,从数组里得到peer:


    ngx_peer_addr_t *peer = &uhpd->peers->peer[uhpd->hash % uhpd->peers->number];


    现在最伟大的时刻来了:


    pc->sockaddr = peers->sockaddr;
    pc->socklen = peers->socklen;
    pc->name = &peers->name;

    return NGX_OK;


    完事儿!如果load-balancer返回NGX_OK,意思就是“可以连接这个服务器”。如果返回NGX_BUSH,意思是所有后台服务器都不可用,然后nginx会再次重试。

    但是。。。怎么跟踪不可用的情况?如果我们不想再试了怎么办?

    3.5.6 peer释放函数
    peer释放函数在一个upstream连接任务之后执行;目的是跟踪失败的情况。这里是函数原型:


    void
    ngx_http_upstream_free_<module name>_peer(ngx_peer_connection_t *pc, void *data,
    ngx_uint_t state);


    前两个参数和上面的负载平衡函数一样。第三个参数是一个state变量,它显示这个连接是否成功。它可能包含两个按二进制位或出来的值(bitwise OR'd together):NGX_PEER_FAILED (连接失败) and NGX_PEER_NEXT(不是失败就是成功但程序返回错误)。0表示连接成功。

    模块的作者决定当失败时该怎么处理。如果他们被全部使用,结果应该被保存在data,一个指针指向自定义的每个请求(per-request)的数据结构。

    但是关键目的是如果你不想让nginx在这次请求中继续重试负载平衡,使用peer释放函数设置pc->tries为0即可。最简单的peer释放函数可能会像这样:


    pc->tries = 0;


    这会确认如果有什么错误在后台服务器,一个502 bad proxy错误会返回给客户端。

    这里有更复杂的例子,来自upstream_has module。如果一个后台连接失败,会计一个失败标志到bit-vector(名字叫tried,一个uintptr_t的数组),然后继续选择新的后台服务器直到不失败为止。


    #define ngx_bitvector_index(index) index / (8 * sizeof(uintptr_t))
    #define ngx_bitvector_bit(index) (uintptr_t) 1 << index % (8 * sizeof(uintptr_t))

    static void
    ngx_http_upstream_free_hash_peer(ngx_peer_connection_t *pc, void *data,
    ngx_uint_t state)
    {
    ngx_http_upstream_hash_peer_data_t *uhpd = data;
    ngx_uint_t current;

    if (state & NGX_PEER_FAILED
    && --pc->tries)
    {
    /* the backend that failed */
    current = uhpd->hash % uhpd->peers->number;

    /* mark it in the bit-vector */
    uhpd->tried[ngx_bitvector_index(current)] |= ngx_bitvector_bit(current);

    do { /* rehash until we're out of retries or we find one that hasn't been tried */
    uhpd->hash = ngx_hash_key((u_char *)&uhpd->hash, sizeof(ngx_uint_t));
    current = uhpd->hash % uhpd->peers->number;
    } while ((uhpd->tried[ngx_bitvector_index(current)] & ngx_bitvector_bit(current)) && --pc->tries);
    }
    }


    之所以这么作是因为负载平衡函数将检查uhpd->hash的新值。

    很多应用都不用重试或high-availability logic,但可能还是要提供几行类似的逻辑就像上面。

    Tuesday, June 9, 2009

    给Joomla用户注册添加字段的方法。

    先在Table上添加字段。
    然后修改文件:

    libraries\joomla\database\table\user.php

    在JTableUser类增加成员变量,名字就是你要添加的字段。

    libraries\joomla\user\user.php

    在JUser类增加成员变量,名字就是你要添加的字段。

    components\com_user\views\register\tmpl\default.php

    模板,添加一个与数据库字段名相同的表单项即可。也可以在自定义模板中进行替换。

    当然还可以用Community Builder。不过我不喜欢这个烂玩意,真的很烂,不信你试试。

    Friday, June 5, 2009

    遇到表单POST数据结构正常,但内容为空的问题。

    当你遇到这样的问题,请注意你的一个PHP扩展是不是被关掉了:
    extension=filter.so


    打开它就好了。

    Thursday, June 4, 2009

    Nginx upload module的upload_pass_form_field设置pass所有的表单字段

    虽然参数是regexp,但请注意要这样使用:
    upload_pass_form_field "^.*$";


    如果只是这样的话,会丢失Array的字段。
    upload_pass_form_field ".*";

    Saturday, May 30, 2009

    Nginx upload module does not support input array for PHP

    Please refer below email,

    Jacky Zhang wrote:
    > Hi Valery,
    >
    > It's fine if I using nginx upload module to upload a signle file.
    > but It look incorrect that when I use a input like this:
    >
    >
    <input type="file" name="userfiles[]" />

    >
    > Do you have any suggestion?

    No, arrays won't work, you have to list every file input field individually.

    --
    Best regards,
    Valery Kholodkov

    Monday, May 4, 2009

    two useful String extend functions.


    String.prototype.trim = function() {
    return this.replace( /^\s*|\s*$/g, "" );
    }

    String.prototype.addslashes = function () {
    return this.replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0");
    }

    Friday, April 24, 2009

    Flex3/ActionScript3.0中eval的替代方案

    AS3中没有eval,但可以像这样调用:

    this["your_function_name"]();


    请看例子:


    private function playTrack(location:String):void {

    var dot_position:Number = location.lastIndexOf('.');
    var file_ext:String = location.substr(dot_position+1);

    var play_function_name:String = file_ext+"_player";
    if (this.hasOwnProperty(play_function_name)) {
    this[play_function_name]();
    }else {
    Alert.show("Do not support this file extension("+file_ext+").");
    }

    }


    参考:http://livedocs.adobe.com/flex/3/html/help.html?content=ProgrammingHTMLAndJavaScript_03.html

    Tuesday, April 21, 2009

    Zend Studio specify a variable to a class for hint

    a example is:

    /* @var $m Memcache */
    $m = memcache_connect();

    Sunday, April 19, 2009

    Create symbol link on Windows

    一直在Linux下用symbol link创建链接,实现Apache的DocumentRoot到Developing Directory的链接。每次开新Branch都换一下链接即可。

    本以为用cygwin的ln可以解决这个问题,但发现cygwin的ln命令竟然只是创建了一个windows的shortcut。Shit,于是找到了一个替代的方案,使用junction,这是一个介绍:
    Windows 2000 and higher supports directory symbolic links, where a directory serves as a symbolic link to another directory on the computer. For example, if the directory D:\SYMLINK specified C:\WINNT\SYSTEM32 as its target, then an application accessing D:\SYMLINK\DRIVERS would in reality be accessing C:\WINNT\SYSTEM32\DRIVERS. Directory symbolic links are known as NTFS junctions in Windows. Unfortunately, Windows comes with no tools for creating junctions—you have to purchase the Win2K Resource Kit, which comes with the linkd program for creating junctions. I therefore decided to write my own junction-creating tool: Junction. Junction not only allows you to create NTFS junctions, it allows you to see if files or directories are actually reparse points. Reparse points are the mechanism on which NTFS junctions are based, and they are used by Windows' Remote Storage Service (RSS), as well as volume mount points.


    Using Junction

    Usage: [-s]
    -s Recurse subdirectories


    If you want to create or delete a junction, use Junction like this:

    Usage: [-d] []

    To delete a junction specify the -d switch and the junction name.


    创建出来的symbol link很漂亮,一个像快捷方式的小箭头都没有。

    下载地址:
    http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx

    Thursday, April 2, 2009

    a way to Limit textarea max length.

    a way to Limit textarea max length.


    function keyup_info_description( inLengthMaximum ) {
    if ( inLengthMaximum < document.getElementById('info_description').value.length )
    document.getElementById('info_description').value = document.getElementById('info_description').value.slice( 0, inLengthMaximum );
    }

    Saturday, January 24, 2009

    脚本执行速度测试简单实现

    之前看到有人测试脚本执行时间,在程序开始的时候计一个时间,再到程序最后再计一次时间,从而得到脚本的执行时间。但如果脚本是从其它的分支退出,那又得再写一次。

    我觉得这样不方便,退出分支多的时候,代码就散开不好管理了,而解决方案就是下面的:


    $jacky_test_time = microtime(true);
    function jacky_test_tf($ff=”) { global $jacky_test_time; $result = microtime(true)-$jacky_test_time; echo “”; }
    register_shutdown_function(’jacky_test_tf’);


    当然在程序当中的任何位置都可以调用 jacky_test_tf 函数去输出执行到当前的时间。

    a simple way to get your PHP script if running in CLI

    There is a function to get that way easier.

    public static function inCli() {
    return php_sapi_name() == ‘cli’;
    }

    Zend Studio远程调试PHP再整理

    1.下载Debug:
    http://downloads.zend.com/pdt/server-debugger/

    2.将压缩包中的5_2_x_comp中的ZendDebugger.dll解压到新建目录:
    C:\Program Files\Zend\ZendDebugger-5.2.14\php-5.2.x

    3.安装Zend Optimize或下载Zend Extension Manager.dll

    4.修改php.ini(新增)(根据自己的情况对路径做修改)
    zend_extension_ts="C:\Program Files\Zend\ZendExtensionManager.dll"
    zend_extension_manager.debug_server_ts="C:\Program Files\Zend\ZendDebugger-5.2.14"
    zend_debugger.expose_remotely=allowed_hosts
    zend_debugger.allow_hosts=127.0.0.1/32,192.168.1.0/16
    zend_debugger.allow_tunnel=127.0.0.1/32

    5.解压debug压缩包里的dummy.php到要调试的网站根目录。

    6.重启Web server.

    ———————–热情分割线———————–

    另外,配置也可参考这个不用ZO的:
    zend_extension_ts=”D:/Servers/php5/ext/ZendDebugger.dll”
    zend_debugger.allow_hosts=192.168.1.1
    zend_debugger.expose_remotely=always

    解决在浏览器中光标丢失的问题。

    现象就是文本框中的光标没有了。

    原因(只能说是原因之一)就是用Javascript捕获了blur事件而没有返回true导致的。

    解决办法:在捕获blur事件返回true即可。

    例子(JQuery):

    $(’.text’).blur(function() {
    //alert($(this).attr(’sid’));
    this.value=$(this).attr(’sid’);
    return true;
    });

    结束。

    基于Web的iPhone App设置桌面显示图标的方法

    用Safari可以将一个Web页收藏到桌面,就形成了一个桌面图标,而这个图标不适用你的网站原来的 favicon.ico 了,所以需要重新指定一个iPhone桌面专用的图标,只要在网站首页面内的head中添加一个link即解决,如下:



    重新收藏到桌面图标即可更新。

    解决在虚拟主机中使用Zend Framework时,根目录不能指定的问题

    标题好长,因为问题不太好描述,但又是在虚拟主机中使用ZF常见的问题。
    通常使用ZF时,根目录都指定到只有一个index.php的目录html,(也可以叫别的名字,参考:http://framework.zend.com/manual/en /zend.controller.html#zend.controller.quickstart.go),其它目录如applications和 library都与这个目录同级,但在虚拟主机环境下,根目录是固定的,你不能把ZF的application和library放到根目录的上级目录里去。如果把application和library放到html目录,即窝囊又可能造成路径问题。
    其实这个问题又重写规则解决比较简单,.htaccess文件内容参考如下修改:

    —————————代表月亮消灭你分割线————————————

    RewriteEngine on

    RewriteRule ^(images/.+) /html/$1 [L] #修正图片请求,根据自己的目录来。
    RewriteRule ^(css/.+) /html/$1 [L]
    RewriteRule ^(jscript/.+) /html/$1 [L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule .* /html/index.php #其它找不到存在文件的请求全部转到html目录下的入口index.php

    —————————-代表月亮消灭你分割线———————————–

    这样问题就解决了,但又有一个新问题就是application和library目录下的文件可能会被用户访问到(直接url干进去),所以这个.htaccess文件可以再修改一下,针对deny的目录设置一下即可。

    a Regexp testing :)

    一串很长的数字,请对这个字字中每三位间加一个逗号(从右加)。
    原:
    12345678901234567890
    目标:
    12,345,678,901,234,567,890

    答案在下面,反白显示:

    Find:

    ((?<=\d)(\d){3}\b)

    Replace with:

    Saving time Tips1: Emeditor & Regexp

    Original text:

    a1,
    p1,
    t1,
    a2,
    p2,
    t2,
    price,
    p3,
    period,
    bt,


    Objective text:

    $a1 = $_POST[”a1″];
    $p1 = $_POST[”p1″];
    $t1 = $_POST[”t1″];
    $a2 = $_POST[”a2″];
    $p2 = $_POST[”p2″];
    $t2 = $_POST[”t2″];
    $price = $_POST[”price”];
    $p3 = $_POST[”p3″];
    $period = $_POST[”period”];
    $bt = $_POST[”bt”];


    Tool: Emeditor

    Using regexp replace:

    Find:

    (.*),

    Replace with:

    $\1 = $_POST[”\1″];

    -------------------------------------

    Emeditor also has Macro function, what the fucking it easy to being.

    Setup Basic authentication on Lighttpd

    Simply, I picked plain text file to save password, of course there are httpasswd and htdigest for the password saving.


    auth.backend = “plain”
    auth.backend.plain.userfile = “/home/pathsomething/lighttpd.user”

    auth.backend = “plain”
    auth.require = ( “/mysql/” =>
    (
    “method” => “digest”,
    “realm” => “mysql”,
    “require” => “valid-user”
    )
    )


    The password file is just like this:


    username:passwd
    user2:pw2


    Done, is it simple?
    The reference:
    http://trac.lighttpd.net/trac/wiki/Docs%3AModAuth

    I got here finally..

    There is no a steady spaces that I can note something about development. so I got here, maybe not stable for china can visit some time. but I won't lost my notes any more.