要看目前的系统配置,可以用phpinfo()看到。以下为选项配置
php_value name value
配置变量名称和值。本选项需 PHP 4.x 版之后才能使用。
php_flag name on|off
配置标志布尔变量选项。本选项需 PHP 4.x 版之后才能使用。
php_admin_value name value
配置 Apache 的配置文件变量。原来在 .htaccess 的配置改到这个选项配置。本选项需 PHP 4.x 版之后才能使用。
php_admin_flag name on|off
配置布尔变量当标志。本选项需 PHP 4.x 版之后才能使用。
asp_tags boolean
配置 PHP 程序是否解析以 ASP Script 语法 <% %> 的标记 (tag)。本选项在 PHP 3.0.4 之后才可使用。更多的细节可以参考>嵌入方法的部份。
auto_append_file string
配置本选项可以让指定的文件附加在原 PHP 程序后面自动执行。若 PHP 程序中有用到 exit() 函数,则指定的文件不会执行。参数 string 即为指定自动执行的文件。
auto_prepend_file string
配置本选项可以让指定的文件在原 PHP 程序之前自动执行。参数 string 即为指定自动执行的文件。
cgi_ext string
本选项配置 CGI 程序的扩展名。
display_errors boolean
本选项配置是否要将执行的错误信息显示在用户的浏览器上。
doc_root string
配置服务器的文件及 PHP 文件放置的根目录。
engine boolean
本选项需要使用apache的模块方式使用 PHP。可配置是否要使用 PHP 引擎。在 httpd.conf 中加入 php3_engine on/off 亦可配置某目录或某虚拟网站是否要用 PHP 解析器。
error_log string
本选项用来配置错误记录文件。在 UNIX 系统上参数 string 即为文件名。Windows NT 会将记录记在事件检视器的日志之中。Windows 95/98 则不支持系统记录。
error_reporting integer
本选项用来配置系统记录的等级。参数 integer 即为等级的级数标志,可以加在一起,默认值为 7,见下表
级数 说明
1 一般的错误
2 一般的警告
4 解析错误
8 非关键的警告
open_basedir string
本选项用来配置提供 PHP 存取的最底层目录。从该指定目录之下的文件或目录,PHP 程序才能存取。使用本选项主要是为了系统安全性的考虑。参数 string 即为要限制的最底层目录节点。值得注意的是在 UNIX 系统中,若该节点之下的文件或目录有符号链结 (symbolic link),则可能会让使用本选项的目的打折,因此在目录的设计上考虑,也是 Webmaster 的重要任务。默认值是所有文件均可存取。在 PHP 3.0.7 版之后,可以配置多个底层目录。
gpc_order string
配置 GET/POST/COOKIE 三种模块的顺序及规则。参数 string 即为要配置的规则,例如:配置成 "GP" 表示忽视 cookie,并在存取方法 (method) 相同时,以 POST 取代 GET。
ignore_user_abort string
默认值为 Off。用来配置当传输未完成时,用户端断线是要继续处理。
include_path string
为 PHP 程序中 require、include 及 fopen_with_path 等函数的文件搜寻路径。在 UNIX 或 Windows 中的斜线方向不同。
log_errors boolean
指定程序错误时是否要记录在 log 文件中。
magic_quotes_gpc boolean
配置 GET/POST/COOKIE 三种模块的特殊字符,包含单引号、双引号、反斜线、及空字符 (NUL) 是否要自动加入反斜线当溢出字符。
magic_quotes_runtime boolean
配置返回资料是否自动加入反斜线当溢出字符。
magic_quotes_sybase boolean
配置 sybase 资料中单引号要自动加上反斜线当溢出字符。
max_execution_time integer
配置程序最久执行时间。单位是秒。
memory_limit integer
配置程序最多使用多少内存。
short_open_tag boolean
配置是否使用短的 PHP 标记 (<? ?>)。若不使用,则必须要用 <?php 作为程序的开头,若要使程序合乎 XML 的标准则要关闭本功能。
track_errors boolean
打开本选项可使最后的错误信息跟着全局变量 $php_errormsg。
track_vars boolean
打开本选项可让用户输入的字符串自动解析到变量之中,而不用自己处理。
upload_tmp_dir string
指定上传文件临时路径。
user_dir string
指定用户根目录的路径。
warn_plus_overloading boolean
若打开本选项,字符串间就只能用英文的句号 (.) 链接,而不能用加号 (+) 链接字符串。
SMTP string
在 Windows 系列操作系统中,用来指定 SMTP 服务器,供 mail 函数使用。参数 string 为 SMTP 服务器名字。
sendmail_from string
配置 "From: " 字符串供 Windows 系列操作系统使用 mail 函数。
sendmail_path string
配置 sendmail 程序的放置路径。例如 /usr/sbin/sendmail。
safe_mode boolean
配置 PHP 在安全模式下执行。
safe_mode_exec_dir string
配置安全模式程序执行的路径。
debugger.host string
指定远端调试的服务器名称,可以是 IP 或 Domain Name。
debugger.port string
配置远端调试服务器的端口 (port)。
debugger.enabled boolean
配置是否可以为调试模式。
enable_dl boolean
本选项要使用apache模块 (Apache module) 的方式才有效。用来配置 PHP 的函数可否作用。当系统处于安全模式 (safe-mode) 时,本选项 enable 也无法使用 dl() 函数。
extension_dir string
配置动态函数的路径。
extension string
PHP 启动时所要载入的动态扩充功能。
mysql.allow_persistent boolean
配置是否允许 MySQL 数据库持续连接 (persistent connections),会影响函数。
mysql.max_persistent integer
配置每个处理程序最多保持几个 MySQL 持续连接。
mysql.max_links integer
配置每个处理程序最多开几个 MySQL 连接,包括持续连接。
msql.allow_persistent boolean
配置是否允许 mSQL 数据库持续连接 (persistent connections),会影响函数。
msql.max_persistent integer
配置每个处理程序最多保持几个 mSQL 持续连接。
msql.max_links integer
配置每个处理程序最多开几个 mSQL 连接,包括持续连接。
pgsql.allow_persistent boolean
配置是否允许 Postgres 数据库持续连接 (persistent connections),会影响函数。
pgsql.max_persistent integer
配置每个处理程序最多保持几个 Postgres 持续连接。
pgsql.max_links integer
配置每个处理程序最多开几个 Postgres 连接,包括持续连接。
sybase.allow_persistent boolean
配置是否允许 Sybase 数据库持续连接 (persistent connections),会影响函数。
sybase.max_persistent integer
配置每个处理程序最多保持几个 Sybase 持续连接。
sybase.max_links integer
配置每个处理程序最多开几个 Sybase 连接,包括持续连接。
sybct.allow_persistent boolean
配置是否允许 Sybase-CT 数据库持续连接 (persistent connections),默认值是打开的。
sybct.max_persistent integer
配置每个处理程序最多保持几个 Sybase-CT 持续连接。默认值为 -1 表示无限制。
sybct.max_links integer
配置每个处理程序最多开几个 Sybase-CT 连接,包括持续连接。默认值为 -1,表示没有限制。
sybct.min_server_severity integer
配置 Sybase-CT 服务器错误报告的最少笔数。默认值为 10。
sybct.min_client_severity integer
配置 Sybase-CT 客户端错误报告的最少笔数。默认值为 10。
sybct.login_timeout integer
配置 Sybase-CT 最久可以使用的登入时间。默认值为 1 分钟。
sybct.timeout integer
配置 Sybase-CT 的 query 操作时间限制。默认值为无限制。
sybct.hostname string
配置 Sybase-CT 可连接机器名称。默认值不设限
ifx.allow_persistent boolean
配置是否允许 Informix 数据库持续连接 (persistent connections),会影响函数。
ifx.max_persistent integer
配置每个处理程序最多保持几个 Informix 持续连接。
ifx.max_links integer
配置每个处理程序最多开几个 Informix 连接,包括持续连接。
ifx.default_host string
配置 Informix 默认连接的服务器名称,供ifx_connect()或ifx_pconnect()函数使用。
ifx.default_user string
配置 Informix 默认连接的用户帐号,供ifx_connect()或ifx_pconnect( 函数使用。
ifx.default_password string
配置 Informix 默认连接的用户密码,供ifx_connect()或ifx_pconnect() 函数使用。
ifx.blobinfile boolean
配置 Informix 长位类模式,0 表在内存;1 表在文件中。亦可以在 PHP 程序中使用ifx_blobinfile_mode()函数来修改。
ifx.textasvarchar boolean
配置 Informix 文字模式默认值,0 表返回 blob 的代码;1 表返回 varchar 字符串。亦可在 PHP 程序中使用ifx_textasvarchar() 函数来修改配置。
ifx.byteasvarchar boolean
配置 Informix 位组模式默认值,0 表返回 blob 的代码;1 表返回 varchar 字符串。亦可在 PHP 程序中使用ifx_byteasvarchar() 来修改配置。
ifx.charasvarchar boolean
配置 Informix 返回字符串的字尾空格是否要自动去除。
ifx.nullformat boolean
配置 NULL 字段的返回方式,true 表示返回字符串 NULL,false 表格返回字符串 ""。亦可在 PHP 程序中以ifx_nullformat() 修改。
bcmath.scale integer
配置 BC 高精确度函数库的小数点位数。
browscap string
配置浏览器的开文件能力名。
uodbc.default_db string
配置 ODBC 默认连接的数据库名称,供odbc_connect()或odbc_pconnect()函数使用。
uodbc.default_user string
配置 ODBC 默认连接的用户帐号,供odbc_connect()或odbc_pconnect()函数使用。
uodbc.default_pw string
配置 ODBC 默认连接的用户密码,供odbc_connect()或函数使用。
uodbc.allow_persistent boolean
配置是否允许 ODBC 数据库持续连接 (persistent connections),会影响odbc_pconnect()函数。
uodbc.max_persistent integer
配置每个处理程序最多保持几个 ODBC 持续连接。
uodbc.max_links integer
配置每个处理程序最多开几个 ODBC 连接,包括持续连接。
以下和 session 有关的配置值,都在 PHP 4.x 以上的版本方支持。在 php.ini 的配置文件中。
session.save_handler
定义 session 储存资料的文件名称。默认值为 files。
session.save_path
定义 session 储存资料的文件路径。默认值为 /tmp。
session.name
配置 session 所使用的 cookie 名称。默认值为 PHPSESSID。
session.auto_start
配置 session 是否自动打开。默认值为 0 (否)。
session.lifetime
配置 cookie 送到浏览器后的保存时间,单位为秒。默认值为 0,表示直到浏览器关闭。
session.serialize_handler
定义连续/解连续资料的标头,本功能只有 WDDX 模块或 PHP 内部使用。默认值为 php。
session.gc_probability
配置每笔要求回应时的废物蒐集 (gc, garbage collection) 处理机率。默认值为 1。
session.gc_maxlifetime
配置废物被清除前的存活秒数。
session.extern_referer_check
决定参照到客户端的 Session 代码是否要删除。有时在安全或其它考虑时,会配置不删除。默认值为 0。
session.entropy_file
配置 session 代码建立时,使用外部高熵值资源或文件来建立,例如 UNIX 系统上的 /dev/random 或 /dev/urandom。
session.entropy_length
配置 session 从高熵值资源读取的位组数。默认值为 0。
session.use_cookies
配置是否要将 session 变成 cookie 存在用户端。默认值为 1,表是打开本功能。
<Iframe src="/URL" width="x" height="x" scrolling="[OPTION]" frameborder="x"></iframe>
src:文件的路径,既可是HTML文件,也可以是文本、ASP等;
width、height:"画中画"区域的宽与高;
scrolling:当SRC的指定的HTML文件在指定的区域不显不完时,滚动选项,如果设置为NO,则不出现滚动条;如为Auto:则自动出现滚动条;如为Yes,则显示;
FrameBorder:区域边框的宽度,为了让"画中画"与邻近的内容相融合,常设置为0。
比如:
<Iframe src="http://www.xyz.com/xyz"; width="250" height="200" scrolling="no" frameborder="0"></iframe>
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
窗口与浮动帧之间的相互控制
在脚本语言与对象层次中,包含Iframe的窗口我们称之为父窗体,而浮动帧则称为子窗体,弄清这两者的关系很重要,因为要在父窗体中访问子窗体或相反都必须清楚对象层次,才能通过程序来访问并控制窗体。
1、在父窗体中访问并控制子窗体中的对象
在父窗体中,Iframe即子窗体是document对象的一个子对象,可以直接在脚本中访问子窗体中的对象。
现在就有一个问题,即,我们怎样来控制这个Iframe,这里需要讲一下Iframe对象。当我们给这个标记设置了ID 属性后,就可通过文档对象模型DOM对Iframe所含的HTML进行一系列控制。
比如在example.htm里嵌入test.htm文件,并控制test.htm里一些标记对象:
<Iframe src="test.htm" id="test" width="250" height="200" scrolling="no" frameborder="0"></iframe>
test.htm文件代码为:
<html>
<body>
<h1 id="myH1">hello,my boy</h1>
</body>
</html>
如我们要改变ID号为myH1的H1标记里的文字为hello,my dear,则可用:
document.myH1.innerText="hello,my dear"(其中,document可省)
在example.htm文件中,Iframe标记对象所指的子窗体与一般的DHTML对象模型一致,对对象访问控制方式一样,就不再赘述。
2、在子窗体中访问并控制父窗体中对象
在子窗体中我们可以通过其parent即父(双亲)对象来访问父窗口中的对象。
如example.htm:
<html>
<body onclick="alert(tt.myH1.innerHTML)">
<Iframe name="tt" src="frame1.htm" width="250" height="200" scrolling="no" frameborder="0"></iframe>
<h1 id="myH2">hello,my wife</h1>
</body>
</html>
如果要在frame1.htm中访问ID号为myH2中的标题文字并将之改为"hello,my friend",我们就可以这样写:
parent.myH2.innerText="hello,my friend"
这里parent对象就代表当前窗体(example.htm所在窗体),要在子窗体中访问父窗体中的对象,无一例外都通过parent对象来进行。
Iframe虽然内嵌在另一个HTML文件中,但它保持相对的独立,是一个"独立王国"哟,在单一HTML中的特性同样适用于浮动帧中。
试想一下,通过Iframe标记,我们可将那些不变的内容以Iframe来表示,这样,不必重复写相同的内容,这有点象程序设计中的过程或函数,减省了多少繁琐的手工劳动!另外,至关重要的是,它使页面的修改更为可行,因为,不必因为版式的调整而修改每个页面,你只需修改一个父窗体的版式即可了。
要注意的是,Nestscape6.0之前版本不支持Iframe标记。
例子:
1:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
<iframe src="页面" width="宽度" height="高度" align="排列可以是left或right,center" scrolling="是否有滚动条可以填no或yes"></iframe>
<IFRAME frameBorder=0 frameSpacing=0 height=25 marginHeight=0 marginWidth=0 scrolling=no name=main src="/bgm/bgm.html" width=300></IFRAME>
2:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
用了iframe后 发现滚动条不漂亮 想用2个图片来代替↑↓
应该怎么实现呢?
回答:
用下列代码替换网页的<title>..</title>
<SCRIPT LANGUAGE="javascript">
function scroll(n)
{temp=n;
Out1.scrollTop=Out1.scrollTop+temp;
if (temp==0) return;
setTimeout("scroll(temp)",80);
}
</SCRIPT>
<TABLE WIDTH="330">
<TR>
<TD WIDTH="304" VALIGN="TOP" ROWSPAN="2" >
<DIV ID=Out1 STYLE="width:100%; height:100;overflow: hidden ;border-style:dashed;border-width: 1px,1px,1px,1px;">
文字<BR> 文字<BR>
文字<BR>
文字<BR>
文字
<BR>
<BR>
</DIV>
</TD>
<TD WIDTH="14" VALIGN="TOP"><IMG SRC="photo/up0605.gif" WIDTH="14" HEIGHT="20" onmouseover="scroll(-1)" onmouseout="scroll(0)" onmousedown="scroll(-3)" BORDER="0" ALT="按下鼠标速度会更快!"></TD>
</TR>
<TR>
<TD WIDTH="14" VALIGN="BOTTOM"><IMG SRC="photo/down0605.gif" onmouseover="scroll(1)" onmouseout="scroll(0)" onmousedown="scroll(3)" BORDER="0" WIDTH="15" HEIGHT="21" ALT="按下鼠标速度会更快!"></TD>
</TR>
</TABLE>
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
下面这段代码可以实现IFrame自适应高度,即随着页面的长度,自动适应以免除页面和IFrame同时出现滚动条。
源代码如下
<script type="text/javascript">
//** iframe自动适应页面 **//
//输入你希望根据页面高度自动调整高度的iframe的名称的列表
//用逗号把每个iframe的ID分隔. 例如: ["myframe1", "myframe2"],可以只有一个窗体,则不用逗号。
//定义iframe的ID
var iframeids=["test"]
//如果用户的浏览器不支持iframe是否将iframe隐藏 yes 表示隐藏,no表示不隐藏
var iframehide="yes"
function dyniframesize()
{
var dyniframe=new Array()
for (i=0; i<iframeids.length; i++)
{
if (document.getElementById)
{
//自动调整iframe高度
dyniframe[dyniframe.length] = document.getElementById(iframeids);
if (dyniframe && !window.opera)
{
dyniframe.style.display="block"
if (dyniframe.contentDocument && dyniframe.contentDocument.body.offsetHeight) //如果用户的浏览器是NetScape
dyniframe.height = dyniframe.contentDocument.body.offsetHeight;
else if (dyniframe.Document && dyniframe.Document.body.scrollHeight) //如果用户的浏览器是IE
dyniframe.height = dyniframe.Document.body.scrollHeight;
}
}
//根据设定的参数来处理不支持iframe的浏览器的显示问题
if ((document.all &line;&line; document.getElementById) && iframehide=="no")
{
var tempobj=document.all? document.all[iframeids] : document.getElementById(iframeids)
tempobj.style.display="block"
}
}
}
if (window.addEventListener)
window.addEventListener("load", dyniframesize, false)
else if (window.attachEvent)
window.attachEvent("onload", dyniframesize)
else
window.onload=dyniframesize
</script>
1.页内帧IFRAME其实很简单,因为DREAMWEAVER没有这个插入功能所以不为人所知.
2.看名字就可以看出.IFRAME其实就是帧FRAME.只不过它可以以IFRAME的形式插入到页面的任何位置,它的属性跟FRAME一样,你可以到帧的面板上查看其属性.
3.插入时我都有用手工写入代码:代码如下:
<iframe src="/sample.html" name="myiframe" scrolling=auto width=250 height=200 frameborder=0 marginwidth=0 marginheight=0>Type error message for Netscape 4 and older browsers here.</iframe>
SRC是指明这个帧所需调用的页面名称,NAME值可有可无但如果你需要调用这个IFRAME的窗口就非写不可了.SCROLLING的属性规定是否需要滚动条,可以是NO.
4.如果不用IFRAME自已的滚动条,你可以用以下代码很简单地在其它地方控制它的左右或上下移动。(资料来源DARKVN)
左右移动:
<img src="/coolweb_images/scroll_left.gif" onMouseOver="ww=setInterval('myiframe.scrollBy(-2,0)',1)" onMouseOut="clearInterval(ww)" width="19" height="16" alt="左移">
<img src="/coolweb_images/scroll_right.gif" width="19" height="16" onMouseOver="ww=setInterval('myiframe.scrollBy(2,0)',1)" onMouseOut="clearInterval(ww)" alt="右移">
上下移动:
<img src="/coolweb_images/scroll_left.gif" onMouseOver="ww=setInterval('myiframe.scrollBy(0,2)',1)" onMouseOut="clearInterval(ww)" width="19" height="16" alt="下移">
<img src="/coolweb_images/scroll_right.gif" width="19" height="16" onMouseOver="ww=setInterval('myiframe.scrollBy(0,-2)',1)" onMouseOut="clearInterval(ww)" alt="上移">
上下移动到底:
onClick="myiframe.scroll(0,0)"和onClick="myiframe.scroll(0,30000)"
5.如果需要在这个帧里调用别的页面,用TARGET指向它。如: target="myiframe"
from: http://www.blog.edu.cn/user1/7089/archives/2005/183517.shtml
1、tween类
flash现在支持一些特殊的过渡(Tween/Easing)效果类,其用法如下:
someTweenID = new mx.transitions.Tween(object, property, function, begin, end, duration, useSeconds)
参数说明如下:
object :用来产生Tween效果的movieClip的引用名;
property :一个字符串值,应用Tween效果的MovieClip属性名,比如"_x","_y","_alpha"等
function :调用的easing类
begin :数字,属性的初始值
end:数字,属性的末值
duration :过渡持续的桢数或者秒数
useSeconds :布尔值,说明duration的单位是帧(false)还是秒(true)。如果没有指定,默认值为false(帧)
2、easing类
MXk24支持16种easing效果(准确的说,应该是19种)。
6种easing类别:
Strong
Back
Elastic
Regular
Bounce
None
每一种包括4种easing类型
easeIn
easeOut
easeInOut
easeNone
None和easeNone只能和其他的类别/类型搭配。easing函数用法如下:
mx.transitions.easing.Bounce.easeOut
3、showTime ,:)
现在,让我们将tween和easing结合起来实践一下。
假设stage上有一个名为ball_mc的movieClip,我们希望ball_mc水平运动,在半秒钟内从x坐标为20处运动到380处,并轻轻的弹跳两下。其写法如下:
ballTween = new mx.transitions.Tween(ball_mc, "_x", mx.transitions.easing.Bounce.easeOut, 20, 380, .5, true);
更加规范的写法如下:
function tweenBall() {
easeType = mx.transitions.easing.Bounce.easeOut;
var begin = 20;
var end = 380;
var time = .5;
var mc = ball_mc;
ballTween = new mx.transitions.Tween(mc, "_x", easeType, begin, end, time, true);
}
下面的函数增加了一个参数:easing类型
function tweenBall(easeType) {
var begin = 20;
var end = 380;
var time = 20;
var mc = ball_mc;
ballTween = new mx.transitions.Tween(mc, "_x", easeType, begin, end, time);
}
调用的示例:
tweenBall(mx.transitions.easing.Bounce.easeOut);
4、附加的技巧
Macromedia为tween类设置了一个事件:onMotionFinished,另外还有两个方法:yoyo() 和rewind()。
还是用例子来说明:
function tweenBall(easeType) {
var begin = 20;
var end = 380;
var time = 20;
var mc = ball_mc;
ballTween = new mx.transitions.Tween(mc, "_x", easeType, begin, end, time);
ballTween2 = new mx.transitions.Tween(mc, "_y", easeType, begin, end, time);
ballTween.onMotionFinished = function() {
this.yoyo();
};
ballTween2.onMotionFinished = function() {
this.yoyo();
};
}
PART 1
一个美国人,一个法国人还有一个中国人走在大沙漠中,
走着走着看到一个瓶子,打开瓶塞后飘出来一个人来,
那个人说:"我是神仙,我能满足你们每个人三个愿望!"
美国人第一个抢着说:"我第一个愿望是要很多的钱."
神仙说:"这个简单,满足你!说说第二个愿望吧."
美国人说:我还要很多的钱!"
神仙满足他的愿望后,美国人又说了他的第三个愿望:"把我弄回家."
神仙说:"没问题."
于是美国人带着很多的钱回了美国.
神仙又问法国人.
法国人说:"我要美女!"
神仙给了他美女.
法国人又说:我还要美女!"
神仙也满足了他,给了他美女..
法国人最后说到:"把我送回法国."
神仙把法国人送回国后问中国人要什么.
中国人说:"先来瓶二锅头吧."
神仙给了他.问他第二个愿望是什么.
中国人说:再来一瓶二锅头!"
神仙问他第三个愿望是什么.
中国人说:"我挺想法国人和美国人的,你把他们都弄回来吧
PART2
法国人和美国人气的不得了,但又无可奈何,三个人只好继续走 走着走着又看见一个瓶子,打开塞子后又冒出一个人来,
那个人说:"我是刚才那个神仙的徒弟,法力没他高强,
所以只能满足你们每个人两个愿望."
法国人和美国人合计合计认为先让中国人说为好,
免得一会又被他弄回来.
于是中国人说:"那就先来瓶二锅头吧."
神仙满足了他的愿望.
法国人和美国人催促中国人赶快把第二个愿望说出来.
中国人喝完二锅头后不紧不慢地对神仙说:"行了,没事了,你丫走吧."
part3
美国人和法国人气呼呼的跟着中国人继续跋涉,
走着走着又看到一个瓶子,打开瓶塞后又飘出一个人来,
那个人说:"我是那个神仙的徒弟的徒弟,我只能满足你们每个人一个愿望!"
美国人急忙抢着说:"我再也不想见到那个中国人了."
> 神仙说:"好的.",然后转头问法国人:"你的呢?"
法国人急忙说:"我也不想见到那个中国人了."
神仙说:"好的.",然后转头问中国人:"你的呢?"
中国人说:"他们说的都不算"
part4
于是乎美国人和法国人咬牙切齿的跟着中国人,
走着走着又看到一个瓶子,打开瓶塞后又飘出一个人来,
那个人说:"我是那个神仙的徒弟的徒弟的徒弟,我只能满足你们三人一个愿望
美国人和法国人异口同声的喊道:"那个中国人说的什么都不算"。
那个人说:"好的",于是乎转头问中国人:"你想说什么?"
那个中国人说:"让他们都回各自的国家吧,别跟着我受罪"。
原文:http://www.gotoandplay.it/_articles/2004/04/swfProtection.php
这篇文章的标题所提出的问题的答案是"不可能"。至少对我来说是不可能的。借助适当的工具,我们可以反编译任何SWF文件。所以,不要将重要的信息置于SWF文件中。SWF文件中不要包含个人的帐号或者密码。
我将简要的论述"保护"技术的历史,和他们是如何失败的,接着我将说明我们能尽的最大努力。中国古语有云,"规则只能防君子,不能仿小人"。
公开的文件格式
在讨论之前,我们先要知道,SWF的文件格式是公开的。公开的文件格式,意味着SWF文件并不是只能由Flash生成。其他公司也能制作可以在SWF播放器上播放的SWF文件。公开的文件格式意味着从什么位置获取什么信息是众所周知的,也就意味着每个字节都是众所周知的。因此,如果我有时间来一个字节一个字节的检查SWF文件,我可以了解所有的细节。
当然,对于一个2M大小的SWF文件,我没有时间来逐个字节的检查。因此,我就借助软件来完成这个工作。如果软件遇到问题,我会暂时接管这个工作,检查发生问题的字节。修正它,然后继续。所以,没有什么东西能够掩藏的住,其限制只是我的时间和我的耐性。如果反编译一个SWF文件的酬劳是数百美元的话,我想我会花上数年时间来逐个字节的读取它。
好了,以下是反编译和保护技术之间的战争历史。
防止被导入
伴随着Flash的出现,Macromedia提供给开发者一个"防止导入的口令保护"功能。如果你给SWF文件加上导入口令的话,这个SWF文件就不能被导入了(知道倒入密码除外)。SWF文件不加保护的话,其中的矢量图形可以被导入到fla文件中。这种保护没有什么用处,仅仅是假想的安全。
试想一下,你的SWF被用户的播放器来播放的,你不可能利用用户的播放器来保护你的SWF文件。因此,它是如何来保护SWF文件的呢?很简单,这种保护存在于你所买的Flash开发工具中。Flash开发工具不能导入有(导入)密码的SWF文件。没关系,对吧?我可以用十六进制编辑打开那个SWF文件,删除保护密码,从而也就移除了保护功能。
如此简单,所以忘记导入保护功能吧。
转换成放映机文件并且压缩
如果我将它转化成exe格式的放映机文件,还可以被反编译吗?答案:是的,SWF文件仍然存在其中。借助软件可以很容易的将SWF文件从exe文件中释放出来。压缩可以使SWF文件不能被十六进制编辑器读取,压缩是一种保护措施吗?压缩算法类似于zip算法,很容易被破解。
FLASM AND THE P-CODE
在flash5的时代,出现了两种流行的工具,免费的"Flasm"和商业的"ASV 2.0"。Flasm就是"Flash asm",它将SWF中的字节码解释成可理解的简短代码(p-codes)。比如"a=3"显示为"push 'a', 3", "setVariable";SWF中的字节码是:"96 08 00 00 61 00 07 03 00 00 00 1D"。如果想学习"SWF格式结构"的话,这是个非常有价值的工具。
程序员喜欢用高级语言(比如:C、C++)来开发软件,但是当讲求效率的时候,他们会在其中混合使用低级的汇编语言。因此,有时候开发者会利用Flasm编写低级别的p-codes来增加效率。所以,Flasm编辑SWF中的actionscript是强有力的。你可以参考例子,了解如何利用这种技术来优化3D代码,但是怀有恶意的用户能够"编辑"SWF文件,SWF中的任何保护措施都可以不费力的移除。我们不需要知道密码就可以移除保护措施。
这儿有个通用、知名的技术来保护我们的影片不被偷窃并在其它的范围内显示。我们编辑脚本来检查_url属性,如果_url不是我们(合法)的范围,就使功能失效并显示一条"You are thief"的消息。可是,借助Flasm可以很容易删除这条脚本语句。不需要1分钟便可以破解这种保护措施。
ACTIONSCRIPT VIEWER AND "void (a)<=b>"c" || 0(!1 && !0)"
ASV(ActionScript Viewer)能够从SWF中提取出角色,例如::声音、形状和位图等都可以被窃取。
它同样可以提取actionscript字节码,ASV 2尝试将p-codes匹配成高级别的actionscript。当遇到"push 'a', 3", "setVariable";时显示"a=3"这样的等同于actionscript的语言。然而我们能够创造没有任何模式来匹配的代码,从而破坏ASV的解析。利用Flasm,可以容易的编写不同于标准模式的代码,从而使ASV不能进行匹配工作。扰乱ASV 2工作的一句有名的代码是";",这是一条jung代码。它不做任何事,但是能搞乱ASV 2的工作。
但是,当保护脚本众所周知时,ASV的作者(Burakk)当然不会放过它。这种保护技术对于ASV 3来说就失效了。
飞速发展的反编译工具
之后是MX时代的到来,许多反编译工具的出现,加快了Flash厄运的速度。
现行版本的ASV 4除了显示得到匹配的actionscript代码,得不到匹配的代码以p-codes形式显示。如果解释成p-codes发生问题,将显示SWF中的字节码。它同样能够显示代码在SWF文件中所处的偏移量,这意味着它不会失效。你不可能扰乱它的工作,因为,至少它能显示SWF文件中的"字节码"。
更甚的是,Flash MX2004提供通过JavaScript API来生成"fla"文件。那使它能够建立发布成SWF格式的fla文件。此刻,所有的东西都在那边了。
更不用说声音、形状和位图了,偷窃者不喜欢这些东西,因为它们套容易取得了。偷窃者喜欢切的actionscript,因为其中隐藏着密码,因为其中有阻止此影片正常播放的脚本代码,
如果ASV只能将脚本反编译成字节码,那么它对于大多数偷窃者是没有用处的。因此很多人进他们的最大努力来阻止ASV 4将脚本反编译成actionscript或者p-codes。实际上,对于大多数反编译者来说,脚本得不到匹配,反编译工具就无用了。
这是曾经用过的一些技术,当它们在因特网上发布并且被反编译组织揭示之后,每种技术的保护效果最终都会变得非常薄弱和气数将尽。
依据数据尺寸(句子)分块反编译
大多数之所以能够成功的迷惑或者破坏反编译器,原因在于播放器和反编译器的不同行为。播放器逐个的执行字节码,就像现实世界中的读书一样,一个单词,接着下一个单词。然而反编译器通常将字节链分成有意义的片断,犹如现实世界中的读书一样,一个句子,接着下一个句子。
反编译器的行为如此简单的原因在于大多数的p-code都是遵循数据大小规律的。对于字节码("96 08 00 00 61 00 07 03 00 00 00 1D"),反编译器遇到代表"push"操作的0x96时会想"push什么呢"?下个字节(0x0008)指示的内容:接下去8个字节中的内容压入堆栈,即把("00 61 00 07 03 00 00 00")压入堆栈。所以,通常反编译器依据数据大小将简短的片断切成一块一块的,这样便会解释成"push something"。因此,("96 08 00 00 61 00 07 03 00 00 00")就成为一个句子。下一个字节是下一个句子的开始,就是代表"setVariable"的0x1D。这样8个字节的"something",将被更进一步解释成一个字符串"a"和一个数字"3"。
让我们来看一下字节码:("99 02 00 05 00 96")。0x99意味着分支(或者跳转),在哪里分支呢?接下去的是(0002),因此数据存储在机下去的两个字节中,将它在下面两个字节处截断。总之,我们知道"99 02 00 05 00"是个句子。接下去的是0x96,代表下个句子的开始。
再看第三个例子,字节码:("88 08 00 03 00 63 00 62 00 61 00 96 07 00")。0x88代表定义常数,定义的常数内容是什么呢?后续字节(0008),表明常数内容存储在后继的8个字节中。所以,句子就是:("88 08 00 03 00 63 00 62 00 61 00")。代表下个句子开始的("96 07 00 ...),意味着将7个字节的数据压入堆栈。
因此,字节码砍成单独的句子。每个句子由命令和数据组成,并且以命令打头。因此,每个句子都是一个基本的单元。理论上来说,对于这种方法没有什么错误。
使播放器从句子中间开始读数据
让我们开始讨论"是播放器从句子中间读数据"的破坏反编译器的技术。
首先,我举一个现实世界的例子:
John says good morning.
Mary says thank you.
现在生成SWF文件:
skip 9 words
Tom says John says good morning. skip 3 words
back 7 words
Mary says thank you.
如果逐个字读的话,结果和原来一样,然而反编译器按句子来读取,自然发生错误。第一,它知道Tom说了什么,但语法不对,汇报出错;第二,它没有看到第二个"skip"命令,因为它处于句子中间;第三,当它被迫退回7个字后,感到迷惑,认为应该从"Tom said"开始执行整个句子;第四,这个错误使它在第二行和第三行之间陷入无限循环之中。
总之,我们增加了"Tom said"这句垃圾代码,并提供整个句子长度的错误数据大小信息。这个错误的长度覆盖了"skip"命令。
来看个真实的例子,请注意,这些技术需要操作字节码,纯actionscript不能够实现。
例1 :
向前跳转的包含无效尺寸数据的死代码。
push True
branchifTrue label2
constants ''
label2:
push 'a',3
setVariable
你仔细看的话,会发现"constants ''"这行是垃圾代码,它不可能被执行到。然而,理论上,当第二行的结果为"not True"时,它将被执行。因此,反编译器尝试对它进行反编译。
让我们来增大"0x88 - constants"后面的"sentence size",从而包括知道脚本结尾的所有字节。你知道,反编译器将把字节码砍成像这样的3个句子:
push True
branchifTrue label2
constants label2: push 'a',3 setVariable
如果你试图反编译此SWF文件,根据我前面提到的4个错误,一些反编译器将碰壁。仍旧有些反编译器幸存,但只是显示:"if(false){};"。ASV 3也不能显示此脚本,但是ASV 4能够显示。为了破解这个SWF,我们移除死代码"constant xxxx", (0x88和随后两个字节),然后所有的东西都得到反编译。
这儿是zip格式的文件,将详细解释怎样制作这样的受保护文件。
例2:
先后跳转的包含无效尺寸数据的死代码。
push 'b'
label1:
push 'a',3
setVariable
branch label2
branch label1
label2:
push 'b'是句垃圾代码,我们将修改它,用来使ASV 4碰壁。让我们来修改push 'b'的"length of sentence"。修改"0x96"后面的2个字节的数据,使句子的长度增长到分支Label1之前。这样,反编译器将把字节码作为3个句子:
push label1: push 'a',3 setVariable branch label2
branch label1
label2:
现在,反编译器不知道将把什么压入堆栈,同样它将在第一个句子和第二个句子之间形成死循环。这种技术将使大部分反编译器碰壁。Flasm、ASV 4同样也无效。为了破解这个SWF,我们手工删除"push b" (0x96和后随的2个字节),这样所有的东西都可反编译了。
当这个技术流传后,burakk将修改ASV 4,使它能正确处理死循环。这样下个版本的ASV就可对付这种技术了。
这儿是zip格式的文件,将详细解释怎样制作这样的受保护文件。
水平有限,敬请批评指正。 E-mail:xmanceo@yahoo.com.cn

33岁的诗人,4.26亿美元的身价,追求纯美爱情的单身CEO,当这些所有可能引发尖叫的因素,聚集在一个叫江南春的男人身上,他的故事在坊间被无数市井渲染,也就不足为奇。
在这个无聊都能变现金的年月里,在这个注意力被称之为经济的时代里,一夜暴富不是问题,问题的关键是暴富之后,如何持续增值。
声称喜欢被关注的江南春,似乎有足够的理由让人们持续地关注他。当他一夜之间成为2.7亿美元的富豪后,在不到半年的时间里,他率领着分众不断制造有轰动效应的财富新闻,从1亿美元并购框架媒介,到3.25亿美元鲸吞聚众传媒,并最终一举成为中国最大的户外电视广告网络运营商。这个上世纪70年代生人的公司领导者颇为崇尚的生意经是:"做有创意的生意"。
文人背景出身的江南春,能将剑拔弩张3年的最大竞争对手聚众收编,的确超出不少市场人士的想象力。全球最大的市场调查公司AC尼尔森的调查显示,新分众在楼宇电视广告市场占有率达到96.5%-98%,拥有绝对的市场话语权。
不过,现在评价江南春的一统江湖为时尚早。从战略上讲,没有敌人就是危机的开始,在一个独大的市场里,怎样保持该行业的市场竞争性?如何保证受众的利益不受损害?新分众创新的动力在哪里?这都是江南春下一步不得不面对的问题。
有人说,看待敌人的方法,是21世纪公司领导者必修的功课,因为它可能关系到一家公司的成败。一个公司的竞争本质,取决于对手有多强,而非本身拥有多大的资产与能力。中国乃至世界公司发展史上有多少公司在天下无敌的氛围中,从自信满满到危机满满,几乎没有任何公司能保持永远的高峰与成功。具有独占竞争优势的新分众会是个例外吗?
江南春的商业思维:"在创意面前生意是不平等的,有创意的生意和没创意的生意,最后投资回报率差得非常远。而且我后来越来越发现,想象力创造你的利润率。"
江南春的爱情观:爱情是纯情的,很文化的,应该很纯情地追求这种东西。
2006年元旦过后的第一个周末,头顶着美国纳斯达克股市"中国传媒第一股"帽子的分众传媒公布了一则收购消息,称已经与中国第二大户外视频网络广告运营商聚众传媒股份有限公司及其股东签订了一项股票收购协议。
根据该收购协议,分众传媒将收购聚众传媒100%的资产。分众传媒将支付9400万美元的现金,并支付价值2.31亿美元的7700万股分众传媒原始股票。
"这次收购巩固了分众的行业领导地位"。分众传媒创始人、CEO江南春在1月9日接受《英才》采访时说。
江南春说,此次收购"对分众、聚众都是一件好事",而且绝大多数的机构投资者对此都持正面的评论。很显然,江南春平稳地坐上了行业老大的位置。
"幸运不可能总是属于分众。"江南春这句曾用来告诫自己和分众高管的话,在这里似乎显得有点不合时宜。就在此次收购消息公布的前180天,2005年7月13日,分众传媒登陆纳斯达克,一夜之间,江南春身价涨至2.7亿美元,成为各大富豪榜中一匹名副其实的"黑马"。
而就在分众宣布收购聚众的前70天,2005年10月17日,分众传媒以超过1亿美元的价格,收购了国内最大的电梯平面媒体框架媒介100%的股权。其收购标的金额创下了近年来我国媒体并购的最高纪录。
所有这些让人震惊的商业故事都跟这家叫分众传媒的公司有关,同时也跟这位名叫江南春的上海人有关。更值得一提的是,分众传媒今年才走过了3年历程,而她的缔造者江南春今年33岁。
江南春说自己并不像外界所描述的那样,喜欢以"诗人江南春"来给自己渲染。这可能是一个误会,就像江南春的出身和他的名字一样。
《江南春》本是诗人杜牧的一首七言绝句,"南朝四百八十寺,多少楼台烟雨中"的诗句千古流传。于是江南春在商界脱颖而出之后,外界开始猜测江南春出身书香门第,幼年就开始饱受熏陶。
江南春告诉我们,自己的父亲其实是一位严谨的审计师,母亲是一个小创业者,承包有自己的门店,完全不是传说中的书香门第。而对于自己江南春的大名,他说纯属巧合。"我姓江,我们家是朝南的,我是春天生的,所以我叫江南春,南说的是空间,春说的是时间,江南春只是一个时空观念的名字。"
但这样的误会并不影响我们把交谈的话题过多地停留在文学上,毕竟,江南春曾有过一段"文学青年"的经历。
江南春说自己对于文学,在内容上很崇拜捷克小说家米兰·昆德拉,而在形式上则比较崇拜阿根廷的波尔赫斯,因为江南春喜欢米兰·昆德拉所强调的词语,比如恐惧、抒情、死亡。而对于波尔赫斯,江南春喜欢他小说中的多种可能性,"一件事情存在多种可能性"。
记得昆德拉曾说,"我曾在艺术领域里四处摸索,试图找到我的方向。"江南春也曾经试图在艺术领域找到自己的方向,只不过昆德拉成功了,而江南春失败了。《抒情时代》展现了江南春的诗歌才华,同时也终结了他的诗歌理想。这正是波尔赫斯所强调的"多种可能性",而江南春把这一多种可能性发挥到了极至。
财富、年轻、单身,这些所有可能引发尖叫的因素,江南春都有,不过他也有让别人失望的因素,因为他声称自己是一个只专注做一件事的人,而目前只专注于他一手缔造的分众,没有认真地想过爱情或组建家庭。
江南春说自己自从出了大学之后就没有谈过恋爱,觉得自己的恋爱早已经在大学谈完了。"在人生不同阶段就要着重做什么事情,我在大学里着重谈恋爱,出了学校门就是创业,将来着重做的事情是什么我不知道,在一个时间段我只做一件事情,全身心只做一件事情"。
这也许是江南春对爱情挑剔的借口,声称自己在生活上有点极端的江南春认为爱情是纯情的,很文化的,应该很纯情地追求这种东西,而生活在商业中的他没有放弃自己对爱情的判断,诗歌没有了,爱情也远去了。
(以下是江南春的口述实录,本刊记者吴仕逵采访整理)
许多中国的富豪成功都是九死一生,我没有这样的感觉。每天都很累,每天都危机四伏,没有特别大的挫折。我想,每天都遇到小危机,每天都小心翼翼,大的危机就不会来找你。老说百折不回,我好像没有怎么被折过几次。
我的生活状态是飞人,起步时是骑自行车,也是空中,低空。现在大城市穿梭,10年其实都是一样的,节奏和方法没有变。我的衣柜里面找不到休闲的衣服,全部都是衬衣,因为10多年来生活好像只有工作。
我不喜欢音乐,也没有时间去听。能喝一点儿酒,但不爱参加应酬场面。约了别人都是去做脚底按摩,经常是一堆上市公司CEO在泡着脚谈事。热气腾腾,像开互联网大会一样。上海的CEO们都很忙,不喜欢吃饭,都喜欢脚底按摩。我来北京也去按摩。"我可能不是中国最努力的人,但一定是中国最努力的100个人之一。我所认识的创业者,陈天桥、马云、李彦宏……真的还没有轻轻松松成功的,没有谁过得很自在,大家觉得都很倦,尽管有时候谈起创意会很兴奋。成长的压力都很大。"
过年的时候,我经常在楼下的厨房烧菜,父母亲戚在上面吃。每次烧一个菜,我就舀一勺在旁边的小碗里,然后一边吃,一边烧第二个菜。我可以一个人在煤球炉前,听着无线电,两个下午就摊出无数的蛋饺。
我觉得工作能改变人的性格。以前读大学写诗歌的时候,我会写"献给新中国女大学生某某的一组情诗",贴到人家寝室门口……还是很有激情的。后来工作了,做了广告,知道做事情要有分寸,就不玩了。
(记者 唐凯林/本文图片来自网络)





