使用pirum管理私有的Pear库

1、先装pirm。
pear channel-discover pear.pirum-project.org
pear install pirum/Pirum

2、配置nginx放置pear虚拟主机,root路径为:/path/to/pear
2.1、在/path/to/pear下建立pirum文件,内容为:


pear.pirum-project.org

Pirum PEAR channel

pirum
http://pear.pirum-project.org/

2.2、pirum build /path/to/pear

3、装备php库文件,比如
3.1、库文件目录准备package.xml文件。
3.2、编辑php文件;
3.3、修改package.xml文件
3.4、使用pear package打包成.tgz文件
3.5、使用pirum add /path/to/pear xxxx.tgz

4、使用pear库
4.1、访问私有的pear web地址,上面有例子

一个简单的golang http.ServeMux实现restful

用来了解http.ServeMux的大概工作过程和实现方法,代码如下:

// go 1.7

package main

import (
	"io"
	"log"
	"net/http"
)

type restful struct {
	m map[string]func(w http.ResponseWriter, r *http.Request)
}

func newRestful() *restful {
	return &restful{make(map[string]func(w http.ResponseWriter, r *http.Request))}
}

func (mux *restful) get(pattern string, callback func(w http.ResponseWriter, r *http.Request)) {
	mux.m["GET"+pattern] = callback
}

func (mux *restful) post(pattern string, callback func(w http.ResponseWriter, r *http.Request)) {
	mux.m["POST"+pattern] = callback
}

func (mux *restful) notFound(callback func(w http.ResponseWriter, r *http.Request)) {
	mux.m["notFound"] = callback
}

func (mux *restful) before(callback func(w http.ResponseWriter, r *http.Request)) {
	mux.m["before"] = callback
}

func (mux *restful) after(callback func(w http.ResponseWriter, r *http.Request)) {
	mux.m["after"] = callback
}

func (mux *restful) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	method := r.Method + r.URL.Path
	if _, k := mux.m[method]; k {
		if mux.m["before"] != nil {
			mux.m["before"](w, r)
		}
		mux.m[method](w, r)
	} else {
		if mux.m["notFound"] != nil {
			mux.m["notFound"](w, r)
		} else {
			w.WriteHeader(404)
		}
		return
	}
	if mux.m["after"] != nil {
		mux.m["after"](w, r)
	}
}

func notFound(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
	return
}

func before(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "before runing...\n")
}

func after(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "after runing...\n")
}

func test(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "test running....\n")
}

func index(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "index running....\n")
}

func main() {
	mux := newRestful()
	mux.get("/", index)
	mux.get("/test", test)
	mux.before(before)
	mux.after(after)
	mux.notFound(notFound)

	err := http.ListenAndServe(":8091", mux)
	if err != nil {
		log.Fatal(err)
	}
}

 

JAVA实现和PHP兼容的hash_pbkdf2函数

PHP:

使用内置函数:hash_pbkdf2();

PHP代码如下:


JAVA代码如下:

import java.io.*;
import java.net.*;
import java.math.BigInteger;


import javax.crypto.*;
import javax.crypto.spec.*;


static public String hash_pbkdf2(String algorithm, String password, String salt, int iterations, int len) throws Exception {
  PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), iterations, len * 4);
  SecretKeyFactory kFactory = SecretKeyFactory.getInstance(algorithm);
  SecretKey key = kFactory.generateSecret(pbeKeySpec);
  byte[] res = key.getEncoded();
  return toHex(res);
}

private static String toHex(byte[] array){
  BigInteger bi = new BigInteger(1, array);
  String hex = bi.toString(16);
  int paddingLength = (array.length * 2) - hex.length();
  if(paddingLength > 0)
    return String.format("%0" + paddingLength + "d", 0) + hex;
  else
    return hex;
}


hash_pbkdf2(“PBKDF2WithHmacSHA1”, password, salt, 1024, 32);

这时PHP和JAVA输出结果一致

Mikrotik ROS做策略路由

因为工作需要翻墙出逃,网关是一台RB951G-2HnD,ROS版本是:6.22,需要对指定的某些IP段走VPN线路出去。

有两种方案:

1、在IP routes里手工增加静态路由,但是如果IP段很多,这样很麻烦,而且路由表里特别多。

2、配合ip firewall做策略路由,具体配置如下:

2.1、在ip Firewall中打开Address List配置,需要通过VPN路由出去的IP段,如下图:

2.2、在Mangle中对需要走VPN出去的包打标签,如下图:

2.3、一般我们已经提前做好了NAT或者masquerade,但是这里要注意一下,做masquerade或者snat的时候不要指定网卡接口。

/ip firewall nat add chain=srcnat action=masquerade

即可。

2.4、进入ip routes,增加一个0.0.0.0/0的路由项,并且Routing Mark选择刚才在ip firewall里定义的New Routing Mark的名字,截图如下:

2.5、OK,以后所有在ip firewall > addresss list > 中定义的FW的IP段都会走VPN出去。

 

一般家用路由器仅作为AP使用,扩展无线漫游

公司有两台限制的NetGear WGR614 150M的无线路由,限制废物利用,将他们配置为纯AP,并且接入现有的无线网络中,多了两个无线漫游的接入点。

以前公司的无线SSID是:WLAN1401,使用WPA2 PSK/aes ccm方式加密,密码是:mywifi98,现有网络是192.168.248.0/24,并且网络中已经存在DHCP Server。

因为没有网线可以插入MAC笔记本,所以所有的配置均在无线的情况下完成,具体步骤如下:

1、保证自己的笔记本处于不能搜索不到WLAN1401信号的环境下(否则后面无线漫游调试的时候会冲突);

2、先按住WGR614背板天线位置的reset键几秒,当电源灯开始黄色闪烁的时候松开,系统被重置。

3、扫描无线网络,应该会出现默认的SSID:NETGEAR,并且是没有密码的,连接上;

4、输入路由器管理地址,http:/192.168.1.1/(一般是这个),账号:admin,密码:password

5、进入管理界面,先找到无线配置界面,把SSID,加密方式修改和现有WLAN1401一样的配置。注意频道的选择,一般使用1、6、13等不冲突的频段。保存,重启。

6、这时候搜索新的无线,会找到WLAN1401,连接进去(如果也能连接到现存的WLAN1401的话,这里就会冲突)。

7、进入LAN设置,注意,这里把LAN的IP地址改成现存网络 WLAN1401中的一个地址,但不要和现有的已使用的IP地址冲突,比如改成:192.168.248.2/24。保存,重启。

8、路由器重启后重新连入wifi,并且进入管理界面,依然进LAN设置里,把LAN的DHCP关闭,保存,重启。

9、把设置完成的WGR614中的LAN口中接入现有的网络的交换机即可,这个AP即可以开始工作。

10、以后可以通过192.168.248.2来管理它。

以上,第7步可以跳过,但是这样以后就没法管理它了,只能重置,另外在这里WAN口是始终不用的。

其他路由器没有测试,应该类似操作就可以配置完成,可以在局域网内做多个无线漫游接入点。

 

prefixfree与animatable。

无意间发现个好东西,之前我们写CSS3标签的时候,针对不同浏览器一般要写各自不同的前缀,比如-webkit,-moz等前缀,如果css负责,会很恼火:

-prefix-free lets you use only unprefixed CSS properties everywhere. It works behind the scenes, adding the current browser’s prefix to any CSS code, only when it’s needed.

官网地址:http://leaverou.github.io/prefixfree/

同一个作者又做了一套针对CSS3动画的封装

http://leaverou.github.io/animatable/

使用只需要利用A标签和自定义属性就可以完成动画,比如

<a data-property=”border-radius” data-from=”0 100%” data-to=”100% 0″></a>

有兴趣的朋友甚至可以有针对性的进行扩展,来维护自己的一套常用的动画LIB。

 

最简单的flash上传文件代码

package
{
	import flash.display.*;
	import flash.text.*;
	import flash.events.DataEvent;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.external.ExternalInterface;
	import flash.media.Camera;
	import flash.media.Microphone;
	import flash.net.XMLSocket;
	import flash.net.FileReference;
	import flash.net.URLRequest;
	import flash.net.URLVariables;
	import flash.events.MouseEvent;

	public class uploadify extends Sprite {

	private var xmlSocket:XMLSocket;
	private var fileRef:FileReference;
	private var url:String = "/path/to/upload";
	private var request:URLRequest = new URLRequest(url);
	private var param:Object = root.loaderInfo.parameters; // 取得FlashVars后面的所有参数
	
	public function uploadify():void {
		this.height = 25;
		this.width = 65;
		ExternalInterface.call("onLog",url);
		ExternalInterface.marshallExceptions = true;

		fileRef = new FileReference();
		fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onError);
		fileRef.addEventListener(IOErrorEvent.IO_ERROR,onIoError);
		fileRef.addEventListener(Event.SELECT,onSelect);
		fileRef.addEventListener(Event.OPEN,onUpload);
		fileRef.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,onComplete);
		ExternalInterface.call("onReady");

		var btn:Sprite = new Sprite();
		btn.graphics.beginFill(0xFFCC00);
		btn.graphics.drawRect(-100, -100, 1000,1000);
		this.addChild(btn);

		var text1:TextField = new TextField();
		text1.htmlText = param["text"];
		text1.selectable = false;
		text1.autoSize = TextFieldAutoSize.LEFT;
		text1.border = false;

		this.addChild(text1);

		text1.addEventListener(MouseEvent.CLICK,mouseOverListener);

	}

	private function mouseOverListener(e:MouseEvent):void{
		fileRef.browse();
	}

	private function onSelect(e:Event):void{
		url = param["url"];
		request = new URLRequest(url);
		fileRef.upload(request);
	}

	private function onComplete(e:DataEvent):void{
		ExternalInterface.call("onComplete",e.data.toString());
	}

	private function onUpload(e:Event):void{
		ExternalInterface.call("onUpload",e.toString());
	}

	private function onIoError(e:IOErrorEvent):void{
		ExternalInterface.call("onError",e.toString());
	}

	private function onError(e:SecurityErrorEvent):void{
		ExternalInterface.call("onError",e.toString());
	}

}

源码下载:uploadify