Remote Desktop Access with NX

We connect to remote machines, whatever physical or virtual machines, through SSH in most cases, but occasionally we do need to live with graphical desktop. Yes, VNC is always used here, but.. urh.. VNC is too slow! NX is another option, and the most important thing is that NX is very fast! Fastest I’ve ever seen.

NX is a commercial product from NoMachine, but this company also provides a free edition which limits two connections simultaneously. There is an open source implementation of NX, NeatX, which is developed by Google.

It’s easy to install NeatX on Ubuntu 10.04:

$ sudo apt-add-repository ppa:freenx-team
$ sudo apt-get update
$ sudo apt-get install neatx-server

NX Clients

Several NX clients are available in the market, e.g., opennx, qtnx, and NoMachine’s NX Client, etc.. I tried and found that NX Client from NoMachine is the best one. It supports Windows, Mac OS X, Linux, and Solaris. Go its download page, and get your version.

Posted in Linux | 1 Comment

Google Storage for Developers 初印象

前天收到 Google Storage (GS) for Developers 的注册邀请,我都忘记我曾经提交过申请了,还好 Google 的排队系统记得 :-)   昨晚试用了一下,初印象就是一个类似 Amazon S3 的存储服务。很好,我正好需要一个类似 S3 的在线存储服务。

Google Storage for Developers is a RESTful service for storing and accessing your data on Google’s infrastructure.

简单地说,就是你可以把数据存放在 Google 的云计算基础设施里,并使用 Google 或者第三方提供的一系列 services, APIs, tools 来访问和操作你的数据。

目前可用的工具

Developer Keys

第一次使用 GSUtil 时,会要求提供 Access Key 和 Secret Key。这对 Keys 可以通过 Key Management tool 来创建。

使用 GSUtil

创建 bucket
$ gsutil mb gs://musics
注意遵循 bucket 命名规则

上传对象到 bucket
$ gsutil cp *.mp3 gs://musics
对象通常就是文件夹和文件。

列出 buckets
$ gsutil ls

列出某 bucket 中的对象
$ gsutil ls gs://musics

移动对象
$ gsutil mv gs://musics/*.mp3 gs://newplace/

重命名
$ gsutil mv gs://musics/xyz.mp3 gs://musics/abc.mp3

下载对象到本地
$ gsutil cp gs://musics/*.mp3 file://MyMusics/

删除对象
$ gsutil rm gs://musics/xyz.mp3

删除 bucket
$ gsutil rb gs://musics

开发

如果你需要开发自己的应用使用 GS,目前 Google 提供了一个 Python library,是基于 Boto 改写,GSUtil 使用的也是它。

在 GSUtil 的安装目录下有一个 cloudreader,这是一个 sample app,可以运行在 Google App Engine (GAE) 中。GAE 和 GS 实在是绝佳的搭档。

Posted in Cloud Computing | Tagged , | Leave a comment

Vim

安装:
$ sudo apt-get install vim vim-gnome exuberant-ctags

如果发现 GVim 的中文菜单无法显示,是因为 Ubuntu 中文操作系统的字符集写作 UTF-8,而 GVim 中认定的是 UTF8,做以下字符连接即可:
$ cd /usr/share/vim/vim72/lang
$ sudo ln -s menu_zh_cn.utf-8.vim menu_zh_cn.utf8.vim

安装完基本的 Vim 就可使用了,但要真正用好 Vim,还要根据需求对它进行配置自定义。已经有很多人分享了很好的配置经验,在 Google 中搜索 vimrc 可以找到很多资料。我发现了一个大牛配置,可以拿来学习和作为自己的配置参考。我个人不太喜欢大量地自定义快捷键,还是使用通用的比较好。

Posted in Linux | Tagged | Leave a comment

Mount Remote Windows Share

I’m using CentOS 5.5.

Make sure your Linux has Samba client installed. If not, run the below to install it:
# yum install samba-client

Now mount Windows share:
# mount -t cifs //win_server/share -o username=theuser,password=thepwd /mnt/winshare

-t cifs: file system type. Use smbfs instead if using an old version Linux
//win_server/share: the shared folder on a Windows machine
-o …: used to specify options. Here it’s used to specify the username/password pair to access the share on Windows
/mnt/winshare: the mount point on Linux

Posted in Linux | Tagged , | Leave a comment

Tor on Windows Step by Step

前面写过一篇如何在 Ubuntu Linux 下使用 Tor,不过绝大多数用户还是在使用 Windows 系统,所以还是写一个 Tor 在 Windows 上的攻略。超简单,几张截图就搞掂。

Tor 的官方网站是 torproject.org,已被墙,幸好有很多热心的人建立了镜像网站,比如 tor.hermetix.orgtor.askapache.com 这两个镜像到目前(2010年4月14日)为止在墙内还能访问。进入 下载 页面,选择 Windows 安装套件,下载得到的文件名形如 vidalia-bundle-0.2.1.25-0.2.7.exe

双击该文件启动安装向导。。

选择 Vidalia 和 Tor 组件。那个 Polipo 和 Torbutton 没用,不用选。

选择安装路径,然后点击 Install 按钮即开始安装。

安装完成后,运行 Vidalia,其界面如下图所示。因为目前中国大陆封禁了 Tor 网络,所以通常情况下是无法直接连入 Tor 网络的。当然,有时候不知道是人品太好或者 GFW 间隙休息,偶然也能直接这么连上 Tor 网络的,属于小概率事件。

连不上,没关系,可以通过网桥接入。点击上图中的 Stop Tor 按钮中断连接尝试,然后点击 Settings 按钮打开配置页,切换到 Network 项,选中 My ISP blocks connections to the Tor network,这将打开 网桥配置 Bridge Settings,如下图。从哪里获得可用网桥呢?发一封 email 给 bridges@torproject.org,正文里写 get bridges 即可。几秒钟后,你就会收到一封自动回复,里面有三个分配给你的地址。将你得到的 Bridge 逐一输入,点击 OK 按钮关闭配置页,回到 Vidalia Control Panel,点击 Start Tor 按钮开始连接。

看到状态栏中的小洋葱变绿了,就表示成功接入 Tor 网络了。至此 Tor 安装运行成功,你得到了一个运行在本地的 SOCKS v5 代理服务器 127.0.0.1:9050

下面你需要配置 Firefox 以使用这个 Tor,就不重复了,具体请见前篇帖子第四步

happy exploring!

Posted in Uncategorized | Tagged , | 13 Comments

Subversion

1. 安装

从 tarball 安装:
$ tar jxvf subversion-1.5.7.tar.bz2
$ cd subversion-1.5.7
$ .configure --prefix=/opt/subversion --with-apxs=/opt/apache/bin/apxs
$ make clean
$ make
$ sudo make install

如果在 Debian/Ubuntu 系:
$ sudo apt-get install subversion libapache2-svn

2. 版本库

Subversion 支持单版本库,也支持多版本库。采用单一版本库管理所有项目,或者为每个项目建立一个独立的版本库,都是允许的,不过这两者的做法都有些极端。推荐的做法是,将关联度高的项目放在同一个版本库中管理。

以下步骤中,我将创建一个版本库 psearch,管理着两个项目 core、client。

新建版本库目录
$ cd /data
$ mkdir -p svn-repos/psearch

初始化版本库
$ svnadmin create /data/svn-repos/psearch
这一操作生成必要的目录与文件。版本库创建完成。

3. 添加项目

添加两个项目 core 和 client 到上一步中创建的版本库中。

首先在一个临时目录下建立以下目录结构:
/home/huangys/temp
–core
—-branches
—-tags
—-trunk
–client
—-branches
—-tags
—-trunk

然后用 svn import 指令来进行项目导入:
$ svn import /home/huangys/temp/ file:///data/svn-repos/psearch/ --message "init"
这种方式非常适合于将已经存在的项目迅速导入到版本库中。

说明:以上使用的三个目录名称 trunk、tags、branches 只是一种约定俗成的习惯,它们在 Subversion 中没有特别含义。
“trunk” 是项目的开发主线,你也可以称之为 “main”, “mainline”, “production” 或任何你喜欢的名字;
“branches” 是放置分支的地方;
“tags” 指明一个时间点的快照,与 branches 的区别是 tags 一旦创建不能修改。你也可以用 “releases”, “snapshots”, “baselines” 或任何你喜欢的名字来代替 “tags”。

4. 建立用户

$ htpasswd -b dav_svn.passwd theuser thepwd

这条指令将新建一个用户 theuser,其密码是 thepwd。
用户密码存储在文件 dav_svn.passwd 中,这个文件名可以任意起。如果这个文件当前不存在,加一个 -c 参数即可,如下:
$ htpasswd -cb dav_svn.passwd theuser thepwd

附带,删除用户的指令:
$ htpasswd -D dav_svn.passwd theuser

5. 建立访问控制策略

该策略文件名和放置的位置可随意。这里我起名为 dav_svn.authz,放在 /data/svn-repos/psearch/conf/ 中。

文件内容如下:

[groups]
admins = user1
core_dev = user2, user3
client_dev = user4, user5
 
[/]
@admins = rw
 
[/core]
@core_dev = rw
@client_dev = r
 
[/client]
@core_dev = r
@client_dev = rw
user6 = r

r 表示读,w 表示写,空表示无权限。
@ 起头表示组,没有 @ 符号起头的是具体用户名,* 表示所有人。

6. 配置 Apache

<VirtualHost *:80>
...
ServerName dev.openow.net
...
<Location /svn>
DAV svn
SVNPath /data/svn-repos/psearch
AuthType Basic
AuthName "psearch Subversion Repository"
AuthUserFile /data/svn-repos/psearch/conf/dav_svn.passwd
AuthzSVNAccessFile /data/svn-repos/psearch/conf/dav_svn.authz
Require valid-user
</Location>
...
</VirtualHost>

注1:dav_svn.passwd 和 dav_svn.authz 随便放到哪里都行。
注2:因为这里是经由 Apache HTTP Server 来提供对 Subversion 的访问,所以需要将版本库的拥有者修改为 Apache HTTP Server 的运行者:
$ sudo chown -R apacheuser.apachegroup /data/svn-repos/psearch

最后记得重启 Apache 使之生效。

通过浏览器或者 SVN 客户端工具访问 http://dev.openow.net/svn/ 就可以了。

如果你需要加装 SSL 以保安全,配置 Apache 使用 mod_ssl 即可。

Posted in Linux | Tagged | Leave a comment

Use KefirBB to Extract Text from BBCode String

之前写了一篇帖子介绍如何从字符串中去除 BBCode 标签、提取纯文本信息,使用的是 JBoss Portal format 包,虽然可以解决问题,但非常不完美,比如,无法支持大写标签、无法识别自定义标签等。春节前发现了一个专门用于处理 BBCode 的 Java 库 KefirBB,当时的版本是 0.5,只支持 Java 6,我修改了些源码以支持 Java 5,并发了 patch 给其作者 Kefir。很快 Kefir 发布了新版本 0.6,同时支持 Java 5 & 6.

使用 KefirBB 提取纯文本信息非常简单。首先新建配置文件 kefirbb.xml 并放置到 CLASSPATH 中,其内容如下:

<?xml version="1.0" encoding="UTF-8"?>
 
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://kefir-bb.sourceforge.net/schemas"
xsi:schemaLocation="http://kefir-bb.sourceforge.net/schemas http://kefir-bb.sourceforge.net/schemas/kefir-bb-0.5.xsd">
 
 <code>
 <pattern>[<var/>]</pattern>
 <template/>
 </code>
 
</configuration>

以上配置表示将所有用 中括号 [] 包含起来的部分去除。

然后就可以在 Java 代码中进行操作了:

TextProcessor processor = BBProcessorFactory.getInstance().create();
String txt = processor.process(bbString);

就是这么简单。

其实 KefirBB 的功能远不止如此,通过在配置文件中指明转换规则,KefirBB 可以进行任何文本间的转换。

Posted in Development | Tagged | 1 Comment

翻墙必备神器 Tor

Tor 本来是用来保护用户网络活动隐私与安全的,在中国当下则被大量用于翻墙,这都是被 GFW 所逼啊。我一直以来不太喜欢用 Tor,因为速度慢。不过最近两年 GFW 越来越猖狂,越来越多的国外站点被屏蔽,动不动就是“连接被重置”,让人很是恼火。慢总比没得上好。没办法,在中国上网,就得戴 Tor。

第一步,安装 Tor

不要使用 Ubuntu 软件库中的 Tor 包,因为无人维护、更新不及时。推荐使用 Tor 官方提供的源。

添加 GPG key:
$ gpg --keyserver keys.gnupg.net --recv 886DDD89
$ gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add -

添加 Tor 官方源:

deb http://deb.torproject.org/torproject.org karmic main

我使用的操作系统是 Ubuntu 9.10,其代号是 karmic,请替换成你当前使用的操作系统版本的代号。

安装:
$ sudo apt-get install tor

Tor 提供 Socks 代理,默认情况下,Tor 监听 9050 端口。当然可以修改之。

第二步,配置 bridge

因为 Tor 网络被中国大陆当局禁止,所以默认情况下,你的客户端无法连接到 Tor 网络中去。需要配置 bridge。

打开 Tor 的主配置档 /etc/tor/torrc,在文件尾添加以下内容:

UseBridges 1
UpdateBridgesFromAuthority 1
 
Bridge 80.68.94.202:8080
Bridge 92.206.112.137:9001
Bridge 85.224.100.20:443
Bridge 77.251.74.120:443
Bridge 86.197.68.213:443
Bridge 72.174.8.28:443
Bridge 193.251.40.45:443
Bridge 88.191.48.109:9001
Bridge 193.11.184.83:1338

从哪里得到以上配置文件中出现的服务器地址和端口?有两个方法:

  • 发一封 email 给 bridges@torproject.org,正文里写 get bridges 即可。几秒钟后,你就会收到一封 email,里面有三个分配给你的地址。
  • 打开 https://bridges.torproject.org,每刷新一次就得到三个可用地址。

记得重启 Tor 以使新配置生效:
$ sudo /etc/init.d/tor restart

第三步,使用 Polipo 提供 HTTP 代理 (optional)

你要是细心的话,就会发现在第一步安装 Tor 时也附带安装了一个名为 Privoxy 的软件,它是用来提供 HTTP 代理的,不过 Privoxy 过时了,现在有了更好的 Polipo

卸载 privoxy:
$ sudo apt-get --purge remove privoxy

安装 polipo:
$ sudo apt-get install polipo

配置 Polipo 以使用 Tor:

打开 Polipo 的主配置档 /etc/polipo/config,并去掉以下两行前面的 # 即可:

socksParentProxy = "localhost:9050"
socksProxyType = socks5

重启 Polipo 以使新配置生效:
$ /etc/init.d/polipo restart

默认情况下,Polipo 监听 8123 端口。可以在主配置档中修改它。

第四步,给 Firefox 安装 FoxyProxy 插件

FoxyProxy 现在有两个版本,我们需要使用的是 Standard 版。

安装完毕后,打开 FoxyProxy 选项,启动“Tor 向导”,在提示是否使用 Privoxy 时,选择“不使用”。
然后配置“URL 模式”,输入你想要使用 Tor 代理的网站,比如:blogger, blogspot, facebook, twitter, friendfeed, youtube, wikipedia zh, etc..
如果你安装了 Polipo,这里推荐使用它提供的 HTTP 代理,速度会好一些。打开“代理服务器细节”,修改端口为 8123,同时去除对“SOCKS 代理”项的选择。
最后在工作模式下拉框里选择“使用基于预定义模板的代理服务器”即可。

fxxk GFW! Enjoy!

[UPDATE] 1 Mar 2010
不推荐使用 Polipo 或者 Privoxy 之类的 HTTP 代理,速度并无明显提升。直接使用 Tor 自己的 Socks 代理就好。

Posted in Uncategorized | Tagged , | 2 Comments

Extract Text from BBCode String

正如其名字所暗示的,BBCode 广泛用在论坛程序开发中,比如 phpbbvbb 等。存储在数据库中的字符串往往是混杂 BBCode 的,如何从这些字符串中剔除 BBCode,以提取纯文本信息?如果使用 PHP 语言,有很多现成可用的 PHP BBCode parser。但如果使用 Java 呢?似乎很难找到现成的 Java BBCode parser。当然,可以使用正则表达式来做匹配分析,不过失之繁琐。无意中,在 JBoss Portal v2.6.7 中发现了一个组件可以分析 BBCode,位于 org.jboss.portal.format.* 包中,其 jar 文件是 portal-format-lib.jar

使用方法:

ToTextRenderer render = new ToTextRenderer();
StringWriter writer = new StringWriter();
render.setWriter(writer);
render.render(bbString.toCharArray(), 0, bbString.length());
String txt = writer.toString();

就是这么简单。

不过这个 JBoss Portal format 组件只支持小写的 BBCode,比如 [b] [/b],不支持大写的,比如 [B] [/B]。
可以修改源码包 org.jboss.portal.format.parser.bbcode 中的 Analyzer.flex 来实现对大写的支持:(以下大写均为我所添加)

<YYINITIAL>
{
"[b]" | "[B]" { return token(OPEN_B, null); }
"[/b]" | "[/B]" { return token(CLOSE_B, null); }
"[i]" | "[I]" { return token(OPEN_I, null); }
"[/i]" | "[/I]" { return token(CLOSE_I, null); }
"[u]" | "[U]" { return token(OPEN_U, null); }
"[/u]" | "[/U]" { return token(CLOSE_U, null); }
"[color="(([A-Za-z]+)|("#"[0-9A-Fa-f]{6}))"]" { return token(OPEN_COLOR, yytext().substring(7, yytext().length() - 1)); }
"[COLOR="(([A-Za-z]+)|("#"[0-9A-Fa-f]{6}))"]" { return token(OPEN_COLOR, yytext().substring(7, yytext().length() - 1)); }
"[/color]" | "[/COLOR]" { return token(CLOSE_COLOR, null); }
"[size="[0-9]{1,2}"]" { return token(OPEN_SIZE, yytext().substring(6, yytext().length() - 1)); }
"[SIZE="[0-9]{1,2}"]" { return token(OPEN_SIZE, yytext().substring(6, yytext().length() - 1)); }
"[/size]" | "[/SIZE]" { return token(CLOSE_SIZE, null); }
"[quote]" | "[QUOTE]" | "[Quote]" { return token(OPEN_QUOTE_ANONYMOUS, null); }
"[quote="~["]"] { return token(OPEN_QUOTE, yytext().substring(7, yytext().length() - 1)); }
"[QUOTE="~["]"] { return token(OPEN_QUOTE, yytext().substring(7, yytext().length() - 1)); }
"[Quote="~["]"] { return token(OPEN_QUOTE, yytext().substring(7, yytext().length() - 1)); }
"[/quote]" | "[/QUOTE]" | "[/Quote]" { return token(CLOSE_QUOTE, null); }
"[code]" | "[CODE]" | "[Code]" { return token(OPEN_CODE, null); }
"[/code]" | "[/CODE]" | "[/Code]" { return token(CLOSE_CODE, null); }
"[list]" | "[LIST]" | "[List]" { return token(OPEN_LIST_UNORDERED, null); }
"[list=1]" | "[LIST=1]" | "[List=1]" { return token(OPEN_LIST_ORDERED_NUMERICAL, null); }
"[list=a]" | "[LIST=a]" | "[List=a]" { return token(OPEN_LIST_ORDERED_ALPHABETICAL, null); }
"[/list]" | "[/LIST]" | "[/List]" { return token(CLOSE_LIST, null); }
"[*]" { return token(LIST_ITEM, null); }
"[url"~["]"]~["["]"/url]" { return token(LINK, yytext().substring(4, yytext().length() - 6)); }
"[URL"~["]"]~["["]"/URL]" { return token(LINK, yytext().substring(4, yytext().length() - 6)); }
.|\n { return token(TEXT, yytext()); }
}

使用 JFlex 来生成对应的 Analyzer.java 文件,然后将编译好的 Analyzer.class 放到 portal-format-lib.jar 中替换原先的 class。

另外一个问题是,不支持用户自定义的 BBCode。我还没有找到简单易行的解决方案,以后再想吧。

[UPDATE] 3 Mar 2010
这篇文章已过时,有更好的方法

Posted in Development | Tagged | 1 Comment

Connect Android Phone to LEAP WiFi

Android phone can connect to WiFi wireless network, but it only supports simple authentication, such as WEP key, if WiFi has security settings. There is no support for LEAP in current Android. At least no support in GUI configuration wizard. Lots of users have been requesting this feature (1386, 1871) in Android’s Google Code site. But wait a minute, does Android really not support LEAP? Take a look at WifiConfiguration.AuthAlgorithm in apidocs, there is a constant for LEAP. Yes, Android supports LEAP, but there is not option on GUI configuration.

Enter into CLI mode thru Terminal or ConnectBot, change to root user, and edit the wpa_supplicant.conf file.

# cd /data/misc/wifi
# vi wpa_supplicant.conf

The following is the content of my copy. Successfully connected to my company wireless network.

network={
  ssid="your_ssid"
  key_mgmt=IEEE8021X
  auth_alg=OPEN SHARED LEAP
  eap=LEAP
  identity="your_username"
  password="your_password"
}

[UPDATE] 2 Jun 2010:

My company changed LEAP security from WEP static key to AES/TKIP recently. The above configuration didn’t work anymore. Now I’m using the following configuration:

network={
  ssid="your_ssid"
  key_mgmt=WPA-EAP
  group=CCMP TKIP
  eap=LEAP
  identity="your_username"
  password="your_password"
}

By the way, this configuration works well on Android 1.5, 1.6, and 2.1.

Have fun.

Posted in Android | Tagged | 26 Comments