你还在使用telnet 与ftp 吗?

传统的telnet 与ftp 服务都使用明文传送用户名和密码,如果在运行服务器或者客户端的网络中装有嗅探器(有很多现成的工具可利用),那么服务器的安全将是非常脆弱的。幸好,我们可以使用连接加密的SSH 协议,由OpenBSD group 开发的OpenSSH 是遵循SSH 协议的一套免费开源工具包,目前已经被集成在大多数的类unix 平台和他们的发布版本中,这也包括商业的操作系统,因为OpenSSH 基于BSD 协议,BSD 协议相对比较宽松。这里是一个运行它的系统列表,当然也包含RedHat Linux 发布。OpenSSH 提供的sshd 服务可用于替代传统telnet...

传统的telnet 与ftp 服务都使用明文传送用户名和密码,如果在运行服务器或者客户端的网络中装有嗅探器(有很多现成的工具可利用),那么服务器的安全将是非常脆弱的。

幸好,我们可以使用连接加密的SSH 协议,由OpenBSD group 开发的OpenSSH 是遵循SSH 协议的一套免费开源工具包,目前已经被集成在大多数的类unix 平台和他们的发布版本中,这也包括商业的操作系统,因为OpenSSH 基于BSD 协议,BSD 协议相对比较宽松。这里是一个运行它的系统列表,当然也包含RedHat Linux 发布。

OpenSSH 提供的sshd 服务可用于替代传统telnet 服务器端程序,sftp-server 子系统(实际由sshd 进行调用)可用于替代传统ftp 服务器端程序,ssh(secure shell) 与sftp(secure ftp)分别用于替代传统的telnet 与ftp 客户端工具。

在RH Linux 下,可以直接使用OpenSSH 软件包,有了OpenSSH,不建议再安装telnet 组件。

$ ssh www.domain.com
$ sftp www.domain.com

在Windows 下,同样有一套出色的支持SSH 协议的免费开源软件包,那就是putty 。最喜欢使用的就是软件包中的putty.exe,它相当于OpenSSH 中的ssh ,putty 功能很多,支持logging、proxy、与本地系统之间的copy、paste等,还兼容telnet 和rlogin 。

putty 提供的psftp.exe 基于命令行,对于大量文件的频繁传输,还是GUI 更方便些,WinSCP2sshwinclient 就是两个不错的工具,都使用SSH 协议,操作风格类似于传统的ftp 图形客户端。前者是绿色软件,小巧实用,后者需要安装,功能更强一些。

 

 

want to know more about sftp tools?here

你还在使用telnet 与ftp 吗?或许是时候关闭它们了,只开放sshd(22端口)服务,使用加密认证的远程命令执行与文件传输吧。

选择微软?还是Google?

近日收到朋友的Gmail邀请,建立了自己的Gmail 帐号,虽然Gmail 提供了许多令人动心的特色,但对我来说,这不是简单的Email 服务商的迁移,而是从IM(msn messenger)、Email(hotmail)、一直到blog(msn spaces) 的迁移。说得大一点,就是选择微软还是google?这里面最难的一个环节是IM ,已经有大长串的朋友在msn messenger 上了,而且可以很方便的与hotmail 帐户之间共享联系人,msn messenger 和hotmail 一直没有提供联系人导出功能,进来是可以的,但出去不许把东西打包带走:)。google 的确在吸引着我,使用gmail 不用再为剩余空间和邮件查找烦恼,摆脱hotmail...

近日收到朋友的Gmail邀请,建立了自己的Gmail 帐号,虽然Gmail 提供了许多令人动心的特色,但对我来说,这不是简单的Email 服务商的迁移,而是从IM(msn messenger)、Email(hotmail)、一直到blog(msn spaces) 的迁移。说得大一点,就是选择微软还是google?这里面最难的一个环节是IM ,已经有大长串的朋友在msn messenger 上了,而且可以很方便的与hotmail 帐户之间共享联系人,msn messenger 和hotmail 一直没有提供联系人导出功能,进来是可以的,但出去不许把东西打包带走:)。

google 的确在吸引着我,使用gmail 不用再为剩余空间和邮件查找烦恼,摆脱hotmail 讨厌的http 收信的同时,终于可以smtp 迅速的发送邮件了。还有简洁实用的gtalk ,音质很具有临场感。

其实还有一点,我欣赏google 后面创新的精神,相信在她后面会有更多精彩。

无论如何,暂时先把google 作为甜点品尝吧,我还希望继续与messenger 上面的朋友们继续保持联系,也希望可以很方便的从messenger 收到邮件通知并进行回复,还希望把我的idea 通过msn spaces 与朋友们共享,同时也希望有一种比较方便的方式看他们正在“说”什么。毕竟我使用这些服务的目的是为了提高生活质量,而不是用来打乱生活。

Awstats 启用HostInfo 插件

Awstats 6.2 版本提供了一个用于显示主机所属信息的插件:HostInfo 。默认此插件为关闭,编辑文件awstats.domain.com.conf 启用此插件,找到以下行:# Plugin: HostInfo# Perl modules required: Net::XWhois# Add a column into host...

Awstats 6.2 版本提供了一个用于显示主机所属信息的插件:HostInfo 。默认此插件为关闭,编辑文件awstats.domain.com.conf 启用此插件,找到以下行:

# Plugin: HostInfo
# Perl modules required: Net::XWhois
# Add a column into host chart with a link to open a popup window that shows
# info on host (like whois records).
#
#LoadPlugin="hostinfo"

将LoadPlugin="hostinfo" 之前的注释去掉,保存退出。

再次运行Awstats 报错,提示在已有路径中找不到Net::XWhois 模块,依次查找RedHat Linux 9 的三张安装光盘。

$ cd /mnt/cdrom/RedHat/RPM
$ rpm -qlp perl-*.rpm |grep -i xwhois

没有找到包含这个模块的程序包,最后在rpmFine.net 找到了这个模块的下载:

ftp://rpmfind.net/linux/dag/redhat/9/en/i386/dag/RPMS/perl-Net-XWhois-0.90-1.0.rh9.dag.noarch.rpm

不过需要注意你的系统版本,最好从下面的链接进入,逐步选择:

http://rpmfind.net/linux/RPM/dag/

下载程序包:

$ wget ftp://rpmfind.net/linux/dag/redhat/9/en/i386/dag/RPMS/perl-Net-XWhois-0.90-1.0.rh9.dag.noarch.rpm

安装模块,先看看这个包含有哪些文件:

$ rpm -qlp perl-Net-XWhois-0.90-1.0.rh9.dag.noarch.rpm
warning: perl-Net-XWhois-0.90-1.0.rh9.dag.noarch.rpm: V3 DSA signature: NOKEY, key ID 6b8d79e6
/usr/lib/perl5/vendor_perl/5.8.0/Net/XWhois.pm
/usr/share/doc/perl-Net-XWhois-0.90
/usr/share/doc/perl-Net-XWhois-0.90/ARTISTIC
/usr/share/doc/perl-Net-XWhois-0.90/Changes
/usr/share/doc/perl-Net-XWhois-0.90/TODO
/usr/share/man/man3/Net::XWhois.3pm.gz

开始安装(需要在root 权限下进行):

# rpm -ivh perl-Net-XWhois-0.90-1.0.rh9.dag.noarch.rpm
warning: perl-Net-XWhois-0.90-1.0.rh9.dag.noarch.rpm: V3 DSA signature: NOKEY, key ID 6b8d79e6
Preparing... ########################################### [100%]
1:perl-Net-XWhois ########################################### [100%]

安装完毕,重新进入Awstats 统计页面,在主机项目增加了“WhoIs 资讯”一栏,如下:

主机WhoIs 资讯网页数文件数字节最近参观日期
202.108.130.138?483001.33 M字节2005年 八月 26日 17:34

通过这个插件得到的查询结果,与使用以下命令得到的内容相同:

$ whois 202.108.130.138

有关Awstats 的安装,请参考车东的文章:AWStats: Apache/IIS的日志分析工具——在GNU/Linux和Windows平台上的使用简介

vi 命令傻瓜讲解

正文下面介绍vi 的一般用法,本文适合初学者入门,但不适合作为手册进行查询,如果需要以命令导向的手册,请使用$ man vi|more ,或看这里的:vi 命令一览表。打开文件进入编辑编辑一个文件:$ vi example.txt同时编辑多个文件:$ vi file1 file2 ... fileN如果使用vi 编辑的某个文件没有正常保存退出,会遗留一个隐含的文件:.filename.swp ,使用如下命令恢复从最后一次保存到非正常退出前所做的编辑:$ vi...

正文

下面介绍vi 的一般用法,本文适合初学者入门,但不适合作为手册进行查询,如果需要以命令导向的手册,请使用$ man vi|more ,或看这里的:vi 命令一览表

打开文件进入编辑

编辑一个文件:

$ vi example.txt

同时编辑多个文件:

$ vi file1 file2 ... fileN

如果使用vi 编辑的某个文件没有正常保存退出,会遗留一个隐含的文件:.filename.swp ,使用如下命令恢复从最后一次保存到非正常退出前所做的编辑:

$ vi -r filename

注意当前模式

进入文件编辑后,vi有四种模式,一种是插入模式(按键盘i 进入),这个模式下键盘输入会作为字符增加到文件中。

另一种是编辑模式,这个状态下可以直接输入命令来移动光标,删除字符等操作,不需要回车确认,每一个命令按键都会直接发生作用。在插入模式下按ESC 键会回到编辑模式。

第三种是命令模式,在编辑模式下按冒号":" 即进入命令模式,这时键盘输入的字符会出现在屏幕下方,回车后,命令执行。这个模式下可以输入保存、字符串搜索、退出编辑等命令。命令模式下,按回车或者ESC 键,回到编辑模式。

第四种是搜索模式,在编辑模式下输入斜杠"/" 或者问号"?" 即进入搜索模式。

上面的四种模式是我为了描述方便所起的名字,下面将引用到。

光标移动

光标的上、下、左、右移动,分别对应按键:k、j、h、l (编辑模式)。

定位到最后一行,输入大写G(编辑模式)。

回到第一行,输入小写g(编辑模式)。

跳到第n 行,在命令模式下输入数字n ,回车。

显示当前所在行数和列数,编辑模式下输入ctrl+g 。

插入内容

在当前字符前面插入内容,编辑模式下输入i ,进入了插入模式,然后输入内容,输入完成之后,按ESC 回到编辑模式。

在当前字符后面插入内容,编辑模式下输入a ,其它操作与上面相同。

在本行首插入内容,编辑模式下输入大写I 。其它操作与上面相同。

在本行尾追加内容,编辑模式下输入大写A 。其它操作与上面相同。

删除

删除当前光标的字符,编辑模式下输入x ,如果希望删除当前光标前面的字符,输入大写X 。

删除一行,编辑模式下连续两次输入d 。删除一个单词,编辑模式下依次输入dw 。

从当前光标删除至行尾,编辑模式下依次输入d$ 。

撤销操作

撤销刚才的一次修改,编辑模式下输入u ,撤销对这一整行的修改,输入大写U 。

如果希望撤销对文件的所有修改,命令模式下依次输入e! ,回车(输入冒号":" 进入命令模式,:e!)。

拷贝粘贴

拷贝一行内容,编辑模式下连续输入两次y 。

将剪贴板中的一行粘贴到当前行的后面,编辑模式下输入p 。

拷贝n 行内容,编辑模式下输入数字n(n是要拷贝的行数,从当前行算起),然后输入y ,拷贝完成,输入p 粘贴多行。

保存/退出

如果保存并关闭文件,命令模式下输入x ,回车即可。

如果保存,同时继续文件编辑,命令模式下输入w ,回车。

如果放弃所有更改,直接退出,命令模式下输入q! ,回车。

命令模式下输入wq 与x 等价。

在两个文件中复制粘贴

需要将file2 的某行粘贴到file1 中。

同时打开两个文件,中间用空格分隔:

$ vi file1.txt file2.txt

打开后当前编辑的为file1 ,在命令模式下输入n ,切换到file2。

找到相关行,编辑模式下输入yy ,再进入命令模式,输入大写N ,切换回上一个文件(以打开顺序为准),找到相关位置,编辑模式下输入p ,粘贴完毕。

 

搜索字符串

要搜索字符串abc ,在搜索模式下(编辑模式下输入斜杠"/" 或者问号"?" 即进入搜索模式),输入abc ,回车。

如果找到,光标会定位到从当前位置到第一个出现字符串abc 的位置,输入n 会跳到下一个abc 出现的位置,输入大写N ,跳到上一个abc 出现的位置。

斜杠"/" 与问号"?" 的区别,前者向后正向搜索,后者向前反向搜索。

替换字符串

要将当前行中的所有字符串abc 替换成efg ,命令模式下输入s/abc/efg/g ,回车。

上面命令只会替换abc 而不会替换ABC 或者aBc 。如果希望忽略大小写,加上参数i ,s/abc/efg/gi ,回车。

如果希望进行全文件范围替换,命令模式下输入%s/abc/efg/g ,回车。

如果替换的字符串中包含了例如斜杠"/" 这样的特殊字符,使用反斜杠"\" 转义。

命令模式下,输入%s/\/image/\/img/gi ,回车

以上命令会将文件中所有的字符串/image 替换成 /img ,并且不区分image 的大小写。

Linux 系统管理学习笔记(四)

rpm 下面列出rpm的一般用法,这里也有一篇非常全面的介绍:rpm 详解。 安装一个软件包: $ rpm -ivh example.rpm 在已安装基础上升级软件包: $ rpm -Uvh upgrade.rpm 删除软件包: $ rpm...

rpm

下面列出rpm的一般用法,这里也有一篇非常全面的介绍:rpm 详解

安装一个软件包:

$ rpm -ivh example.rpm

在已安装基础上升级软件包:

$ rpm -Uvh upgrade.rpm

删除软件包:

$ rpm -e nouse.rpm

查询一个软件包是否已经安装(忽略大小写):

$ rpm -qa |grep -i example

如果要安装的软件包依赖于其它尚未安装的软件包,要忽略依赖关系,强制安装:

$ rpm -ivh --nodeps example.rpm

查看一个软件包中包含哪些文件:

$ rpm -qlp example.rpm

eject

弹出光驱:

$ eject

关闭光驱(直接使用mount 命令,光驱也会自动关闭):

$ eject -t

有关eject 命令这里还有更有趣的讨论

locale

列出当前系统安装的所有locales:

$ locale -a

find

对查找到的文件集合进行命令操作,{}代表文件集合,反斜杠以及前面的空格与后面的分号都不能少。

find . -name "*.dat" -exec cp {} /tmp \;

google code search

 

Google 有一个未公开的code search引擎 http://www.google.com/codesearch。专门搜索源代码时非常有用。比如搜索以下字符串:

lang:shell find {} exec cp

注意,不能输入 -exec,虽然你的目的是搜索字符串"-exec",  但搜索引擎认为你不想在结果中包括 "exec"。

(未完)

北峰 BF-5118 手台基本操作

北峰 BF-5118 手台分为高低段两种,41-43、45-47,分别与国内民放和美国FRS 两个频段的对讲机进行通信,可以进行软扩频。我拿到这台已经扩频,帮人进行调试,在网上没有找到说明书,只有自己摸索一下,现记录几种基本操作,欢迎补充!基本功能机身顶部的两个旋钮,左边的是电源开关,兼音量旋钮。右侧的旋钮是SQL 静噪旋钮,用于调整过滤背景噪音的级别。选择好频率后,可顺时针旋转此旋钮,直到听不到噪音为止。一般在对方信号很好的情况下,可将这个旋钮顺时针旋转到头,并一直保持这个位置即可。发射键,机身左侧最大的按钮即发射键(PTT),按住此键时,可以进行发射,同时失去接收功能。Moni 键,按下此键,SQL 静噪旋钮即失去作用。应该在对方信号很弱,混杂在背景噪音中时使用。SCAN 键,长按此键,可进行频率或者信道扫描。FUN 键,功能按钮,与其他按钮进行配合使用。CH+/CH- 按钮,可在信道模式下更改信道。A、B、C、D 四个按钮,纯粹作为装饰,没有任何功能。进入信道模式直接开机,将进入信道模式。即只能使用存储好的信道,比如CH 00、CH 01 等。此模式下,使用右侧的CH+/CH- 按钮更改当前信道。进入频率模式在频率模式下,能够手动输入频点。如下操作:先关机,按住SCAN 键不放,然后开机,开机后显示当前频点。你可以使用数字键,输入任意本机允许的频点,输入后即可在当前频点进行发射和接收。比如输入...

北峰 BF-5118 手台分为高低段两种,41-43、45-47,分别与国内民放和美国FRS 两个频段的对讲机进行通信,可以进行软扩频

我拿到这台已经扩频,帮人进行调试,在网上没有找到说明书,只有自己摸索一下,现记录几种基本操作,欢迎补充!

基本功能

机身顶部的两个旋钮,左边的是电源开关,兼音量旋钮。右侧的旋钮是SQL 静噪旋钮,用于调整过滤背景噪音的级别。选择好频率后,可顺时针旋转此旋钮,直到听不到噪音为止。一般在对方信号很好的情况下,可将这个旋钮顺时针旋转到头,并一直保持这个位置即可。

发射键,机身左侧最大的按钮即发射键(PTT),按住此键时,可以进行发射,同时失去接收功能。

Moni 键,按下此键,SQL 静噪旋钮即失去作用。应该在对方信号很弱,混杂在背景噪音中时使用。

SCAN 键,长按此键,可进行频率或者信道扫描。

FUN 键,功能按钮,与其他按钮进行配合使用。

CH+/CH- 按钮,可在信道模式下更改信道。

A、B、C、D 四个按钮,纯粹作为装饰,没有任何功能。

进入信道模式

直接开机,将进入信道模式。即只能使用存储好的信道,比如CH 00、

CH 01 等。

此模式下,使用右侧的CH+/CH- 按钮更改当前信道。

进入频率模式

在频率模式下,能够手动输入频点。如下操作:

先关机,按住SCAN 键不放,然后开机,开机后显示当前频点。

你可以使用数字键,输入任意本机允许的频点,输入后即可在当前频点进行发射和接收。比如输入 439.750(北京中继频点),或者438.500(北京直接通联频点)。

保存频点到一个信道

先关机,按住FUN 键不放,然后开机,开机后显示当前频点和当前信道。

先使用CH+/CH- 按钮调整到想要存储的信道,然后使用数字键输入想要使用的的频点,之后按发射键(PTT),则输入的频点被存入当前信道。

参考资源

Windows XP 上USB 2.0 不工作故障解决

故障描述电脑为IBM R51 笔记本,安装Windows XP Professional 操作系统,Windows Updates 到SP1 。笔记本电脑本身支持USB 2.0 (High-Speed) 接口,不过插入USB 2.0 (High-Speed) 的移动硬盘,屏幕右下角提示:a high...

故障描述

电脑为IBM R51 笔记本,安装Windows XP Professional 操作系统,Windows Updates 到SP1 。

笔记本电脑本身支持USB 2.0 (High-Speed) 接口,不过插入USB 2.0 (High-Speed) 的移动硬盘,屏幕右下角提示:

a high speed device plugged into a non-high speed Usb hub

故障原因

USB 2.0 (High-Speed) 驱动程序仅包含在XP SP1 更新中,在安装操作系统时并未安装,Windows Updates 虽然升级到了SP1 ,但没有自动更新USB 控制器的驱动程序,因此这个硬件没有得到真正利用。

解决方案

手动更新USB 控制器的驱动程序。进入控制面板,打开设备管理器,选择Universal Serial Bus Controllers 分支,找到如下设备:

Intel(r) 82801DB/DBM USB2 Enhanced Host Controller - 24CD

显示其属性,发现这个设备没有安装任何驱动程序,但没有标记黄色警告,手动为其安装驱动程序,通过如下路径(英文系统):

Driver tab -> Update Driver -> next

Windows 自己会找到驱动程序,并自动安装,安装后设备名称变为:

Intel(r) 82801DB/DBM USB 2.0 Enhanced Host Controller - 24CD

再次插入移动硬盘,一切正常,实测了一下速率,从移动硬盘向笔记本硬盘copy 一个697Mb 的文件,用时35秒,19Mbps,虽然与USB 2.0 的最高速率480Mbps 差得很远,但以前USB 1.1 的实测速率也远远达不到标称的12Mbps,只有2Mbps 左右。相对以前快了近10倍。

参考信息

一些解决问题过程中找到的资源,对于解决由其它原因导致的此类问题会有帮助。

一个同类问题的讨论:Windows USB 2.0 drivers w/out SP2,讨论中有些观点是错误的,不过包含了一些有益链接。

一篇非常有用的文章:How to check USB version

Comment from StealthMullet 
Date: 03/08/2004 09:46AM PST
Comment

Access Device Manager, click the + next to Uinversal Serial Bus 
controllers, if there is USB 2.0 Enhanced Open Host Controller
there then you have USB 2.0.

一条来自微软的支持信息:Universal Serial Bus 2.0 Support in Windows XP,由此可以确认:在XP 中,USB 2.0 (High-Speed) 驱动程序被包含在SP1 更新中,不需要安装SP2 。

一个第三方的USB 2.0 驱动程序,可以用于Win 98 系统和Win 2000 系统:http://www.perfectdrivers.com/howto/usb20drivers.html

这个驱动程序也提供了针对VIA 芯片的XP 版本,不过作者说明,对于XP 用户最好的方法是升级到SP1 ,那里包含了USB 2.0 驱动程序。

The third folder is the USB 2.0 drivers for Windows XP. A better way
to get these drivers for XP is to do the Windows updates. Service Pack
1 (sp1) contains the USB 2.0 drivers for XP.

一则有关USB 2.0 的详细介绍(来自微软):

USB 2.0 Support in Windows XP: High Speed at Last

MT 中控制Entries 的URL 名称

在Six apart 读到一篇文章,介绍了MT 3.2 版本支持的一项新功能:Entry basename control,在3.2 版本之前,MT不支持手动命名Entries 发布的URL ,是根据Title 自动生成的,如果是英文标题,会将其转化为小写,空格转化为下划线,并自动截断。如果是中文标题,则汉字部分被字母填充,类似于下面这样:mt_oeoeoeentrie.html在3.2 版本中提供了额外的Field 对URL 进行手动指定,这样的URL 就更友好。不过我一直使用3.14 版本,并通过变通的方法实现了URL手动命名。为此需要占用Entries...

Six apart 读到一篇文章,介绍了MT 3.2 版本支持的一项新功能:Entry basename control,在3.2 版本之前,MT不支持手动命名Entries 发布的URL ,是根据Title 自动生成的,如果是英文标题,会将其转化为小写,空格转化为下划线,并自动截断。如果是中文标题,则汉字部分被字母填充,类似于下面这样:

mt_oeoeoeentrie.html

在3.2 版本中提供了额外的Field 对URL 进行手动指定,这样的URL 就更友好。不过我一直使用3.14 版本,并通过变通的方法实现了URL手动命名。

为此需要占用Entries 编辑界面中的Extended Entry 项,并在Individual Archives 中进行设置。

WEBLOG CONFIG -> Archives Files -> Archives

选中Individual 的复选框,在Archives File Template 编辑框中设置:

<MTSubCategoryPath>/<MTIfNonEmpty tag="MTEntryMore"><$MTEntryMore dirify="1"$><MTElse><MTEntryDate format="%Y%m%d%H%M"></MTElse></MTIfNonEmpty>.html

<MTSubCategoryPath> 标签相当于:

<MTParentCategories glue="/"><MTCategoryLabel dirify="1"></MTParentCategories>

可将当前项所属所有父分类按层级,由"/" 进行连接,返回按文件路径规则格式化的字符串。

MTEntryMore 标签从Extended Entry 项中提取URL 命名,如果没有指定,则采用发布的日期命名URL 。

例如,我在本篇Entry 的Extended Entry 中指定:

mt entry basename control

则生成如下URL(本篇所属分类:Study Notes -> Web):

study_notes/web/mt_entry_basename_control.html
当然,如果你使用或者升级到3.2 版本,就不用费这么大的周折了.

表与索引的重命名 RENAME

在DB2 中重命名表或者索引db2=> RENAME TABLE EMP TO EMPLOYEEdb2=> RENAME TABLE ABC.EMP TO EMPLOYEE db2=> RENAME INDEX NEW-IND...

在DB2 中重命名表或者索引

db2=> RENAME TABLE EMP TO EMPLOYEE
db2=> RENAME TABLE ABC.EMP TO EMPLOYEE
db2=> RENAME INDEX NEW-IND TO IND
db2=> RENAME INDEX ABC.NEW-IND TO IND

拥有检查约束和非主键自增列的表不允许重命名,在视图、触发器、函数或者物化查询表中被引用的表也不允许重命名,只能Drop 掉,重新创建。

参考资源 

杨靖宇将军

最近央视八套正在播放连续剧《杨靖宇将军》,很小的时候就有这样的记忆:杨靖宇将军忍受着严寒与断粮几天的饥饿,只身一人在雪山 密林中与日本鬼子周旋多日,打光了所有的子弹,把最后一颗子弹留给了自己。日本人最后想知道杨靖宇这些天究竟吃了些什么,便剖开他的胃,在里面只发现了树 皮、草根和棉花。 看着剧情,借助于网络,相信可以把这个记忆重新添补一下,与感兴趣的朋友共享,先了解一下杨靖宇将军生平,最富传奇的也是大家最关心的杨靖宇将军究竟是如何牺牲的,其实并不是用最后一颗子弹自尽,将军是一直战斗到牺牲,牺牲时留下了三把手枪和二百多发子弹。记者后来居然还采访到在杨靖宇将军牺牲现场的几个抗联叛徒,他们描述了更多的杨靖宇将军牺牲时的详细情况。最后来看一下战斗中幸存下来的警卫员对杨将军的回忆。 杨靖宇留下了两张让人难忘的照片,一张是半身军装照,刚毅威武。另一张是牺牲后被日本人拍的头颅照,依然高傲,嘴角似乎还在嘲笑他的对手,可以在下面网站找到。 以上链接资料来源于网站:杨靖宇将军专题 http://www.jlplib.com.cn/yjy/a_page_1.htm...

最近央视八套正在播放连续剧《杨靖宇将军》,很小的时候就有这样的记忆:杨靖宇将军忍受着严寒与断粮几天的饥饿,只身一人在雪山 密林中与日本鬼子周旋多日,打光了所有的子弹,把最后一颗子弹留给了自己。日本人最后想知道杨靖宇这些天究竟吃了些什么,便剖开他的胃,在里面只发现了树 皮、草根和棉花。

看着剧情,借助于网络,相信可以把这个记忆重新添补一下,与感兴趣的朋友共享,先了解一下杨靖宇将军生平,最富传奇的也是大家最关心的杨靖宇将军究竟是如何牺牲的,其实并不是用最后一颗子弹自尽,将军是一直战斗到牺牲,牺牲时留下了三把手枪和二百多发子弹。记者后来居然还采访到在杨靖宇将军牺牲现场的几个抗联叛徒,他们描述了更多的杨靖宇将军牺牲时的详细情况。最后来看一下战斗中幸存下来的警卫员对杨将军的回忆

杨靖宇留下了两张让人难忘的照片,一张是半身军装照,刚毅威武。另一张是牺牲后被日本人拍的头颅照,依然高傲,嘴角似乎还在嘲笑他的对手,可以在下面网站找到。

以上链接资料来源于网站:杨靖宇将军专题

http://www.jlplib.com.cn/yjy/a_page_1.htm

Editlet 调整

让Editlet 编辑器产生<br /> ,而不是<br>在editor.html 中进行替换%3Cbr%3E%3Cbr%20/%3E 去除Editlet 自动添加的:<link xhref="css/sample.css" mce_href="css/sample.css" rel="stylesheet" type="text/css"> 编辑editor.html ,在getXHTML() 中注释://outStr='<link type="text/css" rel="stylesheet"...

让Editlet 编辑器产生<br /> ,而不是<br>

在editor.html 中进行替换
%3Cbr%3E
%3Cbr%20/%3E

去除Editlet 自动添加的:

<link xhref="css/sample.css" mce_href="css/sample.css" rel="stylesheet" type="text/css">

编辑editor.html ,在getXHTML() 中注释:

//outStr='<link type="text/css" rel="stylesheet" xhref="'+css_url+'" mce_href="'+css_url+'" />';

在setMode() 中修改:

//objEditArea.document.body.innerHTML = html.toString()+'<link type="text/css" rel="stylesheet" xhref="'+css_url+'" mce_href="'+css_url+'">';
objEditArea.document.body.innerHTML = html.toString();//+'<link type="text/css" rel="stylesheet" xhref="'+css_url+'" mce_href="'+css_url+'">';
//objEditArea.document.body.innerHTML = document.frmShowEditor.txtSource.value+'<link type="text/css" rel="stylesheet" xhref="'+css_url+'" mce_href="'+css_url+'">' ;
objEditArea.document.body.innerHTML = document.frmShowEditor.txtSource.value;//+'<link type="text/css" rel="stylesheet" xhref="'+css_url+'" mce_href="'+css_url+'">' ;
以上改动没有起到作用,由于源代码结构比较混乱,还有一层encode,要搞清楚需要很大精力,已经决定放弃继续在这套源码之上的refines了。

检验网页是否符合W3C 推荐的标准

正文W3C 提供了一个免费的在线验证服务,访问如下链接:http://validator.w3.org/在Address 中填入你需要验证的网页地址,点击Check 。如果返回:Passed validation则说明你的网页已经达到了标准,否则,会显示失败,并提示错误数目。Failed validation, 4 errors 下面会显示错误列表,可以根据提示信息修改网页。笔者的网站经过检查,错误主要集中在以下一些地方:IMG标签没有加入alt 属性。 下列标签容易忽视在结尾加入标签结束标志 <tag />。 IMG HR INPUT...

正文

W3C 提供了一个免费的在线验证服务,访问如下链接:

http://validator.w3.org/

在Address 中填入你需要验证的网页地址,点击Check 。如果返回:

Passed validation

则说明你的网页已经达到了标准,否则,会显示失败,并提示错误数目。

Failed validation, 4 errors 

下面会显示错误列表,可以根据提示信息修改网页。

笔者的网站经过检查,错误主要集中在以下一些地方:

  1. IMG标签没有加入alt 属性。
  2. 下列标签容易忽视在结尾加入标签结束标志 <tag />。
    • IMG
    • HR
    • INPUT
    • META
    • BR
  3. 属性的值没有使用双引号"" 引起,即使属性值是数字也需要。
  4. 错误的标签包含关系,比如把H1 标签包含在A 标签当中。
  5. HR 标签中不应直接定义样式,应通过CSS 定义。
  6. 使用了大写的标签名称或者属性。

但这个工具也存在一些问题,比如:

  • 对于网页中类似下面的链接,会对连接符& 的部分检出错误,但实际上这只是一个稍微复杂一些的超链接。
http://www-900.ibm.com/cn/support/forum/app/tscforum/list?categoryid=13&areaid=06
  • 网页中如果包含一些特殊字符,尤其是程序源码(即使已经包含在PRE 标签中),则会检出很多错误,甚至无法进行检测。

参考资源

使用Javascript 高亮搜索引擎关键词

需求 很大一部分网站,搜索引擎是其最重要的外部访问来源,某些情况,用户宁愿在简洁的搜索页面敲入关键词,也不愿按照一条已知的访问路径来找到资源。如果你的页面很大,定位搜索的关键词会不太容易,并不是每个使用者都知道使用"Ctrl+F",如果能将这些关键词高亮显示,是个很好的主意。 当用户在Google 中使用“db2 学习笔记”作为关键词进行搜索时,如果你的网页列在了结果中,用户点开你的网页,页面中所有出现"db2" 和"学习笔记" 地方,都使用特殊的底色进行了标识。 Hilite 我在Scott Yang 的网站,看到了Search Engine Highlight Javascript ,使用他编写的程序:se_hilite.js 1.1 ,可以很轻松的在网站实现以上功能。 安装很简单,将se_hilite.js 保存在网站目录,并在每一个需要高亮关键词的网页中引用这个js...

需求

很大一部分网站,搜索引擎是其最重要的外部访问来源,某些情况,用户宁愿在简洁的搜索页面敲入关键词,也不愿按照一条已知的访问路径来找到资源。如果你的页面很大,定位搜索的关键词会不太容易,并不是每个使用者都知道使用"Ctrl+F",如果能将这些关键词高亮显示,是个很好的主意。

当用户在Google 中使用“db2 学习笔记”作为关键词进行搜索时,如果你的网页列在了结果中,用户点开你的网页,页面中所有出现"db2" 和"学习笔记" 地方,都使用特殊的底色进行了标识。

Hilite

我在Scott Yang 的网站,看到了Search Engine Highlight Javascript ,使用他编写的程序:se_hilite.js 1.1 ,可以很轻松的在网站实现以上功能。

安装很简单,将se_hilite.js 保存在网站目录,并在每一个需要高亮关键词的网页中引用这个js 文件:

<script type="text/javascript" xsrc="se_hilite.js"></script>

之后在CSS 样式单中加入如下定义:

.hilite { background-color: #ff0; }

如果在se_hilite.js 中设定了:

Hilite.style_name_suffix: true; 

则还需要定义额外的CSS 样式:

.hilite1 { background-color: #ff0; }
.hilite2 { background-color: #f0f; }
.hilite3 { background-color: #0ff; }
.hilite4 ...

原理

如果在A 页面点击链接到达B 页面,则在B 页面可通过document.refferer 读到A 页面的链接。如果A 页面是一个搜索结果页面,则在B 页面读到的refferer 看起来会像下面这个样子:

http://www.google.com/search?q=db2+%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0&hl=en&lr=&newwindow=1

通过解析这个链接,取出每一个关键词,并在B 页面装载完成之后,使用Javascript 对页面进行搜索,对每一个关键词位置加入描述底色的代码。

这个动作实际是在用户的客户端浏览器中完成的,并没有对你的实际网页内容做任何更改。

功能扩展

笔者下载并在网站安装了Hilite,同时做了以下功能扩展:

  1. 增加了对中文关键词的支持。
  2. 增加了对关键词的链接索引,可以通过锚点(anchor)迅速链接到关键词首次出现的地方。
  3. 增加了国内流行的搜索引擎,因为要分析refferer,所以针对每个搜索引擎需提供单独的代码。作者的程序结构非常好,所以很容易扩充。
  4. 增加了搜索站内相关文章的功能,不需要动态程序,只需要利用搜索引擎和Meta 标签,当然这也需要对网站页面进行更多的修改。
  5. 额外增加了一个微不足道的小功能,把用户搜索的关键词再次放到这个页面上,让用户可以快速的发起第二次搜索(可以是在你网站内部)。

中文支持

搜索时浏览器已将URI 进行编码处理,根据页面所采用的字符集不同,编码结果也不同。对于同一个关键词“db2 学习笔记”,Google(UTF-8) 和Baidu(GB2312) 的页面分别会产生不同的编码:

http://www.google.com/search?hl=en&q=db2+%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0
http://www.baidu.com/s?wd=db2+%D1%A7%CF%B0%B1%CA%BC%C7&cl=3

Javascript 中相应提供了用于解码的函数:

decodeURI(encodedURIString)
decodeURIComponent(encodedURIString)

上述decode 函数只能处理UTF-8 编码的URI,如果把GB2312 编码的URI作为参数,会抛出一个错误:

The URI to be decoded is not a valid encoding

我们必须自己实现一个处理GB2312 编码URI 的函数。

Keyword.decodeGBURI = function(strcode) {
    try {
        var result = '';
        for ( var i = 0; i < strcode.length; i ++) {
            var thischr = strcode.substr(i,1);
            if (thischr == '%') { // 则后面为16进制编码
                var ascii = eval('0x' + strcode.substr(i+1,2)); // 取出2位16进制值,转成10进制ascii码
                if ((ascii > 0x20 && ascii < 0x30) ||
                    (ascii > 0x39 && ascii < 0x41) || 
                    (ascii > 0x5a && ascii < 0x61) ||
                    (ascii > 0x7a && ascii < 0x91)) { // !"#$%&'()*+,-./ :;<=>?@ [\]^_;` {|}~
                    try {
                        result = result + String.fromCharCodeAt(ascii); // 还原为单字节字符    
                    } catch (e)    { // ie6不支持,放弃,继续处理
                        i = i + 2;
                        continue;
                    }
                    
                    i = i + 2;
                } else { // 双字节字符
                    ascii = eval('0x' + strcode.substr(i+1,2) + strcode.substr(i+4,2)); // 取出4位16进制值,转成10进制ascii码
                    try    {
                        result = result + chrval(ascii); // 还原为双字节字符,调用vb函数处理gb2312编码
                    } catch (e) { // 不支持vb脚本,放弃这个双字节字符,继续处理下面
                        i = i + 5; 
                        continue;
                    }
                    i = i + 5;
                }
            } else if (thischr == '+')
                    result = result + ' '; // 加号还原为空白
            else // 字母,不需要解码
                    result = result + thischr;
        }
    } catch(e) { return false; };
        
    return result;
};

这个函数由Javascript 编写,但为了完成转换,额外调用了一个自定义的VBscript 函数chrval(vstrin) :

function chrval(vstrin)
    chrval = chr(vstrin)
end function

函数chr() 根据ASCII 码取得对应字符。Javascript 语言使用Unicode 编码,未提供此函数。因此,我们必须将这个函数保存在一个单独的.vbs 文件中,并通过如下语句进行引用,供Javascript 调用。

<script type="vbscript" xsrc="/js/chr.vbs"></script>

关键词链接索引

如果希望打开此功能,需要设定:

Keyword.index: true,

对应实现此功能,增加了函数:

Keyword.indexHTML = function(html, query) {
    var re = new Array();
    var q = '您的查询关键词标明如下,点击可以跳到文中首次出现的位置:';
    for (var i = 0; i < query.length; i ++) {
        if (query[i]) {
            var classname = Keyword.style_name;
            if (Keyword.style_name_suffix)
                classname += (re.length==0?'':re.length);
            re.push([new RegExp('('+query[i]+')', "gi"), classname]);
            q += '<span class="' + classname + '">' + (query[i]).link('#kIdx' + i) + ' </span>';
        }
    }
    var last = 0;
    var tag = '<';
    var skip = false;
    var skipre = new RegExp('^(script|style|textarea)', 'gi');
    var part = null;
    var result = '';
    while (last >= 0) {
        var pos = html.indexOf(tag, last);
        if (pos < 0) {
            part = html.substring(last);
            last = -1;
        } else {
            part = html.substring(last, pos);
            last = pos+1;
        }
        if (tag == '<') {
            if (!skip) {
                for (var j = 0; j < re.length; j ++) {
                    part = part.replace(re[j][0], ''.anchor('kIdx' + j) + '$1');
                }
            } else
                skip = false;
        } else if (part.match(skipre)) {
            skip = true;
        }        result += part + (pos < 0 ? '' : tag);
        tag = tag == '<' ? '>' : '<';
    }
    result = q + '<p>' + result;
    return result;
};

支持更多搜索引擎

不同的搜索引擎会产生不同结构的URI ,需要对其进行分析,确定解码函数(UTF-8 或者GB2312),并提取出关键词。因此,要实现某个搜索引擎关键词的高亮显示,在以下函数中增加相关搜索引擎定义即可:

Keyword.decodeReferrer(referrer) 

搜索相关文章

原理:在每个网页中通过Meta 标签定义关键词,如果用户通过搜索引擎找到了页面A,那么将页面A 中定义的关键词(如果定义了多个,只取前两个)提交到搜索引擎继续搜索。

要使用此功能,需要:

  • 修改参数refill2:
Keyword.refill2: true,
  • 修改参数element2:
Keyword.element2: 'w',
  • 在页面中加入如下代码(以Baidu 为例),参数element2 的值应与搜索引擎用于提交关键词的文本框名称一致。
<!-- Search Baidu -->
<form name="baidu2" method="get" action="http://www.baidu.com/baidu">
  <input name="tn" type="hidden" value="bds" />
  <input name="cl" type="hidden" value="3" />
  <input name="si" type="hidden" value="aiview.com" />
  <input name="ct" type="hidden" value="2097152" />
  <input id="w" name="w" type="hidden" size="34" maxlength="100" class="frame" />
  <a xhref='javascript:document.baidu2.submit()'>站内相关文章&nbsp;&gt;</a>
</form>
<!-- Search Baidu -->

便捷搜索

要使用此功能,需要:

  • 修改参数refill1:
Keyword.refill1: true,
  • 修改参数element1:
Keyword.element1: 'word',
  • 在页面中加入如下代码(以Baidu 为例),参数element1 的值应与搜索引擎用于提交关键词的文本框名称一致。
<!-- Search Baidu -->
<form name="baidu" method="get" action="http://www.baidu.com/baidu">
  <input name="tn" type="hidden" value="bds" />
  <input name="cl" type="hidden" value="3" />
  <input name="si" type="hidden" value="aiview.com" />
  <input name="ct" type="hidden" value="2097152" />
  <input id="word" name="word" size="34" maxlength="100" class="frame" value="wwf" tabindex="1" />
  <input type="submit" value="站内搜索" class="buttonface" tabindex="2" />
</form>
<!-- Search Baidu -->

代码下载

Scott Yang 的原程序只有一个文件se_hilite.js 1.1 (24 October 2004) - latest ,笔者修改的版本包含2个文件:keywords.js 1.2.0 chr.vbs

由于程序修改后,已经不仅是Highlight 的功能,因此更改了程序中对象的名称为Keyword 。

参考资源

更新 2007-02-07

优化了针对不同浏览器的onload 事件处理 ,使highlight 加载得更快。这里下载更新的keyword.js v1.30.

Apache 2.0.46 整合Tomcat 5.5.9

Apache 使用RHEL AS3 中的默认安装版本,如果没有安装,到Apache 网站下载。 http://www.apache.org/ Tomcat 下载: http://jakarta.apache.org/tomcat/ JRE 或者JDK下载: http://www.sun.com/j2se/ 安装过程参考: linux下Tomcat 5.0.20 与...

Apache 使用RHEL AS3 中的默认安装版本,如果没有安装,到Apache 网站下载。

http://www.apache.org/

Tomcat 下载:

http://jakarta.apache.org/tomcat/

JRE 或者JDK下载:

http://www.sun.com/j2se/

安装过程参考:

两者分别安装成功,并可正常运行,时间原因,未继续完成整合配置,不过上面的资料可供今后参考。

安装MT Collect 插件,实现文章内自动索引标题

安装环境 Movable Type 3.14 RedHat Linux 安装配置插件 下载插件 安装配置说明 作者网站,还有很多其它插件。 将文件Collect.pl 上传到服务器上MT 的plugins 目录,并设置权限:$ tag -zxvf...

安装环境

  • Movable Type 3.14
  • RedHat Linux

安装配置插件

下载插件

安装配置说明

作者网站,还有很多其它插件。

将文件Collect.pl 上传到服务器上MT 的plugins 目录,并设置权限:

$ tag -zxvf Collect.tar.gz
$ cp Collect/Collect.pl /var/www/cgi-bin/mt/plugins/
$ chmod 755 /var/www/cgi-bin/mt/plugins/Collect.pl

修改MT 模板

Individual Archives 模板相关部分如下:

  <MTCollect tags="h3,H3"><MTCollectThis><$MTEntryBody$></MTCollectThis>
  <MTIfCollected>
  <table align="right" width="250" class="section" bgcolor="#EEEEEE" style="padding-top: 2">
  <tr>
    <td bgcolor="#BBBBBB">目录</td>
  </tr>
  <tr>
    <td>¡¡
      <ol>
        <MTCollected><li><a xhref="http://blog.alex.com/cgi-bin/mt/mt.cgi#<$MTCollectedIndex$>" mce_href="http://blog.alex.com/cgi-bin/mt/mt.cgi#<$MTCollectedIndex$>"><$MTCollectedContent$></a></li>
        </MTCollected>
      </ol>
    </td>
  </tr>
  </table>
  </MTIfCollected>
  </MTCollect>
  <MTCollect tags="h3,H3"><MTCollectThis show="1" h3="&lt;a name=&quot;[N]&quot; \/&gt;/" H3="&lt;a name=&quot;[N]&quot; \/&gt;/"><$MTEntryBody$></MTCollectThis>
  </MTCollect>

上面的模板共使用了两次MTCollect 标签,第一次用于生成索引目录,第二次用于在索引的段落标题中加入锚链接(anchor)。MTCollect 标签的tags 属性用于指定收集的HTML 标签名称,区分大小写,如果有多个标签,用逗号隔开,这里我们收集标题标签h3 与 H3。

<MTCollect tags="h3,H3">

MTCollectThis 标签用于指定收集的对象,并对收集的标签赋以新值。需要用到tag="new value" 的格式,tag 必须是上级MTCollect 收集的标签名称。我们需要在标题中加入锚链接,并保存原标题。因此我们如下定义模板:

<MTCollectThis show="1" h3="&lt;a name=&quot;[N]&quot; \/&gt;/" H3="&lt;a name=&quot;[N]&quot; \/&gt;/"><$MTEntryBody$></MTCollectThis>

上面的模板会将原文档中的内容:

<h3>段落标题1</h3>
<h3>段落标题2</h3>

替换成如下内容:

<a name="1" /><h3>段落标题1</h3>
<a name="2 /><h3>段落标题2</h3>

新值当中的最后一个斜线 "/" 代表收集到的内容,如果需要写入一个真实的斜线,比如A 标签的结束标志 "<a />",则需要使用转义字符 "\/" 。

方括号"[]" 中的 "N" 代表收集序号,我们恰好利用这个序号来作为锚链接的值。

属性 show="1" 告诉MTCollect ,不仅显示收集并替换的新值,也显示作为收集对象的原始内容。

此插件所有标签的使用方法,请参考:

http://www.staggernation.com/mtplugins/Collect/

使用

在编写新的Blog 时,使用H3 或h3 作为文章的段落标题,上述代码将会自动识别,并生成目录索引,生成的目录索引自动编号,并可以链接到对应文章标题处。具体实例可参看本文右上部的目录。

 

安装MT Related Entries 插件,实现相关文章

安装环境 Movable Type 3.14 Redhat Linux Related Entries 2.0  配置插件 下载插件 安装和配置指南 解开压缩包,将文件RelatedEntries.pl 上传到服务器上MT 脚本文件所在的目录,例如:/cgi-bin/mt/plugins/ 如果MT...

安装环境

配置插件

下载插件

安装和配置指南

解开压缩包,将文件RelatedEntries.pl 上传到服务器上MT 脚本文件所在的目录,例如:

/cgi-bin/mt/plugins/

如果MT 根目录下plugins 目录不存在,则手动创建。

设置.pl 文件的权限为 755

chmod 755 RelatedEntries.pl

之后就可以在MT 的模板中进行调用了。

修改MT 模板

在Individual Archives 模板中定义如下:

  <MTRelatedEntries>
  <p>
  <b>相关文章</b>
  <ul>
    <MTEntries lastn="5"><li><$MTInclude module="EntryLinkWithDate"$></li></MTEntries>
  </ul>
  </p>
  </MTRelatedEntries>

Rebuild 站点即可。

Update

已改用关联性更准确的plugin TagSupplymentals,参考related entries by tags

 

Editlet 功能扩展:增加标题<Hn>和预定格式<PRE>

需求 Editlet 当前版本未提供标题定义功能<H1>...<H6>,虽然可以通过定义<P class="header1"></p> 来达到相同的显示效果,但真正的标题可以反映良好的页面结构,对于自动抓取网页的程序也更友好(Crawl-Friendly),有关标题的使用可以参见使用真正的标题,这是网站亲和力设计的一部分。 预定格式<PRE>标签,用于在网页上保持文本的原有格式,对于在网页上显示程序源代码十分有用。 本文内容基于已经解除限制的Editlet 版本。 代码 将文本Text加入形如<TAG>Text</TAG> 这样的标签,DHTML 提供了标准的命令:FormatBlock,该命令可通过如下方式调用:execCommand('FormatBlock', false, '<H1>')HRESULT execCommand(          BSTR...

需求

Editlet 当前版本未提供标题定义功能<H1>...<H6>,虽然可以通过定义<P class="header1"></p> 来达到相同的显示效果,但真正的标题可以反映良好的页面结构,对于自动抓取网页的程序也更友好(Crawl-Friendly),有关标题的使用可以参见使用真正的标题,这是网站亲和力设计的一部分。

预定格式<PRE>标签,用于在网页上保持文本的原有格式,对于在网页上显示程序源代码十分有用。

本文内容基于已经解除限制的Editlet 版本

代码

将文本Text加入形如<TAG>Text</TAG> 这样的标签,DHTML 提供了标准的命令:FormatBlock,该命令可通过如下方式调用:

execCommand('FormatBlock', false, '<H1>')

HRESULT execCommand(          BSTR cmdID,
    VARIANT_BOOL showUI,
    VARIANT value,
    VARIANT_BOOL *pfRet
);

参数value 可以是一个HTML 标签,取值依赖于cmdID,当cmdID='FormatBlock' 时,已知的有效标签包括:

<H1>...<H6>,<P>,<DIV>,<PRE>,<UL>,<OL>,<DD>

首先将editlet.html 进行解码。为了需要,进行一下简单重构。

原来程序中用两个函数csslist() 与fontlist() 分别生成CSS与字体的下拉菜单,重构为一个通用的函数fmtList(),并更改原来函数的调用。原字体大小的下拉菜单采用硬编码,也改为使用fmtList() 生成。

原函数:

function fontList(l_str_fontnames)
{
 //alert("inside 1"+l_str_fontnames);
 var fontnames=l_str_fontnames;
 var lastfont=fontnames.substring(fontnames.lastIndexOf(",")+1,fontnames.length);
 //alert("inside 1");
 document.write('<OPTION selected value=Font>Font');
 document.write('<OPTION value="Arial">Arial');
 document.write('<OPTION value="Times New Roman">Times New Roman');
 document.write('<OPTION value="Verdana">Verdana');
 if(fontnames.length>0)
 {
 while(fontnames.indexOf(",")>=0)
 {
  var str=fontnames;
  var commaindex=fontnames.indexOf(",");
  var font=fontnames.substring(0,commaindex);
  fontnames=fontnames.substring(commaindex+1);
  document.write('<OPTION value='+font+'>'+font+'</OPTION>');
 }
 document.write('<OPTION value='+lastfont+'>'+lastfont+'</OPTION>');
 }
 //alert("Fontname="+font_name);
 setFontName(font_name);
}

重构后:

function fmtList(l_str_list, style)
{
 var item;
 var commaindex=l_str_list.indexOf(",");
 var first_item=l_str_list.substring(0,commaindex);
 l_str_list=l_str_list.substring(commaindex+1);
 document.write('<OPTION selected value='+first_item+'>'+first_item+'</OPTION>');
 while(1)
 {
  commaindex=l_str_list.indexOf(",");
  if(commaindex==-1)
  {
   if(l_str_list=="" || l_str_list==null)
    break;
   else
    item=l_str_list;
    l_str_list=null;
  }else
  {
   item=l_str_list.substring(0,commaindex);
   l_str_list=l_str_list.substring(commaindex+1);
  }
  document.write('<OPTION ');
  if(style=1) // show this item with css
   document.write('class='+item+' ');
  document.write('value='+item+'>'+item+'</OPTION>');
 } 

增加一个函数setBlock() ,在下拉菜单的onChange事件中调用。

function setBlock(formatblock)
{
 if(formatblock=="Block")
 {
  return;
 }
 cmdExec('formatblock',formatblock);
}

定义下拉菜单:

<TD>
<SELECT class="formfield" id=Block
onchange="setBlock('&lt;'+this[this.selectedIndex].value+'&gt;'); Block.value='Block';"
name=Block style="LEFT: 0px; TOP: 10px">
<script>fmtList(block_list,0);</script>
</SELECT>
</TD>  

在editor.html 中添加相关变量:

var l_str_block_flag = window.parent.block_flag;
var font_size_list = window.parent.font_size_list;
var block_list = window.parent.block_list;

var l_str_flist="function%20fmtList%28l_str_list%2C%20style%29%0D%0A%7B%0D%0A%09var%20item%3B%0D%0A%09var%20commaindex%3Dl_str_list.indexOf%28%22%2C%22%29%3B%0D%0A%09var%20first_item%3Dl_str_list.substring%280%2Ccommaindex%29%3B%0D%0A%09l_str_list%3Dl_str_list.substring%28commaindex+1%29%3B%0D%0A%09document.write%28%27%3COPTION%20selected%20value%3D%27+first_item+%27%3E%27+first_item+%27%3C/OPTION%3E%27%29%3B%0D%0A%09while%281%29%0D%0A%09%7B%0D%0A%09%09commaindex%3Dl_str_list.indexOf%28%22%2C%22%29%3B%0D%0A%09%09if%28commaindex%3D%3D-1%29%0D%0A%09%09%7B%0D%0A%09%09%09if%28l_str_list%3D%3D%22%22%20%7C%7C%20l_str_list%3D%3Dnull%29%0D%0A%09%09%09%09break%3B%0D%0A%09%09%09else%0D%0A%09%09%09%09item%3Dl_str_list%3B%0D%0A%09%09%09%09l_str_list%3Dnull%3B%0D%0A%09%09%7Delse%0D%0A%09%09%7B%0D%0A%09%09%09item%3Dl_str_list.substring%280%2Ccommaindex%29%3B%0D%0A%09%09%09l_str_list%3Dl_str_list.substring%28commaindex+1%29%3B%0D%0A%09%09%7D%0D%0A%09%09document.write%28%27%3COPTION%20%27%29%3B%0D%0A%09%09if%28style%3D1%29%20//%20show%20this%20item%20with%20css%0D%0A%09%09%09document.write%28%27class%3D%27+item+%27%20%27%29%3B%0D%0A%09%09document.write%28%27value%3D%27+item+%27%3E%27+item+%27%3C/OPTION%3E%27%29%3B%0D%0A%09%7D%09%0D%0A%7D"
//var l_str_script = l_str_script_start+l_str_script_button+l_str_script_table+l_str_script_image+l_str_script_link+l_str_script_clear+l_str_script_symbols+l_str_script_color+l_str_script_init+l_str_font+l_str_script_cleanhtml+l_str_script_open+l_str_fcss+l_str_copy+l_str_script_end;
var l_str_script = l_str_script_start+l_str_script_button+l_str_script_table+l_str_script_image+l_str_script_link+l_str_script_clear+l_str_script_symbols+l_str_script_color+l_str_script_init+l_str_font+l_str_script_cleanhtml+l_str_script_open+l_str_flist+l_str_copy+l_str_script_end;

var l_str_td_block = "%3CTD%3E%3CSELECT%20%20class%3D%22formfield%22%20id%3DBlock%20%0D%0A%09%20%20onchange%3D%22setBlock%28%27&lt;%27+this%5Bthis.selectedIndex%5D.value+%27&gt;%27%29%3B%20Block.value%3D%27Block%27%3B%22%20%0D%0A%09%20%20name%3DBlock%20style%3D%22LEFT%3A%200px%3B%20TOP%3A%2010px%22%3E%20%0D%0A%09%20%20%20%20%3Cscript%3EfmtList%28block_list%2C0%29%3B%3C/script%3E%3C/SELECT%3E%20%3C/TD%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20";

var l_str_td_font_type = "%3CTD%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CDIV%20class%3Dbutton%20onclick%3D%22cmdExec%28%27bold%27%29%22%3E%3CIMG%20align%3DabsMiddle%20%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22Bold%20text%22%20class%3Dicon%20src%3D%22"+icons_path+"/bold.gif%22%3E%20%3C/DIV%3E%3C/TD%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%3CTD%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CDIV%20class%3Dbutton%20onclick%3D%22cmdExec%28%27italic%27%29%22%3E%3CIMG%20align%3DabsMiddle%20%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3D%22Italic%20text%22%20class%3Dicon%20src%3D%22"+icons_path+"/italic.gif%22%3E%20%3C/DIV%3E%3C/TD%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%3CTD%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CDIV%20class%3Dbutton%20onclick%3D%22cmdExec%28%27underline%27%29%22%3E%3CIMG%20%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20align%3DabsMiddle%20title%3D%22Underlined%20text%22%20class%3Dicon%20%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20src%3D%22"+icons_path+"/under.gif%22%3E%20%3C/DIV%3E%3C/TD%3E";
var l_str_td_font_style = "%3CTD%3E%3CSELECT%20class%3D%22formfield%22%20onchange%3D%22setFont%28this%5Bthis.selectedIndex%5D.value%29%3B%20select1.value%3D%27Font%27%3B%22%20%0D%0A%09%20%20id%3Dselect1%20name%3Dselect1%20style%3D%22LEFT%3A%200px%3B%20TOP%3A%2010px%22%3E%20%0D%0A%09%20%20%20%20%3Cscript%3EfmtList%28font_list%2C0%29%3B%3C/script%3E%0D%0A%09%20%20%20%20%3C/SELECT%3E%20%3C/TD%3E%0D%0A%09%3CTD%3E%3CSELECT%20%20class%3D%22formfield%22%20id%3DFontSize%20%0D%0A%09%20%20onchange%3D%22setSize%28this%5Bthis.selectedIndex%5D.value%29%3B%20FontSize.value%3D%27Size%27%3B%22%20%0D%0A%09%20%20name%3DFontSize%20style%3D%22LEFT%3A%200px%3B%20TOP%3A%2010px%22%3E%20%0D%0A%09%20%20%20%20%3Cscript%3EfmtList%28font_size_list%2C0%29%3BsetFontSize%28font_size%29%3B%3C/script%3E%3C/SELECT%3E%20%3C/TD%3E";
var l_str_css="%3CTD%3E%3CSELECT%20class%3D%22cmbtext%22%20style%3D%22width%3A%20150px%3Bheight%3A%2019px%3B%22%20onchange%3DsetStyle%28editArea%2CHTMLMode%2C%22%22%2Cthis%5Bthis.selectedIndex%5D.text%29%3B%20css1.value%3D%27CSS%27%3B%0D%0A%09%20%20%20%09%20%20id%3Dcss1%20name%3Dcss1%20style1%3D%22LEFT%3A%200px%3B%20TOP%3A%2010px%22%3E%20%0D%0A%09%20%20%20%09%20%20%20%20%3Cscript%3EfmtList%28css_list%2C1%29%3B%3C/script%3E%0D%0A%09%20%20%20%09%20%20%20%20%3C/SELECT%3E%20%3C/TD%3E%0D%0A%09%20%20%20";

if(l_str_block_flag==1)
{
  l_str_piece_tr2_all += l_str_td_block + l_str_td_sep ;
  l_int_tr2_count++;
 } 

在editor.js 中修改并添加新的变量:

var block_flag   = 1 ;
var css_list   = "Choose Style,big-font,middle-font,small-font";
var font_list   = "Font,Arial,Times New Roman,Verdana,ËÎÌå,ºÚÌå";
var font_size_list  = "Size,1,2,3,4,5,6,7"
var block_list   = "Block,H1,H2,H3,H4,H5,PRE"

修改完成,今后只需对以上的变量进行维护即可。

参考资源

MT整合HTML在线编辑器Editlet(三)——统一CSS

正文 Editlet 提供了默认的CSS,可以在编辑界面为所选文字指定样式。此CSS 文件位置为:editlet 主目录/css/sample.css 如果你在编辑界面使用了此样式单定义,则Editlet 会自动在文章末尾加入外联样式单的链接,否则发布的文章将无法正确显示Editlet 中定义的样式。<LINK xhref="css/sample.css" mce_href="css/sample.css" type=text/css rel=stylesheet> 一般我们在MT 当中已经定义好了一套CSS,让Editlet 使用MT 的CSS...

正文

Editlet 提供了默认的CSS,可以在编辑界面为所选文字指定样式。此CSS 文件位置为:

editlet 主目录/css/sample.css

如果你在编辑界面使用了此样式单定义,则Editlet 会自动在文章末尾加入外联样式单的链接,否则发布的文章将无法正确显示Editlet 中定义的样式。

<LINK xhref="css/sample.css" mce_href="css/sample.css" type=text/css rel=stylesheet>

一般我们在MT 当中已经定义好了一套CSS,让Editlet 使用MT 的CSS 只需很简单的几步。

打开editor.js 进行编辑,首先确定没有关闭CSS 功能按钮,应有如下定义:

var css_flag    = 1 ;

然后修改CSS 文件指向,如果你的CSS 文件名称为:style.css,放在web 根目录下的css 文件夹中,则修改如下:

//var css_url   = "css/sample.css";
var css_url   = "/css/style.css";

接下来告诉Editlet 如何生成用于选择样式单的下拉列表,需要把你在style.css 中定义的样式名称,组成一个用逗号分隔的字符串,赋给变量css_list 。

//var css_list   = "header1,header2,text,pageheader,boldtext,tableheader1,tablecolor,italictext,textbg,tableheader2,tableheader3,graytext,smalltext,header3,header4,graytextbold,redtext,footertext";
var css_list   = "big-font,middle-font,small-font";

editor.js 修改完毕。

接着打开editor.html 进行编辑,只需修改一处,找到CSS 链接,修改如下:

<!--
<link type="text/css" rel="stylesheet" xhref="css/sample.css" mce_href="css/sample.css">
-->
<link type="text/css" rel="stylesheet" xhref="/css/style.css" mce_href="/css/style.css">

在此文件中链接CSS 文件,是为了使用实际的样式来格式化编辑界面中的每一个CSS 选项,实现“所见即所得”编辑。

修改完成,现在就可以在Editlet 的界面中使用MT 的CSS 了。

参考资源

MT整合HTML在线编辑器Editlet(二)

整合Editlet到MT 首先将Editlet上传到MT所在的Web服务器,可以放在任意目录,我的目录结构如下:/index.html /archives/ /weblog/static/ /weblog/editlet/ /weblog/editlet/editlet.html /weblog/editlet/editor.html MT模板 MT的后台管理页面均使用了模板,存放在目录 /tmpl/cms/ 。有两个模板与Entries的新增与编辑相关,分别是:header.tmpl、edit_entry.tmpl 。 editlet.html 主要做了如下几件事: 在head 部装载editor.js...

整合Editlet到MT

首先将Editlet上传到MT所在的Web服务器,可以放在任意目录,我的目录结构如下:

/index.html 
/archives/
/weblog/static/
/weblog/editlet/
/weblog/editlet/editlet.html
/weblog/editlet/editor.html
MT模板

MT的后台管理页面均使用了模板,存放在目录 /tmpl/cms/ 。有两个模板与Entries的新增与编辑相关,分别是:header.tmpl、edit_entry.tmpl 。

editlet.html 主要做了如下几件事:

  1. 在head 部装载editor.js 脚本,并定义Editlet程序文件的存放路径。
  2. 在body 标签中定义事件处理。
  3. 生成编辑工具条与文本区域。
  4. 为文本区域设定初始编辑内容。
  5. 保存文本区域的内容。

要实现整合,我们就需要把这几项功能实现在MT的以上两个模板中。

修改MT部分

我们把第1、2项功能放到header.tmpl 中实现。

打开header.tmpl 进行编辑,在<head>与</head>之间加入editlet.html 头部的脚本:

<script type="text/javascript" xsrc="/weblog/editlet/editor.js" mce_src="/weblog/editlet/editor.js"></script>
<script type="text/javascript">
var path="/weblog/editlet/";
</script>

其中变量path 指定为editlet目录的web绝对路径。

在<body>标签中加入editlet.html <body>标签中的script:
<body onafterprint="return window_onafterprint()" LANGUAGE="javascript">

保存header.tmpl ,注意修改文件之前先进行备份。

打开edit_entry.tmpl 进行编辑。先找到<form> 标签,在标签中加入:

onsubmit="return getContent();"
<form name="entry_form" method="post" onsubmit="return getContent();" action="<TMPL_VAR NAME=SCRIPT_URL>">

接着找到那个叫做Entry Body 的文本区域(textarea),将其注释掉:

<!--
<textarea class="full-width" name="text" id="text" tabindex="3" rows="<TMPL_IF NAME=DISP_PREFS_SHOW_EXTENDED>10<TMPL_ELSE>20</TMPL_IF>"><TMPL_VAR NAME=TEXT ESCAPE=HTML></textarea>
-->

在后面使用MT的<INCLUDE> 标签将editlet.html页面包含到这里,路径要写成editlet.html 在服务器上的文件系统绝对路径,写成web的绝对或相对路径都无法工作。

<INCLUDE TMPL="/var/www/html/weblog/editlet/editlet.html">

为了装载和保存编辑内容,添加一个隐含的文本框,id、name、value等属性与注释掉的<textarea> 相同:

<input name="text" id="text" type=hidden value="<TMPL_VAR NAME=TEXT ESCAPE=HTML>">

对MT的修改到此结束。

修改Editlet部分

打开Editlet.html 进行编辑。首先删除<table> 标签之前以及</table> 标签之后的所有代码,以上部分已经在MT模板中实现了。

接下来删除<form> 与</form> 标签之间的所有代码,保存的功能将通过在MT模板中定义的onsubmit 事件在editor.js中完成。

函数setContent() 用于设置文本区域的初始内容,我们将其改为:

//setContent('Your Content');
setContent(document.entry_form.text.value);

text 在edit_entry.tmpl 中定义,打开一个Entry 时,MT将数据写入这个文本框,保存时,MT读取其内容并保存。

函数setEditlet(path) 用于生成工具条和文本区域,保留这个部分。

为了使文本区域的宽度适合MT,修改<table> 标签:

<!--
<table border="0" width="760" cellspacing="0" cellpadding="2" style="HEIGHT: 151px; WIDTH: 760px">
-->
<table border="0" width="580" cellspacing="0" cellpadding="0" style="HEIGHT: 151px; WIDTH: 580px">

打开editor.js 进行编辑。

函数getContent() 将会在编辑内容被提交时执行,我们只需将此函数获得的文本区域内容交给MT来处理,修改如下:

//document.form1.hid_out_content.value = content1;
//document.form1.submit();
document.entry_form.text.value = content1;

变量content1 是Editlet 获取的文本区域内容。

找到函数setEditlet() 的定义,将其中的函数调用replace() 注释掉,replace() 所处理的一些转换,MT已经做过了,否则会重复处理。修改后如下:

function setEditlet(path){
 setEditor(path);
 //replace();
}

接下来修改一些配置参数。

将编辑区域的宽度缩小,以适合MT:

//var editorwidth  = 900 ;
var editorwidth  = 580 ;

关闭一些不使用的按钮,以使工具条宽度不超过580,只需要设置哪些后缀为"_flag" 的参数,将值改为0 即可。

var table_flag   = 0 ;
var help_flag    = 0 ;
var clean_html_flag   = 0 ;
var spellcheck_flag   = 0 ;
var save_flag    = 0 ;
var open_flag   = 0 ;
var xhtml_flag    = 0 ;

在编辑区域中按回车键,默认会产生一个<br> 标签,如下修改后,将产生<p> </p>标签,依个人编辑喜好而设定。

//var CarriageReturn  = false;
var CarriageReturn  = true;

Editlet 部分修改完毕。

测试

至此,基本功能整合完毕,进入MT后台管理,进行测试。

选择“NEW ENTRY”,应该可以看到新的编辑界面,测试一下各编辑按钮是否正常工作,测试保存功能。

选择“ENTRIES”,选择一篇已有文章打开编辑,测试原有内容是否正常装入,有无重复转换字符(比如空格、双引号"、连接符&)的问题,测试保存功能。

参考资源

MT整合HTML在线编辑器Editlet(一)——解除限制

前言 Movable Type 是一个非常不错的Blog网站发布和管理系统,目前最新版本是v3.14,后台提供了带有简单超文本编辑功能的文章编辑界面。 但缺乏诸如标题、字体、CSS、项目列表、表格和图片等内容的支持。虽然对于一个熟练的bloger来说,以上这些都可以通过手工在文章内容中嵌入超文本标签来完成,但却无法使其更专注于内容。在比较了多个超文本在线编辑器组件和产品之后,笔者选择了Editlet ,其在IE浏览器中运行的界面如下,本文就是在类似这样一个界面中发布的,比如我可以随意在其它网页或者word文件中拷贝一个与下面类似的图表,粘贴在这里。本文介绍把Editlet整合到MT后台发布管理系统的过程。 准备工作 系统应该先安装好MT,相关信息请参考车东的MT安装笔记:初始化和安全配置。 下载Editlet,目前Editlet提供JSP、PHP,PERL三个版本,不过网站以及程序包内均未标识版本信息。免费下载版本增加了一些限制:只能在运行Editlet的本机上访问,就是说只能通过http://localhost 或者http://127.0.0.1 进行访问;另外增加了时间限制,只能免费试用一个月。 下载地址:http://www.editlet.com 我下载了PHP版本。 笔者的安装环境: RedHat Linux...

前言

Movable Type 是一个非常不错的Blog网站发布和管理系统,目前最新版本是v3.14,后台提供了带有简单超文本编辑功能的文章编辑界面。

但缺乏诸如标题、字体、CSS、项目列表、表格和图片等内容的支持。虽然对于一个熟练的bloger来说,以上这些都可以通过手工在文章内容中嵌入超文本标签来完成,但却无法使其更专注于内容。在比较了多个超文本在线编辑器组件和产品之后,笔者选择了Editlet ,其在IE浏览器中运行的界面如下,本文就是在类似这样一个界面中发布的,比如我可以随意在其它网页或者word文件中拷贝一个与下面类似的图表,粘贴在这里。本文介绍把Editlet整合到MT后台发布管理系统的过程。

Editlet Full feature interface

准备工作

  1. 系统应该先安装好MT,相关信息请参考车东的MT安装笔记:初始化和安全配置
  2. 下载Editlet,目前Editlet提供JSP、PHP,PERL三个版本,不过网站以及程序包内均未标识版本信息。免费下载版本增加了一些限制:只能在运行Editlet的本机上访问,就是说只能通过http://localhost 或者http://127.0.0.1 进行访问;另外增加了时间限制,只能免费试用一个月。
    下载地址:http://www.editlet.com
    我下载了PHP版本。
  3. 笔者的安装环境:
    RedHat Linux
    Movable Type 3.14

解除Editlet的限制

Editlet程序的所有文件都在一个压缩包内,HTML和JS代码无需编译,虽然主要代码经过了加密处理,但也很容易找到限制的部分并去除。

如果仅仅使用Editlet的基本编辑功能(除去打开文件、保存文件、上载图片、拼写检查),甚至无需将其放在一个Web服务器上,就可以测试。

我们将其解压到web服务器根目录下的editlet目录,在editlet根目录有以下几个重要的文件:

  • editor.html
  • editor.js
  • editlet.html
  • multi_editlet.html

其中,editor.html包含了程序的核心代码,editlet.html是程序运行的主页面,它通过editor.js调用核心文件editor.html的代码。

multi_editlet.html是另外一个主页面,当在同一个页面需要使用多个编辑器窗口时使用,我们这里暂不考虑。

分析editor.html

程序以函数Decode2() 作为入口,函数内部首先进行软件是否过期检查,然后检查访问链接是否包含localhost或是127.0.0.1来确认是否在本机运行程序。

如果以上两项测试通过,程序执行函数enable() 和b() 。在enable() 中,判断是被editlet.html、multi_editlet.html 哪一个调用,并分别作出不同的配置。这个程序的作者很有意思,函数b(z) 中放了一堆迷惑的代码,实际只做了一件事:调用函数a() ,而核心的主体代码全部在函数a() 中。

函数a() 的主要作用:读取文件editor.js中以及本文件中的的配置参数,根据这些参数,动态生成用于显示编辑器页面的代码,然后调用解码函数写到浏览器。

这些动态组合的代码使用内置函数escape() 进行了编码,这样可以避免一些特殊字符在组合过程中出错。在根据配置参数组合完成之后,调用函数c(y) ,同样使用内置函数unescape() 进行解码,然后写到浏览器。函数c(y) 只有一行代码:

window.document.write(unescape(y));

如果需要查看这些编码了的代码到底做了什么,可以使用这个工具

了解程序流程后,去除限制,只需要删除掉相关函数并清理变量定义,然后以函数enable() 和a() 作为入口函数即可。具体的过程较为繁琐,不祥述,下面提供修改后的程序文件下载。

修正的文件中,也包含了editor.js,不仅去除了editlet.html 的限制代码,也重整了两个文件之间的配置参数调用关系,重整后,所有参数均在editor.js 中一处配置。

运行Editlet

在浏览器中运行editlet.html 所在的链接,这里是带全部编辑按钮的Editlet 演示页面。如果使用非IE浏览器,比如Firefox,会有部分调用了IE组件的按钮——比如表格——会被隐含起来。为了安全起见,该测试页面链接的所有动态程序文件(PHP)被删除。

(未完待续)

参考资源

我参与的公益活动

2005-06-24 白马雪山大众慈善学校捐助活动——北京义卖捐助会 活动照片 2005-04-02 WWFChina网站与露游网论坛共同组织的顺义义务植树活动 2004-11-23 再次听取珍妮·古道尔博士在清华大学的精彩演讲(根与牙)2004-10-17 关爱智障人士——慧灵福利社区献爱心活动有感(LVYE)2004-01-10 WWFChina 2003网站志愿者颁奖会2003 WWFChina 2002 网站志愿者颁奖会2002-04-20 WWFChina 2002地球日宣传活动2002-11-12 聆听珍妮·古道尔博士在北大的演讲(WWF)2002-03-09...

谁是WWF?  WWFChina网站志愿者做什么?  加入志愿者 >>