nusoap 客户端获取的中文数据变成问号的问题

问题描述:
使用 nosoap_client 类创建了一个客户端 SOAP 对象,然后从 $client->call 方法传回UTF-8编码的中文数据时,所有的中文数据均显示为问号(nusoap 版本为 0.9.5)

问题原因:
nusoap_client 的 decode_utf8 属性默认设置为 true,导致默认对UTF-8数据进行转码,在 nusoap 中的具体调用过程如下:

class.soapclient.php 中的 nusoap_client 的 parseResponse 在解析返回的数据时使用了 nusoap_parser 类

		$parser = new nusoap_parser($data, $this->xml_encoding, $this->operation, $this->decode_utf8);

class.soap_parser.php 中 soap_parser 类的 character_data 方法中又调用了utf8_decode进行了转码

		if ($this->xml_encoding=='UTF-8'){
			// TODO: add an option to disable this for folks who want
			// raw UTF-8 that, e.g., might not map to iso-8859-1
			// TODO: this can also be handled with xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, "ISO-8859-1");
			if($this->decode_utf8){
				$data = utf8_decode($data);
			}
		}

解决方法:
在使用 $client = new nusoap_client() 创建了对象之后马上设置 decode_utf8 为 false;

设置方法如下:

$client->decode_utf8 = false;

$client->decodeUTF8(false);

补充:
又遇到一则因服务端输出信息编码不匹配,导致 NuSOAP XML Parser 以’ISO-8859-1′编码解析而出错的问题,NuSOAP 库相关部分代码在 class.nusoap_base.php 中,具体位置如下:

    /**
	* charset encoding for outgoing messages
	*
	* @var      string
	* @access   public
	*/
    var $soap_defencoding = 'ISO-8859-1';
	//var $soap_defencoding = 'UTF-8';

解决方法:

$client->soap_defencoding = 'utf-8';	# 仅比上述问题增加该项设置
$client->xml_encoding = 'utf-8';	# 默认值
$client->decode_utf8 = false;

参考链接:
http://blog.csdn.net/mynamesucks/archive/2006/05/26/756480.aspx
http://lhx1026.javaeye.com/blog/506092
http://plog.longwin.com.tw/programming/2010/03/16/php-soap-nusoap-client-2010

Apache 按天分割日志的方法

这里介绍了两个管道日志程序来实现

A. 使用 cronolog 为每一天建立一个新的日志

从 http://cronolog.org/download/ 可以下载 cronolog 程序,把下载到的 cronolog 程序并放到 Apache 的 bin 目录下(详细参数参见:http://cronolog.org/usage.html

主配置文件中的使用方法

ErrorLog "|bin/cronolog logs/error_%Y%m%d.log"
CustomLog "|bin/cronolog logs/access_%Y%m%d.log" combined

虚拟主机配置文件中的使用方法

ServerAdmin webmaster@localhost
DocumentRoot "E:/htdocs"
ServerName localhost
ErrorLog "|bin/cronolog logs/localhost/error_%Y%m%d.log"
CustomLog "|bin/cronolog logs/localhost/access_%Y%m%d.log" combined

B. 使用 rotatelogs 每隔一天记录一个日志

rotatelogs 是 Apache 2.2 中自带的管道日志程序,参数如下(参见:http://lamp.linux.gov.cn/Apache/ApacheMenu/programs/rotatelogs.html

语法
rotatelogs [ -l ] logfile [ rotationtime [ offset ]] | [ filesizeM ]

选项
-l
使用本地时间代替GMT时间作为时间基准。注意:在一个改变GMT偏移量(比如夏令时)的环境中使用-l会导致不可预料的结果。
logfile
它加上基准名就是日志文件名。如果logfile中包含”%”,则它会被视为用于strftime()的格式字符串;否则它会被自动加上以秒为单位的”.nnnnnnnnnn”后缀。这两种格式都表示新的日志开始使用的时间。
rotationtime
日志文件滚动的以秒为单位的间隔时间。
offset
相对于UTC的时差的分钟数。如果省略,则假定为”0″并使用UTC时间。比如,要指定UTC时差为”-5小时”的地区的当地时间,则此参数应为”-300″。
filesizeM
指定以filesizeM文件大小滚动,而不是按照时间或时差滚动。

主配置文件中的使用方法

ErrorLog "|bin/rotatelogs -l logs/error_%Y%m%d.log 86400"
CustomLog "|bin/rotatelogs -l logs/access_%Y%m%d.log 86400" combined

虚拟主机配置文件中的使用方法

ServerAdmin webmaster@localhost
DocumentRoot "E:/htdocs"
ServerName localhost
ErrorLog "|bin/rotatelogs -l logs/localhost/error_%Y%m%d.log 86400"
CustomLog "|bin/rotatelogs -l logs/localhost/access_%Y%m%d.log 86400" combined

PS1:这两个管道日志文件程序还有一点不同之处是使用 cronolog 时如果日志是放在某个不存在的路径则会自动创建目录,而使用 rotatelogs 时不能自动创建,这一点要特别注意。
PS2:有关 Apache 日志文件的更多信息请参见:http://lamp.linux.gov.cn/Apache/ApacheMenu/logs.html

Apache 反向代理错误一则

在 Windows 上使用 Apache 搭建了一个 PHP 环境,由于要和一些原先在使用的网站使用同一域名,便搭建了一个反向代理,将相应路径反向代理到原来的网站所在的服务器,根目录则使用当前服务器,运行了一段时间,网站管理人员报告称反向代理的那些网站不能访问了,访问相应的地址时显示如下错误:

Service Temporarily Unavailable
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.

查看Apache的logs/error.log日志文件,有显示如下内容:

[Thu Jul 01 12:03:45 2010] [error] (OS 10061)由于目标机器积极拒绝,无法连接。 : proxy: HTTP: attempt to connect to 192.168.0.10:8080 (192.168.0.10) failed
[Thu Jul 01 12:03:45 2010] [error] ap_proxy_connect_backend disabling worker for (192.168.0.10)

一开始感觉就是连接被防火墙阻止了,但网站管理人员称防火墙已关闭,并且使用使用IE访问反向代理的那个地址能正常显示。后来到网上查阅了一些资料,有个国外的网站(Techie-Gyan)上说这个问题是由于Apache向外的链接不被允许导致的,于是又检查了系统防火墙以及系统日志等,发现是系统日志里面果然有好多条HTTP连接被阻止的记录,询问了网站管理人员后得知,原来服务器上有个防火墙软件,因为想让系统安全一点,防护级别被提到了最高,于是Apache的HTTP连接就被默认阻止了,更改了防火墙的配置以后,一切正常了。

打包修改过的文件的批处理

在没有进行版本管理的项目中,常常会因为忘记修改过哪些文件而把整个项目都覆盖一遍,既浪费网络带宽又浪费时间,每次覆盖都要在FTP上传好久,于是我就写了一个批处理脚本,将修改过的需要覆盖的文件打包成一个压缩包,代码如下:

@echo off
:: 网站更新文件打包程序

:: 设置临时目录:
set TEMP=temp

set /P FROM=源文件目录^(默认为www^):
if @%FROM%@==@@ set FROM=www

set /P TO=导出压缩包文件名^(默认为update-%date:~0,4%%date:~5,2%%date:~8,2%^):
if @%TO%@==@@ set TO=update-%date:~0,4%%date:~5,2%%date:~8,2%

set /P DAY=修改时间^(m-d-y,默认为今天{%date:~5,5%-%date:~0,4%}^):
if @%DAY%@==@@ set DAY=%date:~5,5%-%date:~0,4%

:: 将要打包的文件复制到临时文件夹,将排除文件列表(excludelist.txt)中的文件排除在外
xcopy %FROM% %temp% /S /Y /I /D:%DAY% /EXCLUDE:excludelist.txt

:: 使用7z命令行程序进行打包
7z a -t7z %TO%.7z .\%temp%\*

:: 删除临时文件
rmdir /S /Q %temp%

echo 文件已打包到 %TO%.7z
pause>nul

该批处理使用了7-zip的命令行压缩工具来打包,将7z.exe复制到当前目录即可
excludelist.txt 中包含了需要排除的文件列表,xcopy的帮助中是这样说明的:

指定含有字符串的文件列表。每一个字符串必须在文件的单独行中。如果有任何字符串与要被复制的文件的绝对路径相符,那个文件将不会得到复制。
例如,指定如 \obj\ 或 .obj 的字符串会排除目录 obj 下面的所有文件或带有 .obj 扩展名的文件。

Apache崩溃提示php5ts.dll出错的问题

现象:

Apache在Windows启动后自动启动服务时出错,跳出错误报告,提示php5ts.dll导致Apache崩溃,同时,所有基于MySQL的PHP程序无法运行,例如phpMyAdmin一登录就出错

原因:

PATH环境变量设置中将MySQL的安装路径也加入在里面,而且MySQL的路径在PHP的路径前面,导致PHP的MySQL模块使用了MySQL安装目录下的libMySQL.dll而不是PHP安装目录下的libmysql.dll,而根据PHP安装目录中install.txt在第966行左右的警告:

Warning

Don’t mix up your installation with DLL files from different PHP
versions. You have the only choice to use the DLL’s and extensions that
ship with your downloaded PHP version.

这个警告说只能使用你下载PHP时一起下载过来的版本的DLL,而上面的设置恰恰混合使用了MySQL里面的DLL和PHP自己的DLL,因而导致了这个问题的产生。

解决方法:

将 Path 环境变量中的 PHP 路径放到 MySQL 的前面,或者如果你不需要直接在命令行中使用 mysql 的话(仍然可以切换到MySQL目录下再访问mysql命令行程序,只是不那么方便)可以去掉 MySQL 在 Path 环境变量的路径