技术 / 设计
vc备忘:COM指针
一、标准模式
调用某个函数或方法,返回接口指针,在某个时间范围内使用这个接口指针,然后释放它。下面是使用这种模式的代码例子:
void f(void) {
IUnknown *pUnk = 0;
// 调用
HRESULT hr = GetSomeObject(&pUnk);
if (SUCCEEDED(hr)) {
// 使用
UseSomeObject(pUnk);
// 释放
pUnk->Release();
}
}
二、CComPtr
CComPtr类实现客户端基本的COM引用计数模型。CComPtr有一个数据成员,它是一个未经过任何加工的COM接口指针。其类型被作为模板参数传递:
CComPtr
CComPtr
缺省的构造函数将这个原始指针数据成员初始化为NULL。
CComPtr智能指针在析构时自动Release。
三、CComQIPtr
CComQIPtr与CComPtr关系很密切(实际上,它只增加了两个成员函数)。CComQIPtr必须要两个模板参数:一个是被操纵的指针类型 ,另一个是对应于这个指针类型的GUID。例如,下列代码声明了操纵IDataObject 和IPersist接口的智能指针:
CComQIPtr
CComQIPtr
CComQIPtr的优点是它有重载的构造函数和赋值操作符。同类版本(例如,接受相同类型的接口)仅仅AddRef右边的赋值/初始化操作。这实际上就是CComPtr的功能。异类版本(接受类型不一致的接口)正确调用QueryInterface来决定是否这个对象确实支持所请求的接口:
void f(IPersist *pPersist) {
CComQIPtr
// 同类赋值 - AddRef''s
p = pPersist;
CComQIPtr
// 异类赋值 - QueryInterface''s
do = pPersist;
}
再比如:
CComQIPtr
CComPtr
m_pWebBrowser2->get_Document(&psDisp);
psDocment = psDisp; // 这里自动调用QueryInterface
vc备忘:COM字符串
一、BSTR
在 C++ 中,一个 BSTR 实际上就是一个指向字符串中第一个字符的指针。
BSTR bstr = NULL;
bstr = SysAllocString ( L"Hi Bob!" );
if ( NULL == bstr )
// out of memory error
// Use bstr here...
SysFreeString ( bstr );
注意,BSTR在使用完毕后必须使用SysFreeString释放,否则会导致内存泄露。
二、CComBSTR
CComBSTR是封装了BSTR的智能指针。在CComBSTR型变量析构时,将自动释放内存。
CComBSTR bs1;
CComBSTR bs2 = "new text";
pStuff->GetText ( &bs1 ); // ok, takes address of internal BSTR
pStuff->SetText ( bs2 ); // ok, calls BSTR converter
三、COM规则,调用者负责释放传出[out]参数的内容。
BSTR bsName = NULL;
pLastNode->get_text(&bsName);//pLastNode为指向结点的指针
//使用bsName的代码(略)
....
//释放bsName字符串占用的内存
SysFreeString(bsName);
get_text的参数是out参数,内部会为该字符串分配内存,需要调用者释放。
vim正则表达式的非贪婪模式
我的目标是,将下列代码的中*.gif 都替换成 images/*.gif :



一开始使用:
:%s/src="\(.*\)\.gif"/src="\1.gif"/g
发现第一行内匹配的是:
src="abc.gif" />
这是vim正则的贪婪模式的问题。
vim也可以使用非贪婪模式来匹配,具体的使用方法是将上面的 "*" 改成 "\{-}" ,即
:%s/src="\(.\{-}\)\.gif"/src="\1.gif"/g
Wordpress插件开发FAQ
- 如何添加插件的option页面:
function your_function_name_here() {
if (function_exists('add_options_page')) {
add_options_page('subpaneltitle', 'submenuitemname',
minuserlevel, basename(__FILE__), 'my_options_subpanel');
}
}
add_action('admin_menu', 'your_function_name_here');
- 添加子菜单:
function mycategoryorder_menu()
{
if (function_exists('add_submenu_page')) {
add_submenu_page("edit.php", 'My Category Order', 'My Category Order',
2,"mycategoryorder",'mycategoryorder');
}
}
add_action('admin_menu', 'mycategoryorder_menu');
或(添加顶层菜单)
function fm_post_add_options() {
add_menu_page('FileManager', 'FileManager', 8, '../wp-admin/fm.php');
}
add_action('admin_menu', 'fm_post_add_options');
- 选项处理函数:
往数据库中添加选项:
add_option($name, $value, $description, $autoload);
获取选项值:
get_option($option);
更新选项值:
update_option($option_name, $newvalue);
- option处理的一般步骤是什么样的:
add_option('ddle_header', '
Latest Post From Each Category
');
...
function ddle_add_option_pages() {
if (function_exists('add_options_page')) {
add_options_page('Latest From Each Category', 'DDLatestFromEach', 8,
__FILE__, 'ddle_options_page');
}
}
function ddle_options_page() {
if (isset($_POST['info_update'])) {
?>update_option('ddle_header', (string) $_POST["ddle_header"]);
echo "Configuration Updated!";
?>} ?>
... - 如何实现<!--xxx-->这样的内置标签功能:
function ddle_generate($content) {
$content = str_replace("", dd_last_from_each(), $content);
return $content;
}
add_filter('the_content', 'ddle_generate');
- 如何往页面内加入JavaScript或者CSS?
add_action('admin_head', array(&$wp_cats, 'header_inserts'));class wp_cats {
function header_inserts() {
global $parent_file;if ('edit.php' == $parent_file) {
echo '' . "\n";
echo '' . "\n";
echo ' ';
}
}
}
PHP安全编程
1. 过滤输入数据
最重要的原则之一就是:“永远不要相信用户输入的任何数据。”过滤输入数据是防止SQL注入的有效方法。
function add_magic_quotes($array)
{
foreach ($array as $k => $v) {
if ( is_array($v) ) {
$array[$k] = add_magic_quotes($v);
} else {
$array[$k] = addslashes($v);
}
}
return $array;
}
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);
return $value;
}
function strip_slashes()
{
// If already slashed, strip.
if ( get_magic_quotes_gpc() ) {
$_GET = stripslashes_deep($_GET );
$_POST = stripslashes_deep($_POST );
$_COOKIE = stripslashes_deep($_COOKIE);
$_SERVER = stripslashes_deep($_SERVER);
}
$_GET = add_magic_quotes($_GET );
$_POST = add_magic_quotes($_POST );
$_COOKIE = add_magic_quotes($_COOKIE);
$_SERVER = add_magic_quotes($_SERVER);
}
2. 过滤输出数据
对任何要在HTML页面上显示的数据,必须经过过滤,否则就是引入了“跨站脚本攻击(XSS)”的危险。
$html = array();
$html['username'] = htmlentities($clean['username'], ENT_QUOTES, 'UTF-8');
echo "Welcome, {$html['username']}.";
记得使用htmlentities 防止XSS。
3. 使用SESSION跟踪
对于需要授权才能访问的页面,记得使用SESSION验证用户权限。
$user = $_SESSION['user'];
if ($_SESSION['verified']) ...
4. 防止文件上传攻击
使用is_uploaded_file() 和 move_uploaded_file() 防止文件上传攻击
还可以使用filesize() 来校验文件的大小
5. 使用Token和时间戳
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
?>
CSS设计常见问题收集(三)
- 长文字自动换行:
IE的代码:div {Firefox下的代码(使用js):
width:300px;
word-wrap:break-word;
border:1px solid red;
}function toBreakWord(intLen){
var obj=document.getElementById("ff");
var strContent=obj.innerHTML;
var strTemp="";
while(strContent.length>intLen){
strTemp+=strContent.substr(0,intLen)+" ";
strContent=strContent.substr(intLen,strContent.length);
}
strTemp+=" "+strContent;
obj.innerHTML=strTemp;
}
if(document.getElementById && !document.all) toBreakWord(37) - 一行内文本超出指定宽度溢出的处理:
一般的文字截断(适用于inline与block元素):.text-overflow {对于表格文字溢出的定义:
display:block;/*内联对象需加*/
width:31em;
word-break:keep-all;/* 不换行 */
white-space:nowrap;/* 不换行 */
overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */
text-overflow:ellipsis;/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
}table{这个写法只有IE会有“...”,其它的浏览器文本超出指定宽度时会隐藏。
width:30em;
table-layout:fixed;/* 只有定义了表格的布局算法为fixed,下面td的定义才能起作用。 */
}
td{
width:100%;
word-break:keep-all;/* 不换行 */
white-space:nowrap;/* 不换行 */
overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */
text-overflow:ellipsis;/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/
} - list-style-image无法准确定位的问题
li { list-style:url("arrowb.gif"); }另外一种方法是使用li的背景图像来模拟。
li a { position:relative; top:-5px; font:12px/25px 宋体; } - 对齐文本与文本输入框
现象:

设置文本框的vertical-align:middle 就可以了。
-
参考文章:
- web标准常见问题集合
CSS设计常见问题收集(二)
-
如何水平居中?
html, body { margin: 0; text-align: center; }
#container { position: relative; margin: 0 auto; width: 760px; text-align: left; } -
如何垂直居中文本?
div { height:30px; line-height:30px; border:1px solid red }只要给容器设置一个与其高度相同的行高就可以了。 -
怎样使一个层垂直居中于浏览器中?
div {这里我们使用百分比绝对定位,与外补丁负值的方法,负值的大小为其自身宽度高度除以二。
position:absolute;
top:50%;
left:50%;
margin:-100px 0 0 -100px;
width:200px;
height:200px;
border:1px solid red;
} -
图片垂直于容器内
* {margin:0;padding:0}
div {
width:500px;
height:500px;
border:1px solid #ccc;
overflow:hidden;
position:relative;
display:table-cell;
text-align:center;
vertical-align:middle
}
div p {
position:static;
+position:absolute;
top:50%
}
img {
position:static;
+position:relative;
top:-50%;left:-50%;
width:276px;
height:110px
}<div><p><img src="http://www.google.com/intl/en/images/logo.gif" /></p></div>
-
保持容器的最小高度:
div.box1,div.box2{
width: 300px;
min-height: 150px;
float: left;
}
* html div.box1,* html div.box2{height: 150px;} -
未知高度的非表格垂直对齐:
#div1, #div2 {display:table-cell; *display: inline; zoom:1; vertical-align:middle;}
效果:
CSS设计常见问题收集(一)
- firefox下,内容float时,父容器不能被撑开(闭合容器或清除浮动问题):
<div><p>web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全web标准常见问题大全</p></div>CSS代码如下:div {现象:
width:200px;
border:1px solid red
}
p {
float:left;
width:100px;
}

可以看到,父容器没有随着子容器而扩张。
解决方法:(1)加入<div style="clear:both"></div>清除浮动。
(2)为父容器也添加float:left;属性。
(3).gainlayout{display:inline-block;} .gainlayout{display:block;} - IE6的双倍边距BUG:
在IE中,对一个div浮动时,并设定该div的margin时,会出现双倍的margin值。
CSS代码:float:left;现象:
margin-left:100px;

解决方法:加上display:inline即可。 - IE6下图片下方有空隙:
现象:

解决方法:解决这个BUG的方法也有很多,可以是改变html的排版,或者设置img 为display:block。
或者设置vertical-align属性为vertical-align:top | bottom |middle |text-bottom
都可以解决。 - IE6下这两个层中间有间隙:
代码:<div class="left">aaaaaa</div>CSS代码:
<div class="right">aaaaaa</div>.left {现象:
float:left;
width:100px;
height:100px;
background:red
}
.right {
width:100px;
height:100px;
background:orange
}

解决方法:这个IE的3PX BUG也是经常出现的,解决的办法是给.right也同样浮动 float:left 或者相对IE6定义“.left margin-right:-3px;”。 - FF下文本无法撑开容器的高度:
CSS代码:div {现象:
width:200px;
height:100px;
border:1px solid red
}

可以看到,当文字的内容高度超过容器规定的高度时,容器不能自动撑开。
解决方法:标准浏览器中固定高度值的容器是不会象IE6里那样被撑开的,那我又想固定高度,又想能被撑开需要怎样设置呢?办法就是去掉height设置min-height:200px; 这里为了照顾不认识min-height的IE6 可以这样定义:
{
height:auto !important;
height:100px;
min-height:100px;
} - IE6下容器的宽度BUG:
现象:

解决方法:
(1)div
{
border: 20px;
padding: 20px;
width: 200px;
}
* html div
{
width: 280px;
w\idth: 200px;
}
(2)div
{
border: 20px;
padding: 20px;
width: 200px !important;
width: 280px;
width/**/:/**/200px;
}
(3)div
{
border: 20px;
padding: 20px;
width: 200px !important;
width /**/:280px;
} - IE6无法定义1px左右高度的容器:
现象:

解决方法:解决的方法有很多,例如:overflow:hidden | zoom:0.08 | line-height:1px
ASP技巧几则
- 如果使用Access数据库不能更新和删除数据,请检查是否是文件权限的问题。可以将Access文件属性的“安全”选项卡中“everyone”的写入权限选中。如果是xp下,还需要先将“我的电脑”->“文件夹选项”->“查看”中的“使用简单文件共享(推荐)”前的勾去掉,属性中才会有“安全”选项。
- rs.close和set rs=nothing是你的好朋友,永远记住用完就要关闭,要不然很容易把Access锁住。
- 不要边打开数据库修改,边运行ASP程序,同样会把Access锁住。
- 需要返回数据集才有RecordSet,如果只是delete或者update,使用conn.execute更合适。
- 读数据时,使用rs.open sql,conn,1,1,需要写的时候,使用rs.open sql,conn,1,3。
- 对用户输入的数据、需要显示的数据、从数据库中读出来的数据,都需要做好过滤,防止sql注入和xss攻击。
- sql语句错误可能会导致死循环。比如你使用
rs.open sql,conn,1,1,当sql语句有问题(很可能是输入参数出错)时,很容易就死循环了。(not rs.eof 根本不起作用,不知道是微软的哪个程序员想出来的这个逻辑,如果sql语句出错,那么rs理应为空才对啊,这种处理方式真是无语了。)解决方法是使用结果分页,出错时,最多显示一页空白内容,不会死循环。
do while not rs.eof...loop - 一个好的调试器太重要了,Asp Studio不错,好像还是中国人开发的,不过是商业软件,呵呵。
- 多表查询记住使用inner join,left join 和right join。
ubuntu的grub error 17
xp下一次意外死机重启后,就进不了系统了。提示信息是“Error 17...”。
光盘重启到Dos,用“fdisk /mbr” 恢复主引导记录。重启后能进入XP。
使用ubuntu livecd重启,将原来安装ubuntu的分区挂载(mount)在/mnt/目录下。
发现问题出在分区的编号上,以前安装的时候,ubuntu是安装在/dev/hdc8的,也就是grub的(hd0,7)上。而死机以后,这个分区编号莫名其妙的变成了/dev/hdc7,也就是grub的(hd0,6)上。
找到问题就好办了。
chroot /mnt/sudo vim /boot/grub/menu.lst将其中的(hd0,7)都改成(hd0,6)sudo grub
root (hd0,6)
setup (hd0)
quit- 重启



