AJAX架构之Dojo篇

出处【饮水思源】: http://www.51ajax.com/

一、前言
自去年开始,AJAX一下成了关注的技术热点,各种AJAX框架迅速的发展了起来,其中又分为客户端AJAX架构,服务器端AJAX架构等,其中DojoToolkit做为一个优秀的客户端AJAX架构,被越来越多的人所关注,学习。自去年开始,AJAX一下成了关注的技术热点,各种AJAX框架迅速的发展了起来,其中又分为客户端AJAX架构,服务器端AJAX架构等,其中DojoToolkit做为一个优秀的客户端AJAX架构,被越来越多的人所关注,学习。

二、Dojo简介

作为早期的开源AJAX架构之一,Dojo开始于2004年9月,网址是 http://www.dojotoolkit.org,由JotSpot的Alex Russell所领导。

Dojo是一个开源的JavaScript工具包,本身预置了很多模块,可以实现完整的轻量级窗口组件及很多功能。Dojo的包加载机制(Package System)可以实现动态加载所需模块,而且用户可以编写自己的Dojo扩展模块,有很好的灵活性。

三、技术特点

1.文件结构

Dojo目前最高版本号是0.3.1,它的文件主要由一个包含主要功能的核心代码文件(Dojo.js)和众多的Javascript文件组成。使用时可以根据包机制,动态载入所需模块。

根据核心代码包含模块的不同,又细分为以下多个版本:
·AJAX版本:可以创建带有AJAX应用程序,集成复杂的可视效果,并使用事件模块。
·Widget版本:包括与小器件实现松散耦合的 HTML 和CSS 模板能力,提供明确分离的样式、内容和逻辑。
·Event and I/O版本:包括事件模块及I/O模块
·Event版本:包括事件模块
·Kitchen Sink版本:该版本包括整个工具集合

以上版本分别适用于不同的场合。用户也可以根据自己的需求重新构建自己的核心代码文件,只包含自己常用的模块,以避免频繁动态加载常用的模块。

2.程序结构

Dojo官方的定义中,将Dojo称之为Toolkit(工具包),不是Framework(只是Framework的一部分),也不是Library(在Library之上又加了一层封包系统)。Dojo包括了Javascript本身的语言扩展,以及各个方面的工具类库,和比较完善的UI组件库。

如下图:


从图中也可看出,Dojo的设计结构非常合理,且扩展性非常强,能够不断增加新的功能,且保证程序高效的运行。

四、官方资源

Dojo的官方网站有以下资源,可以帮助我们很快的熟悉Dojo的结构,当然,因为Dojo有丰富的功能,要完全掌握还需要在实际开发中逐渐掌握。

1. Dojo手册(The Dojo Manual)
网址:http://manual.dojotoolkit.org/
系统地介绍Dojo的机制,使用方法,示例代码等

2.Dojo邮件列表(The Dojo Mailing Lists)
可以讨论交流在使用Dojo中遇到的问题,或希望改进的建议
申请加入地址:http://dojotoolkit.org/mailman/listinfo/dojo-interest
查看存档:http://news.gmane.org/gmane.comp.web.dojo.user

3.Dojo错误跟踪系统(Bug Tracking)
网址:http://trac.dojotoolkit.org/
可以提交有效地发现bug,提交bug,以便能够及时地消除Dojo中的bug

4.代码仓库(The Dojo Subversion Repository)
网址:http://trac.dojotoolkit.org/browser
可以很方便地获得最新版本的Dojo程序包

5.The Dojo Wiki
网址:http://dojo.jot.com/
Dojo Wiki的内容类别相对比较丰富,涉及到Dojo的各个方面。

6.IRC
聊天室地址:irc.freenode.net

7.Dojo程序包中附带的Demo程序
提供了8大类近30个Demo程序,可以在实践中更快地掌握Dojo的用法。

提示:推荐加入Dojo的邮件列表,并仔细研究示例代码,这样能更快地掌握Dojo的使用方法。

五、发展前景

1.技术层面
与其它AJAX框架相比,Dojo设计的包加载机制(Package System)和模块化(Libraries)的结构,能保持更好的扩展性,提高执行性能,减轻了用户开发的工作量,并保持一定的灵活性(用户可以自己编写扩展)。

2.市场层面
Dojo现在发展迅猛,得到广泛的支持,并成立了Dojo 基金会 , IBM 、AOL 、SUN这些大公司和WebWork、Tapestry、Open Laszlo等开源团队都是dojo基金会的成员,雄厚的后盾保证了Dojo可以持续的发展下去。

3.开发团队
在Alex Russell的领导下,Dojo的开发团队有着强大的开发能力,从目前版本提供的功能、质量及更新的速度我们就可以看出来了。另外近期Dojo将会发布0.4.0。

4.用户群体
由于Dojo出色的设计,越来越多的AJAX专家及新手加入到了Dojo的开发者中,这些开发者也会相应地动Dojo的发展。

5.学习资源
Dojo官方网站有着丰富的学习资源(见“官方资源”一节),可以帮助人们更快地掌握Dojo,减少学习成本。

六、结语

Dojo可以帮助开发人员开发大型的AJAX项目,并有助于构建健壮的代码,节省开发时间。Dojo背后强大的支持后盾也可以保证持续不断的补充新功能,有助于我们脱离低层重复的工作,专注于在此基础上进行开发。

本文来自: 脚本之家(www.jb51.net) 详细出处参考:http://www.jb51.net/article/9347.htm

fckeditor 中javascript做copy操作的写法

1. 如果是ie,copy到剪贴板自然好办,如果不是ie,这里使用了flash来做copy操作

//===============================Copy to clipboard=================================//

function CopyText(id) { 
    
//copyToClipboard(document.getElementById(id).value); 
    
if (document.getElementById(id
))     {
        var 
tocopy=document.getElementById(id).innerHTML
;
        
tocopy=tocopy.replace(/&/g"&"
); 
        
copy(tocopy
);
    }
}

function copy(text2copy) {
    if (
window.clipboardData
) { 
        
window.clipboardData.setData("Text",text2copy
); 
    } else {
        var 
flashcopier ‘flashcopier’

        if(!
document.getElementById(flashcopier
)) { 
            var 
divholder document.createElement(‘div’); divholder.id flashcopier

            
document.body.appendChild(divholder
); 
        } 
        
document.getElementById(flashcopier).innerHTML 

        var 
divinfo ‘<embed src="’+absbaseurl+‘images/others/_clipboard.swf" FlashVars="clipboard=’+escape(text2copy)+‘" width="0" height="0" type="application/x-shockwave-flash"></embed>’

        
document.getElementById(flashcopier).innerHTML divinfo
;
        
alert(jslang[72
]);
    } 
}

function copyToClipboard(meintext)
{
     if (
window.clipboardData

       {
       
alert("ie"
);
       
// the IE-manier
       
window.clipboardData.setData("Text"meintext
);
       
       
// waarschijnlijk niet de beste manier om Moz/NS te detecteren;
       // het is mij echter onbekend vanaf welke versie dit precies werkt:
       
}
       else if (
window.netscape

       { 
       
       
// dit is belangrijk maar staat nergens duidelijk vermeld:
       // you have to sign the code to enable this, or see notes below 
       
netscape.security.PrivilegeManager.enablePrivilege(‘UniversalXPConnect’
);
       
       
// maak een interface naar het clipboard
       
var clip Components.classes[‘@mozilla.org/widget/clipboard;1’].createInstance(Components.interfaces.nsIClipboard
);
       if (!
clip
) return;
       
alert("mozilla"
);
       
// maak een transferable
       
var trans Components.classes[‘@mozilla.org/widget/transferable;1’
]
                      .
createInstance(Components.interfaces.nsITransferable
);
       if (!
trans
) return;
       
       
// specificeer wat voor soort data we op willen halen; text in dit geval
       
trans.addDataFlavor(‘text/unicode’
);
       
       
// om de data uit de transferable te halen hebben we 2 nieuwe objecten 
       // nodig om het in op te slaan
       
var str = new Object
();
       var 
len = new Object
();
       
       var 
str Components.classes["@mozilla.org/supports-string;1"
]
                    .
createInstance(Components.interfaces.nsISupportsString
);
       
       var 
copytext=meintext
;
       
       
str.data=copytext
;
       
       
trans.setTransferData("text/unicode",str,copytext.length*2
);
       
       var 
clipid=Components.interfaces.nsIClipboard
;
       
       if (!
clip) return false
;
       
       
clip.setData(trans,null,clipid.kGlobalClipboard
);
       
       }
       
alert("Following info was copied to your clipboard:\n\n" meintext
);
       return 
false
;
}

中文分词软件 LibMMSeg

xapian 是不支持中文的,但是可以通过LibMMSeg来弥补改缺憾。

LibMMSeg 简介

LibMMSeg 是Coreseek.com为 Sphinx 全文搜索引擎设计的中文分词软件包,其在GPL协议下发行的中文分词法,采用Chih-Hao Tsai的MMSEG算法。

MMSEG: A Word Identification System for Mandarin Chinese Text Based on Two Variants of the Maximum Matching Algorithm

Published: 1996-04-29
Updated: 1998-03-06
Document updated: 2000-03-12
License: Free for noncommercial use
Copyright 1996-2006 Chih-Hao Tsai (Email: hao520 at yahoo.com )

您可以在Chih-Hao Tsai’s Technology Page找到算法的原文。

LibMMSeg 采用C++开发,同时支持Linux平台和Windows平台,切分速度大约在300K/s(PM-1.2G),截至当前版本(0.7.1)LibMMSeg没有为速度仔细优化过,进一步的提升切分速度应仍有空间。

下载

下载 MMSeg 0.7.3

修订记录

0.7.3
– 2008.05.27 修正 Makefile 无法安装csr_typedefs.h的问题
– 2008.05.27 修正 x64系统上编译无法作为动态库的一部分编译的问题

0.7.2
– 2008.05.19 修正 指定的目录中无词典不提示错误的问题
– 2008.05.19 新增 Ruby 的调用API

0.7.1
– 2008.04.23 修正了在类似 “english 中文 english" 的句子,切分不正确的问题

0.7
– 第一次发行

安装

Window平台

打开源码包中src\win32 子目录下的对应的工程文件,目前LibMMSeg内置了VS2003和VS2005的工程文件。

Linux平台

在源码包根目录下执行:

./configure && make && make install

使用

词典的构造

mmseg -u unigram.txt

该命令执行后,将会产生一个名为unigram.txt.uni的文件,将该文件改名为uni.lib,完成词典的构造。需要注意的是,unigram.txt 必须为UTF-8编码。

词典文件格式:

….
河 187
x:187
造假者 1
x:1
台北队 1
x:1
湖边 1
……

其中,每条记录分两行。其中,第一行为词项,其格式为:[词条]\t[词频率]。需要注意的是,对于单个字后面跟这个字作单字成词的频率,这个频率需要在大量的预先切分好的语料库中进行统计,用户增加或删除词时,一般不需要修改这个数值;对于非单字词,词频率处必须为1。第二行为占位项,是由于LibMMSeg库的代码是从Coreseek其他的分词算法库(N-gram模型)中改造而来的,在原来的应用中,第二行为该词在各种词性下的分布频率。LibMMSeg的用户只需要简单的在第二行处填"x:1"即可。

用户可以通过修改词典文件增加自己的自定义词,以提高分词法在某一具体领域的切分精度,系统默认的词典文件在data/unigram.txt中。

分词

mmseg -d <dict_dir> tobe_segment.txt

其中,命令使用‘-d’开关指定词库文件所在的位置,参数dict_dir为词库文件(uni.lib )所在的目录;tobe_segment.txt 为待切分的文本文件,必须为UTF-8编码。如果一切正确,mmseg会将切分结果以及所花费的时间显示到标准输出上。

对特殊短语的支持

由于LibMMSeg是为Sphinx全文搜索引擎设计的,因此其内置了部分搜索引擎切分算法的特性,主要表现在对特殊短语的支持上。

在搜索引擎中,需要处理C++时,如果分词器中没有词组C++,则将被切分为C/x +/x +/x,在进一步的检索中,可能每个词会由于出现的过于频繁而被过滤掉,导致搜索的结果与C++相关度不高不说,也严重影响的全文搜索的速度。在LibMMSeg中,内置对特殊短语的支持。

其输入文件格式如下

// test commit
.net => dotnet
c# => csharp
c++ => cplusplus

其中左侧是待支持的特殊短语,右侧是左侧的特殊短语需要被转换为的短语。这一转换在分词前进行。

可以在行的开头加入’//’作为注释符号,发现符号’//’后,整行将被忽略。

特殊短语词库构造命令:

mmseg -b exceptions.txt

其中, 开关’-b’指示mmseg是要构造特殊短语词库;exceptions.txt是用户编辑的特殊短语转换规则。

该命令执行后,将在当前目录下产生一个名为"synonyms.dat"的文件,将该文件放在"uni.lib"同一目录下,分词系统将自动启动特殊短语转换功能。

注意:

1、在启用了该功能后,如果分词系统发现了一个特殊短语,将直接输出其在右侧对应的替换的值;

2、右侧被替换的值,请保证不会被分词器进行切分。(eg. C++ => C# 这个转换的意义不大,并且可能导致C++这个短语永远无法被检索到!)

 

附录:

MMSeg算法说明

首先来理解一下chunk,它是MMSeg分词算法中一个关键的概念。Chunk中包含依据上下文分出的一组词和相关的属性,包括长度(Length)、平均长度(Average Length)、标准差的平方(Variance)和自由语素度(Degree Of Morphemic Freedom)。下面列出了这4个属性:

    

        

            

            

        

        

            

            

        

        

            

            

        

        

            

            

        

        

            

            

        

    

属性 含义
长度(Length) chuck中各个词的长度之和
平均长度(Average Length) 长度(Length)/词数
标准差的平方(Variance) 同数学中的定义
自由语素度(Degree Of Morphemic Freedom) 各单字词词频的对数之和

 

Chunk中的4个属性只有在需要该属性的值时才进行计算,而且只计算一次。

其次来理解一下规则(Rule),它是MMSeg分词算法中的又一个关键的概念。实际上我们可以将规则理解为一个过滤器(Filter),过滤掉不符合要求的chunk。MMSeg分词算法中涉及了4个规则:

        

  • 规则1:取最大匹配的chunk (Rule 1: Maximum matching)
  •     

  • 规则2:取平均词长最大的chunk (Rule 2: Largest average word length)
  •     

  • 规则3:取词长标准差最小的chunk (Rule 3: Smallest variance of word lengths)
  •     

  • 规则4:取单字词自由语素度之和最大的chunk (Rule 4: Largest sum of degree of morphemic freedom of one-character words)

这4个规则符合汉语成词的基本习惯。

再来理解一下匹配方式复杂最大匹配(Complex maximum matching):

复杂最大匹配先使用规则1来过滤chunks,如果过滤后的结果多于或等于2,则使用规则2继续过滤,否则终止过滤过程。如果使用规则2得到的过滤结果多于或等于2,则使用规则3继续过滤,否则终止过滤过程。如果使用规则3得到的过滤结果多于或等于2,则使用规则4继续过滤,否则终止过滤过程。如果使用规则 4得到的过滤结果多于或等于2,则抛出一个表示歧义的异常,否则终止过滤过程。

最后通过一个例句–“研究生命起源来简述”一下复杂最大匹配的分词过程。MMSeg分词算法会得到7个chunk,分别为:

    

        

            

            

            

        

        

            

            

            

        

        

            

            

            

        

        

            

            

            

        

        

            

            

            

        

        

            

            

            

        

        

            

            

            

        

        

            

            

            

        

    

编号 chunk 长度
0 研_究_生 3
1 研_究_生命 4
2 研究_生_命 4
3 研究_生命_起 5
4 研究_生命_起源 6
5 研究生_命_起 5
6 研究生_命_起源 6

使用规则1过滤后得到2个chunk,如下:

    

        

            

            

            

        

        

            

            

            

        

        

            

            

            

        

    

编号 chunk 长度
4 研究_生命_起源 6
6 研究生_命_起源 6

计算平均长度后为:

    

        

            

            

            

            

        

        

            

            

            

            

        

        

            

            

            

            

        

    

编号 chunk 长度 平均长度
4 研究_生命_起源 6 2
6 研究生_命_起源 6 2

使用规则2过滤后得到2个chunk,如下:

    

        

            

            

            

            

        

        

            

            

            

            

        

        

            

            

            

            

        

    

编号 chunk 长度 平均长度
4 研究_生命_起源 6 2
6 研究生_命_起源 6 2

计算标准差的平方后为:

    

        

            

            

            

            

            

        

        

            

            

            

            

            

        

        

            

            

            

            

            

        

    

编号 chunk 长度 平均长度 标准差的平方
4 研究_生命_起源 6 2 0
6 研究生_命_起源 6 2 4/9

使用规则3过滤后得到1个chunk,如下:

    

        

            

            

            

            

            

        

        

            

            

            

            

            

        

    

编号 chunk 长度 平均长度 标准差的平方
4 研究_生命_起源 6 2 0

匹配过程终止。最终取“研究”成词,以相同的方法继续处理“生命起源”。

分词效果:

研究_生命_起源_
研究生_教育_

 

摘自: http://www.coreseek.com/index.php?page=mmseg

 

相关软件: http://www.coreseek.com/opensource/Sphinx/

Sphinx 官方网站: http://www.sphinxsearch.com/

关于tcl语言

TCL语言

  TCL (最早称为“工具命令语言”"Tool Command Language", 但是目前已经不是这个含义,不过我们仍然称呼它为TCL)是一种 脚本语言。 由John Ousterhout创建。 TCL很好学,功能很强大。TCL经常被用于 快速原型开发,脚本编程, GUI和测试等方面。TCL念作“踢叩” "tickle". Tcl的特性包括:

  * 任何东西都是一条命令,包括语法结构(for, if等)。

  * 任何事物都可以重新定义和重载。

  * 所有的数据类型都可以看作字符串。

  * 语法规则相当简单

  * 提供事件驱动给Socket和文件。基于时间或者用户定义的事件也可以。

  * 动态的域定义。

  * 很容易用C, C++,或者Java扩展。

  * 解释语言,代码能够动态的改变。

  * 完全的Unicode支持。

  * 平台无关。Win32, UNIX, Mac 上都可以跑。

  * 和Windows的GUI紧密集成。 Tk

  * 代码紧凑,易于维护。

  TCL本身不提供面向对象的支持。但是语言本身很容易扩展到支持面向对象。许多C语言扩展都提供面向对象能力,包括XOTcl, Incr Tcl 等。另外SNIT扩展本身就是用TCL写的。

  使用最广泛的TCL扩展是TK。 TK提供了各种OS平台下的图形用户界面GUI。连强大的Python语言都不单独提供自己的GUI,而是提供接口适配到TK上。另一个流行的扩展包是Expect. Expect提供了通过终端自动执行命令的能力,例如(passwd, ftp, telnet等命令驱动的外壳).

  另外一个TK的例子 (来自 A simple A/D clock) 它使用了定时器时间,3行就显示了一个时钟。

  proc every {ms body} {eval $body; after $ms [info level 0]}

  pack [label .clock -textvar time]

  every 1000 {set ::time [clock format [clock sec] -format %H:%M:%S]} ;# RS

  解释:第一行定义了过程every, 每隔ms毫秒,就重新执行body代码。第二行创建了标签起内容由time变量决定。第3行中设置定时器,time变量从当前时间中每秒更新一次。

rpmbuild 用法简介

rpm是linux上一个非常好用的包管理工具,但是很多时候我们下载到的软件并不是一个rpm包,安装后就不好管理了;但是如果稍微留心一下就会发现,虽然开发者没有给我们直接提供一个现成的rpm包,但是关于制作rpm包的99%的工作已经帮我们做完了,就是spec文件的编写;只要我们发现源码包里面有一个.spec文件,我们就可以使用rpmbuild命令来自己制作rpm包了,制作完rpm包后再安装就比较好管理了,下面简单介绍一下rpmbuild的用法:

-bp 只作准备 (解压与打补丁)
-bc 准备并编译
-bi 编译并安装
-bl 检验文件是否齐全
-ba 编译后做成*.rpm和src.rpm
-bb 编译后做成*.rpm
-bs 只做成*.src.rpm

-tc -ti -ta -tb -ts 的功能类似,只是所需参数由spec文件变成tar包。

–buildroot    相当于我们config时使用的prefix ,指定程序安装的目录 如: /usr/local/xxxx

 

问题: 当使用tar包进行制作时,spec文件在tar包中的位置如何约定的呢?

参考: http://www.jinbuguo.com/redhat/rpmbuild.html

xapian

官方网站: http://www.xapian.org/

xapian是啥玩意?

xapian 是个“Xapian 是个开源概率论信息检索库,基于GPL发布。他是用C++编写的,提供的绑定能够支持其他语言(支持Perl, Python, PHP, Java, and TCL )的研发。 Xapian 设计为一个高度可适应的工具集,能够让研发人员方便地为他们自己的应用程式增加高级索引和搜索功能。”

在网上找到这段介绍后,俺手痒痒就想试试xapian ?- 一定要给php整个这东东上去.参考了若干文档以后,这就开始动手了(我的环境仍然是freebsd + apache 2.2 + php 5.1.2,apache和php原来就已安装好):

1.下载xapian

cd /usr/local/src
wget http://www.oligarchy.co.uk/xapian/0.9.4/xapian-core-0.9.4.tar.gz
wget http://www.oligarchy.co.uk/xapian/0.9.4/xapian-bindings-0.9.4.tar.gz

前者是xapian的核心lib代码,后者是给其他语言调用的接口

2.安装Xapian-core

cd /usr/local/src
tar xzvf xapian-core-0.9.4.tar.gz
cd xapian-core-0.9.4
./configure –prefix=/usr/local/xapian
make
make install

3.安装Xapian-bindings

cd /usr/local/src
tar xzvf xapian-bindings-0.9.4.tar.gz
cd xapian-bindings-0.9.4
ln -s /usr/local/xapian/bin/xapian-config /usr/local/bin/xapian-config #这里需要做个软连接,编译的时候需要用到
./configure –without-python #我没用到python,就不编译了, 还有tcl,如果你的机器上没有安装tcl语言,就–without-tcl
make
make install

进行到这一步,Xapian-bindings应该算是安装好了,但是不知道为何,编译好的xapian.so没有按说明文档所说的自动复制到php的extension目录,于是我手工完成这一步骤

cp php/.libs/xapian.so /usr/local/lib/php #/usr/local/lib/php是我在php.ini配置的extension目录

然后修改php.ini
extension=xapian.so

PHP 代码美化工具

phpCodeBeautifier is a tool which avoid you of spending hours on reformating code to suit your own way of presenting it.

The tool has been declined into 3 versions:

        

  • A GUI version which allow to process file visually.
  •     

  • A command line version which allow to be batched or integrated with other tools (CVS, SubVersion, IDE …).
  •     

  • As an integrated tool of PHPEdit.

 

官方地址:http://www.waterproof.fr/products/phpCodeBeautifier/

官方下载:
http://www.waterproof.fr/products/phpCodeBeautifier/download.php

本地下载:
windows版:http://phpor.net/download/phpCB-1.0.1-windows.zip
linux版:http://phpor.net/download/phpCB-1.0.1-linux.tgz

 

手册地址:http://www.waterproof.fr/products/phpCodeBeautifier/manual.php

apache 模块编写 之 helloworld篇

关于apache模块的资料比较少,这里给出两个比较简单的例子,来揭开apache模块神秘的面纱,当然例子很初级,不过只有初级才容易入门,写一个helloworld吧:

/**
 * filename:    helloworld.c
 * author:      lijunjie <lijunjie1982@yahoo.com.cn>
 * version:     1.0
 */
#include <httpd.h>
#include <http_protocol.h>
#include <http_config.h>

static int helloworld_handler(request_rec *r) {
        if (!
r->handler || strcmp(r->handler"helloworld"
)) {
                return 
DECLINED
;
        }
        if (
r->method_number != M_GET
){
                return 
HTTP_METHOD_NOT_ALLOWED
;
        }
        
ap_set_content_type(r,"text/html;charset=asscii"
);
        
ap_rputs("hello world"r
);
        return 
OK
;
}

static void helloworld_hooks(apr_pool_t *pool) {
        
ap_hook_handler(helloworld_handlerNULLNULLAPR_HOOK_MIDDLE
);
}

module AP_MODULE_DECLARE_DATA helloworld_module = {
        
STANDARD20_MODULE_STUFF
,
        
NULL
,
        
NULL
,
        
NULL
,
        
NULL
,
        
NULL
,
        
helloworld_hooks
};

/****** install ***********
compile: apxs -i -c mod_helloworld.c

modify httpd.conf, add

LoadModule helloworld_module modules/mod_helloworld.so

<Location /helloworld>
    SetHandler helloworld
</Location>

********************************/

 

下面给出一个稍微复杂一点的,对我们进一步的了解有很大帮助的,它可以输出一些比较有意义的东西了

/**
 * filename:    helloworld.c
 * author:      lijunjie <lijunjie1982@yahoo.com.cn>
 * version:     1.1
 */
#include <httpd.h>
#include <http_protocol.h>
#include <http_config.h>

static int printitem(void *rec, const char *key, const char *value){
        
// recive rec pointer , we will send  some request use it
        
request_rec *rec;
        
ap_rprintf(r"<tr><th scope=’row’>%s</th><td>%s</td></tr>\n"
                                        
ap_escape_html(r->poolkey), 
                                        
ap_escape_html(r->poolvalue));
        return 
1;
}

static void printtable(request_rec *rapr_table_t *t
                                const 
char *caption, const char *keyhead,
                                const 
char *valhead) {
                
ap_rprintf(r,"<table border=’1′ width=’100%’><caption>%s</caption><thead>"
                                                "<tr><th scope=’col’>%s</th><th scope=’col’>%s"
                                                "</th></tr></thead><tbody>"
,
                                                 
captionkeyheadvalhead);
                
apr_table_do(printitemrtNULL);

                ap_rputs("</tbody></table>\n",r);

}
static int helloworld_handler(request_rec *r) {
        if (!
r->handler || strcmp(r->handler"helloworld")) {
                return 
DECLINED;
        }
        if (
r->method_number != M_GET){
                return 
HTTP_METHOD_NOT_ALLOWED;
        }
        
ap_set_content_type(r,"text/html;charset=asscii");
        
ap_rputs("This is the Apache hello world module<br>"r);
        
printtable(rr->headers_in"Request Headers""Header""Value");
        
printtable(rr->headers_out"Response Headers""Header""Value");
        
printtable(rr->headers_in"Environment""Variable""Value");

        return OK;
}

static void helloworld_hooks(apr_pool_t *pool) {
        
ap_hook_handler(helloworld_handlerNULLNULLAPR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA helloworld_module = {
        
STANDARD20_MODULE_STUFF,
        
NULL,
        
NULL,
        
NULL,
        
NULL,
        
NULL,
        
helloworld_hooks
};
/****** install ***********
compile: apxs -i -c mod_helloworld.c

modify httpd.conf, add

LoadModule helloworld_module modules/mod_helloworld.so

<Location /helloworld>
    SetHandler helloworld
</Location>

********************************/