• 2009-06-18

    sqlite

    试了下sqlite,感觉比key-value的数据库要爽些,毕竟比较熟悉SQL。这个api也比tokyocabinet,bdb的好看多了。尤其tokyocabinet的,感觉有点丑陋。

     

    准备写个记账的软件,因为gnucash实在是太大块了,除了记账其他功能我也用不着,有些功能它又没有。

    不过不知道怎样导出gnucash的数据,据说是xml的,但我打开发现是二进制的。不知咋的。嗯,写好了再说。

  • 2009-06-15

    NILFS浅尝

    今天把内核升级到了2.6.30,内核加载快了很多。原来要3s+,现在是1.9s。不知道怎么回事 ^ ^

    启用了nilfs文件系统,被其能恢复删除的文件的特性吸引。虽然不明白原理,只是想把玩下。

    emerge了nilfs-utils后,删除了一个空的ext4分区,格成nilfs的。复制了一个大文件过去,从ext4分区,速度是30M/s左右,还算不错。

    snapshot功能:

    用lscp命令可以显示所有的check point

    check point是不可以mount的,要先转成snapshot

    然后再mount上snapshot:

    于是被删掉的文件又出现了。虽然只是只读的,,

    嗯,觉得还不错。只是还不算稳定吧。毕竟在内核里面还是experimental的(一开始还死活找不到哪里启用,没开prompt for experimental xxx)

     

  • 2009-06-09

    Linux下的C编程

    包括基础的系统编程,还有gtk的基础。于是写了2个实用的小程序:

    程序用ImageMagick转换成了图片 : convert -font "Courier" -pointsize 18 label:@/home/reus/gtk/tray.c tray.png

    自动更换壁纸:

    定时弹出:

  • 2009-05-26

    fuckgfw

    本文将提供一种一劳永逸的翻墙方式(ssh -D),实施之后,那道墙——对你来说——将从此透明。

    本文面向的用户:使用Windows作为操作系统并且使用Firefox作为常用浏览器。

    第一步:免费获取拥有SSH权限的帐号和密码。

    默认的免费获取方式:将本文转载到你自己的博客上,将转载后的文章网址发送到f.ckgfw#gmail.com

    转载方式:拷贝文章代码至博客后台HTML编辑器中,直接发布即可,文章标题自拟,可在前后文插入自己的评论。

    经过人工审核,你将收到一封附有五个拥有SSH权限的帐号和密码的电子邮件,你可以将它们赠与你信任的人。

    更多获取方式将在今后陆续激活,请关注我们的最新更新:https://friendfeed.com/fuckgfw

    第二步:配置MyEnTunnel软件

    下载并安装MyEnTunnel,该软件全名为My Encrypted Tunnel。

    一键下载:https://dl.getdropbox.com/u/873345/download/myentunnel.exe

    myentunnel

    按照上图将第一步收到的帐号信息填写到相应的地方后,点击save按钮,再点击hide按钮。

    第一次连接过程中会出现一个认证对话框,按照提示确认即可。以后的自动连接中将不再出现此认证对话框。

    最后点击hide按钮,使对话框隐藏到系统任务栏中。

    提示:

    为MyEntunnel创建一个快捷方式,将其复制到系统的【启动】(C:\Documents and Settings\当前用户名(需要修改成你自己的)\「开始」菜单\程序\启动)文件夹中,今后开机便可自动启动软件,并自动连接服务器。

    tray

    绿色代表连接成功且稳定;黄色代表正在连接或重新连接;红色代表连接失败。

    第三步:配置Firefox浏览器

    假设你正使用Firefox浏览器阅读本文。

    一键安装:http://autoproxy.mozdev.org/latest.xpi

    xpi-offical

    点击立即安装,安装后,重新启动Firefox。然后你会看到如下对话框,选择gfwlist (P.R.China)后,点击确定。

    gfwlist

    接着你会看到Firefox主界面右上角出现有一个“福”字图案,点击“福”。

    fu

    点击“代理服务器——编辑代理服务器”。

    edit

    随即出现如下画面,你会看到如GAppProxy、Tor和Your Freedom这样一系列代理服务器名称。

    before

    将GAppProxy一栏的参数修改为如下图所示。

    after

    修改完毕后,点击确定。至此配置已全部就绪。

    获取更多帮助,请关注反馈中心:https://friendfeed.com/fuckgfw-feedback

    Bernie:"Eat me!"

    第四步:支持fuckGFW

    1. 如果您翻墙成功,请大笑一声并用充满磁性地低音说出:Hello, world!
    2. 如果由于线路原因,始终翻墙不成,不要气馁,给我们发Email,咱们一起解决问题。
    3. 假如哪天突然无法正常连接,请先到反馈中心汇报,我们会及时做出反应。
    4. 目前您有如下几种方式及时获取我们的最新动态:FriendFeed | Twitter | Blog
    5. 保持默契,我们相信您一定可以做到。

    版权信息:您可以自由复制、传播、演绎本作品且无需署名、无需注明原始出处。

  • 就是把一段html分成几段,标签都能够匹配上(呃……其实试下就知道,说不太明白)
    主要用于长文章的分页。
    function html_subsection($input, $length = 300) {
    $ret = array();
    $res = '';
    $unclosed_tags = array();
    $cur_length = 0;
    $index = 0;
    while ($token = _get_next($input, $index, $length)) {
    $res .= $token;
    $cur_length += mb_strlen($token, 'utf8');
    if ($token[0] == '<' && $token[1] != '/' && mb_substr($token, mb_strlen($token, 'utf8') - 2, 1, 'utf8') != '/') {
    array_push($unclosed_tags, $token);
    }
    else if ($token[0] == '<' && $token[1] == '/') {
    $tag_in_stack = array();
    preg_match('/^<([a-zA-Z]*)/', $unclosed_tags[sizeof($unclosed_tags) - 1], $tag_in_stack);
    $tag_in_stack = $tag_in_stack[1];
    $tag_in_token = array();
    preg_match('/^<\/([a-zA-Z]*)/', $token, $tag_in_token);
    $tag_in_token = $tag_in_token[1];
    if ($tag_in_stack == $tag_in_token) {
    array_pop($unclosed_tags);
    }
    }
    if ($cur_length > $length) {
    for ($i = sizeof($unclosed_tags) - 1; $i >= 0; --$i) {
    $close_tag = array();
    preg_match('/^<([a-zA-Z]*)/', $unclosed_tags[$i], $close_tag);
    $close_tag = $close_tag[1];
    $close_tag = "";
    $res .= $close_tag;
    }
    $ret[] = $res;
    $res = '';
    $cur_length = 0;
    for ($i = 0; $i != sizeof($unclosed_tags); ++$i) {
    $res .= $unclosed_tags[$i];
    }
    }
    }
    for ($i = 0; $i != sizeof($unclosed_tags); ++$i) {
    $ret[sizeof($ret) - 1] .= $unclosed_tags[$i];
    }
    return $ret;
    }
    function _get_next($input, &$index, $max_length) {
    if ($index >= mb_strlen($input, 'utf8')) {
    return false;
    }
    if (mb_substr($input, $index, 1, 'utf8') == '<') {
    $next_index = mb_strpos($input, '>', $index, 'utf8') + 1;
    $res = mb_substr($input, $index, $next_index - $index, 'utf8');
    $index = $next_index;
    }
    else {
    $next_index = mb_strpos($input, '<', $index, 'utf8');
    if ($next_index - $index > $max_length) {
    $next_index = $index + $max_length;
    }
    $res = mb_substr($input, $index, $next_index - $index, 'utf8');
    $index = $next_index;
    }
    return $res;
    }
  • 2009-04-11

    强力推荐Drupal

    http://www.drupal.org

    这不仅仅是一个CMS,其实是一个开发框架,伪装成CMS的开发框架。OY

  • 2009-04-11

    做了个模板

    就是现在用的这个~

    点击下载

  • 用的是lua+wxlua,wxWidget的lua模块:

    今天的成果 = =

     

     

    require 'wx'

    -- 创建 frame
    local frame = wx.wxFrame(wx.NULL,
    wx.wxID_ANY,
    '啊啊啊哦哦哦',
    wx.wxPoint(450, 450),
    wx.wxSize(300, 300)
    )
    local icon_xpm = {
    --/* columns rows colors chars-per-pixel */
    "32 32 6 1",
    " c black",
    ". c navy",
    "X c red",
    "o c yellow",
    "O c gray100",
    "+ c none",
    --/* pixels */
    "++++++++++++++++++++++++++++++++",
    "++++++++++++++++++++++++++++++++",
    "++++++++++++++++++++++++++++++++",
    "++++++++++++++++++++++++++++++++",
    "++++++++++++++++++++++++++++++++",
    "++++++++ ++++++++++",
    "++++++++ ............ ++++++++++",
    "++++++++ ............ ++++++++++",
    "++++++++ .OO......... ++++++++++",
    "++++++++ .OO......... ++++++++++",
    "++++++++ .OO......... ++++++++++",
    "++++++++ .OO...... ",
    "++++++++ .OO...... oooooooooooo ",
    " .OO...... oooooooooooo ",
    " XXXXXXX .OO...... oOOooooooooo ",
    " XXXXXXX .OO...... oOOooooooooo ",
    " XOOXXXX ......... oOOooooooooo ",
    " XOOXXXX ......... oOOooooooooo ",
    " XOOXXXX oOOooooooooo ",
    " XOOXXXXXXXXX ++++ oOOooooooooo ",
    " XOOXXXXXXXXX ++++ oOOooooooooo ",
    " XOOXXXXXXXXX ++++ oOOooooooooo ",
    " XOOXXXXXXXXX ++++ oooooooooooo ",
    " XOOXXXXXXXXX ++++ oooooooooooo ",
    " XXXXXXXXXXXX ++++ ",
    " XXXXXXXXXXXX ++++++++++++++++++",
    " ++++++++++++++++++",
    "++++++++++++++++++++++++++++++++",
    "++++++++++++++++++++++++++++++++",
    "++++++++++++++++++++++++++++++++",
    "++++++++++++++++++++++++++++++++",
    "++++++++++++++++++++++++++++++++"
    };
    local bitmap = wx.wxBitmap(icon_xpm)
    local frame_icon = wx.wxIcon()
    frame_icon:CopyFromBitmap(bitmap)
    frame:SetIcon(frame_icon)
    bitmap:delete()
    frame_icon:delete()

    -- 创建一个menu
    local menu = wx.wxMenu()
    menu:Append(0, '你好', "嘿嘿")
    menu:Append(11, '置中', '窗口置中')
    menu:Append(1, '退出', '退出程序')

    -- 创建menubar,并加入menu
    local menu_bar = wx.wxMenuBar()
    menu_bar:Append(menu, 'Menu')
    frame:SetMenuBar(menu_bar)

    -- 菜单的事件
    frame:Connect(0, wx.wxEVT_COMMAND_MENU_SELECTED, function(event) print("呵呵") end)
    frame:Connect(1, wx.wxEVT_COMMAND_MENU_SELECTED, function(event) frame:Close(true) end)
    frame:Connect(11, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
    frame:Centre();
    end)

    -- 显示状态栏,并设置文字
    frame:CreateStatusBar()
    frame:SetStatusText('Welcome! 欢迎!')

    -- 创建工具栏
    frame:CreateToolBar()

    -- 时间类
    local time = wx.wxDateTime():SetToCurrent()
    if (time:IsWorkDay()) then
    print("go to work!")
    else
    print("have a good weekend")
    end
    -- 时间菜单
    local time_menu = wx.wxMenu()
    time_menu:Append(2, '现在时间', '显示现在的时间')
    menu_bar:Append(time_menu, '时间')
    frame:Connect(2, wx.wxEVT_COMMAND_MENU_SELECTED, function(event)
    time:SetToCurrent()
    print(time:FormatDate(), time:FormatTime())
    end)

    -- 目录类
    local dir = wx.wxDir(wx.wxGetCwd())
    local cont = dir:GetFirst()
    while cont do
    cont = dir:GetNext()
    end

    -- 创建panel
    local panel = wx.wxPanel(frame, wx.wxID_ANY)

    -- 创建button
    local exit_button = wx.wxButton(panel, wx.wxID_EXIT, '退出',
    wx.wxPoint(15, 5),
    wx.wxSize(80, 30))
    frame:Connect(wx.wxID_EXIT, wx.wxEVT_COMMAND_BUTTON_CLICKED, function(event)
    frame:Close(true);
    end)

    -- 进度条
    local gauge = wx.wxGauge(panel, wx.wxID_ANY, 100,
    wx.wxPoint(15, 40),
    wx.wxSize(250, 30))
    local increase_button = wx.wxButton(panel, 20, '+',
    wx.wxPoint(100, 5),
    wx.wxSize(40, 30))
    local decrease_button = wx.wxButton(panel, 21, '-',
    wx.wxPoint(145, 5),
    wx.wxSize(40, 30))
    frame:Connect(20, wx.wxEVT_COMMAND_BUTTON_CLICKED, function(event)
    if gauge:GetValue() < gauge:GetRange() then
    gauge:SetValue(gauge:GetValue() + 5)
    end
    end)
    frame:Connect(21, wx.wxEVT_COMMAND_BUTTON_CLICKED, function(event)
    if gauge:GetValue() ~= 0 then
    gauge:SetValue(gauge:GetValue() - 5)
    end
    end)

    -- 显示frame并进入主循环
    frame:Show(true)
    wx.wxGetApp():MainLoop()

  • 下面是PHP代码:

    define('SINGLE_THREAD', false);
    $thread = time() * 100 + rand(0, 99);
    
    global $db;
    $db = new mysqli('localhost', '', '', '');
    $db->query("SET NAMES UTF8");
    if (SINGLE_THREAD) {
    	$db->query("UPDATE member SET lock_s=0");
    }
    $no_rows = 0;
    while (true) {
    	$sql = "UPDATE member SET lock_s=1,thread='$thread' WHERE lock_s=0 AND protected=0 LIMIT 20";
    	$db->query($sql);
    	if ($db->affected_rows > 0) {
    		$no_rows = 0;
    		$sql = "SELECT * FROM member WHERE lock_s=1 AND thread='$thread'";
    		$res = $db->query($sql);
    		while ($row = $res->fetch_array()) {
    			user($row['id'], "http://api.fanfou.com/users/friends.json?id=$row[id]", "relation");
    			user($row['id'], "http://api.fanfou.com/users/followers.json?id=$row[id]", "follow");
    			$db->query("UPDATE member SET lock_s=2 WHERE id='$row[id]'");
    		}
    	}
    	else {
    		sleep(16);
    		++$no_rows;
    		if ($no_rows > 100) {
    			print "$no_rows\n";
    			exit();
    		}
    	}
    }
    
    function user($user_id, $api_url, $table) {
    	global $db;
    	$page = 1;
    	$friends = json_decode(@file_get_contents($api_url . "&page=$page"));
    	while (!empty($friends)) {
    		foreach ($friends as $f) {
    			if ($f->protected) {
    				$f->protected = 1;
    			}
    			else {
    				$f->protected = 0;
    			}
    			$sql = "INSERT INTO member VALUES (
    				'" . $f->id . "',
    				'" . $f->name . "',
    				'" . $f->screen_name . "',
    				'" . $f->location . "',
    				'" . $f->description . "',
    				'" . $f->profile_image_url ."',
    				'" . $f->url . "',"
    					. $f->protected . ","
    					. $f->followers_count . ",
    				0,
    				'0'
    					)";
    			$db->query($sql);
    			if ($table == 'follow') {
    				$sql = "INSERT INTO $table VALUES (
    					'" . $f->id . "',
    					'$user_id'
    						)";
    			}
    			else {
    				$sql = "INSERT INTO $table VALUES (
    					'$user_id',
    					'" . $f->id . "'
    						)";
    			}
    			$db->query($sql);
    		}
    		++$page;
    		$friends = json_decode(@file_get_contents($api_url . "&page=$page"));
    	}
    }
    

    ==============下面是数据表定义=============

    follow

    字段 类型 Null 默认 注释
    lid char(128)    
    rid char(128)    

    member

    字段 类型 Null 默认 注释
    id char(255)    
    name char(255)    
    screen_name char(255)    
    location char(255) NULL  
    description text NULL  
    image char(255) NULL  
    url char(255)    
    protected int(1) 0  
    followers int(16) 0  
    lock_s int(1) 0  
    thread char(12) 0  

    relation

    字段 类型 Null 默认 注释
    lid char(128)    
    rid char(128)    

    =================今天先到这,详细的以后再说 = = ==================

  • 2009-02-17

    lisp解释器

    嘛……我不懂lisp,能实现的就是我懂的(就是,,只是四则运算) = =!

  • http://www.psucc.com/fanfou/

    刚写的,新鲜热辣

  • 2009-02-09

    lift

    impressive

  • 听不错的,说得很明白

  • 2009-02-02

    wordpress

    看了下docs,大致熟悉了plugin的开发,熟悉下action和filter和funtions就可以了。

  • 2009-01-31

    dropbox

    好东西,推荐之。

    安装,设置完之后,默认在home目录生成一个文件夹

    这个文件夹的存取跟其他文件夹是一样的,只不过就多了同步内容到服务器的功能。

    比如我就将gnucash和ff的scrapbook的扩展的工作目录都设进去。这样在更新帐本或者新截取网页后,都能和服务器同步。

    同步是增量的,会先比较新旧文件,只传输不同的部分。

    文件夹内容变更时,状态栏会有图标指示:

    同步完成后的图标:

    总容量是2GB,也有50GB的,不过要$99一年。我网络是茂名电信100M的,速度50K左右。传小文件还凑合。

    支持windows,mac,linux

  • 效果:(就拿moon老大的把 =v=)

  • 2009-01-29

    All about monads 01

     

  • 2009-01-29

    All about monads 00

     


     

  • 在programming in lua那个的基础上改了加上缩进的版本:

     function serialize(object, level)
        if type(object) == 'string' then
            return string.format('%q', object)
        elseif type(object) == 'number' then
            return object
        elseif type(object) == 'table' then
            local ret = {}
            ret[#ret+1] = '{\n'
            for k, v in pairs(object) do
                for i = 1, level do
                    ret[#ret+1] = '\t'
                end
                ret[#ret+1] = '['
                ret[#ret+1] = serialize(k, level + 1)
                ret[#ret+1] = '] = '
                ret[#ret+1] = serialize(v, level + 1)
                ret[#ret+1] = '\n'
            end
            for i = 1, level - 1 do
                ret[#ret+1] = '\t'
            end
            ret[#ret+1] = '}'
            return table.concat(ret)
        end
    end

    a = {
        abcd = 'fdsa',
        'fdasdfas',
        531,
        {
            ['fdsa'] = 'fdsa',
            35,
            {
                ['fdsa'] = 341,
                41,
            },
        },
        33,
    }
    print(serialize(a, 1))