安静
PHP技术博客

150707 discuz百度分享图片添加

张 清月阅读(924)

继上次 jiathis分享图片问题后,这次需求方又要求改成百度分享,总之程序员么,就是各种解了。 上次地址: discuz jiathis分享图片修改 同样的文件:template/default/forum/viewthread_node.htm 添加如下代码即可解决:

  //找到 aimgcount[{$post[pid]}] = [<!--{echo dimplode($aimgs[$post[pid]]);}-->]; 上方添加 

  <!--{if $threadattachmenturl != null}-->
  window._bd_share_config = { "common": { 
  "bdSnsKey": {}, 
  "bdText": "", 
  "bdMini": "2", 
  "bdMiniList": false, 
  "bdPic": "{echo $threadattachmenturl[0];}",
  "bdStyle": "0", "bdSize": "16" },
  "share": {} 
  }; 
  <!--{/if}--> 

150618 Discuz屏蔽插件安装后删除xml文件

张 清月阅读(902)

插件安装后Discuz会删除Xml文件

当你通过Discuz后台云系统安装完插件以后,系统会调用 source/admincp/admincp_plugins.php 文件进行删除相关的语言安装XML. 我们需要做如下修改进行保留:

//中425行注释即可 
//cloudaddons_clear('plugin', $dir);

//实际函数实现内容
function cloudaddons_clear($type, $id)
{
    global $_G;
    if (isset($_G['config']['plugindeveloper']) && $_G['config']['plugindeveloper'] > 0) {
        return;
    }
    $dirs = array('plugin' => array('plugin', './source/plugin/'), 'template' => array('style', './template/'));
    if ($dirs[$type] && cloudaddons_getmd5($id . '.' . $type)) {
        $entrydir = DISCUZ_ROOT . $dirs[$type][1] . $id;
        $d = dir($entrydir);
        $filedeleted = false;
        while ($f = $d->read()) {
            if (preg_match('/^discuz\_' . $dirs[$type][0] . '\_' . $id . '(\_\w+)?\.xml$/', $f)) {
                @unlink($entrydir . '/' . $f);
                if ($type == 'plugin' && !$filedeleted) {
                    @unlink($entrydir . '/' . $f);
                    $importtxt = @implode('', file($entrydir . '/' . $f));
                    $pluginarray = getimportdata('Discuz! Plugin');
                    if ($pluginarray['installfile']) {
                        @unlink($entrydir . '/' . $pluginarray['installfile']);
                    }
                    if ($pluginarray['upgradefile']) {
                        @unlink($entrydir . '/' . $pluginarray['upgradefile']);
                    }
                    $filedeleted = true;
                }
            }
        }
    }
}

Discuz开启注册表单更多选项后,用户注册依然可以乱填(性别依然为空)

看了下代码这真心的让人很无语

 //source/function/function_profile.php function profile_check 
 //214行 
 if(in_array($fieldid, array('birthday', 'birthmonth', 'birthyear', 'gender'))) { 
    $value = intval($value); return true; 
 } elseif(in_array($fieldid, array('birthprovince', 'birthcity', 'birthdist', 'birthcommunity', 'resideprovince', 'residecity', 'residedist', 'residecommunity'))) {
    $value = getstr($value); 
    return true; 
 } 

Discuz! X3.2 R20150609 发布,但没有走后台通知更新发布功能

补丁包下载(适合 X3.2 任意版本):

简体中文 GBK http://download.comsenz.com/DiscuzX/3.2/patch/DX32R20150609SCGBK.zip
繁体中文 BIG5 http://download.comsenz.com/DiscuzX/3.2/patch/DX32
R20150609TCBIG5.zip
简体 UTF8 http://download.comsenz.com/DiscuzX/3.2/patch/DX32R20150609SCUTF8.zip
繁体 UTF8 http://download.comsenz.com/DiscuzX/3.2/patch/DX32
R20150609TCUTF8.zip  

升级方法:

  1. 根据原有的语言版本下载升级包 
  2. 解压缩, 将目录中的文件上传至服务器, 覆盖旧文件 
  3. 使用创始人身份进入后台更新缓存 更新记录 

150403 Ci框架中language重新加载配置文件

张 清月阅读(691)

Ci加载一种语言配置文件后再加载另外一个是无效的,如何重载呢?

$this->lang->is_loaded = array();
$this->lang->language = array();

//或者

if (isset ( $this->lang->is_loaded )) {
    for($i = 0; $i <= sizeof ( $this->lang->is_loaded ); $i ++) {
        unset ( $this->lang->is_loaded [$i] );
    }
}

From:
http://stackoverflow.com/questions/7563390/codeigniter-change-loaded-language

密码保护:秘密

admin阅读(1054)

这是一篇受密码保护的文章,您需要提供访问密码:

150107 小彩蛋JS

张 清月阅读(761)

看到酷壳上有个小彩蛋JS,觉得挺有意思,做个摘录,不过代码做了压缩代码看上去不是很容易看懂.

javascript: (function() {
    function c() {
        var e = document.createElement("link");
        e.setAttribute("type", "text/css");
        e.setAttribute("rel", "stylesheet");
        e.setAttribute("href", f);
        e.setAttribute("class", l);
        document.body.appendChild(e)
    }

    function h() {
        var e = document.getElementsByClassName(l);
        for (var t = 0; t < e.length; t++) {
            document.body.removeChild(e[t])
        }
    }

    function p() {
        var e = document.createElement("div");
        e.setAttribute("class", a);
        document.body.appendChild(e);
        setTimeout(function() {
            document.body.removeChild(e)
        }, 100)
    }

    function d(e) {
        return {
            height: e.offsetHeight,
            width: e.offsetWidth
        }
    }

    function v(i) {
        var s = d(i);
        return s.height > e && s.height < n && s.width > t && s.width < r
    }

    function m(e) {
        var t = e;
        var n = 0;
        while (!!t) {
            n += t.offsetTop;
            t = t.offsetParent
        }
        return n
    }

    function g() {
        var e = document.documentElement;
        if (!!window.innerWidth) {
            return window.innerHeight
        } else if (e && !isNaN(e.clientHeight)) {
            return e.clientHeight
        }
        return 0
    }

    function y() {
        if (window.pageYOffset) {
            return window.pageYOffset
        }
        return Math.max(document.documentElement.scrollTop, document.body.scrollTop)
    }

    function E(e) {
        var t = m(e);
        return t >= w && t <= b + w
    }

    function S() {
        var e = document.createElement("audio");
        e.setAttribute("class", l);
        e.src = i;
        e.loop = false;
        e.addEventListener("canplay", function() {
            setTimeout(function() {
                x(k)
            }, 500);
            setTimeout(function() {
                N();
                p();
                for (var e = 0; e < O.length; e++) {
                    T(O[e])
                }
            }, 15500)
        }, true);
        e.addEventListener("ended", function() {
            N();
            h()
        }, true);
        e.innerHTML = " <p>If you are reading this, it is because your browser does not support the audio element. We recommend that you get a new browser.</p> <p>";
        document.body.appendChild(e);
        e.play()
    }

    function x(e) {
        e.className += " " + s + " " + o
    }

    function T(e) {
        e.className += " " + s + " " + u[Math.floor(Math.random() * u.length)]
    }

    function N() {
        var e = document.getElementsByClassName(s);
        var t = new RegExp("\\b" + s + "\\b");
        for (var n = 0; n < e.length;) {
            e[n].className = e[n].className.replace(t, "")
        }
    }
    var e = 30;
    var t = 30;
    var n = 350;
    var r = 350;
    var i = "//s3.amazonaws.com/moovweb-marketing/playground/harlem-shake.mp3";
    var s = "mw-harlem_shake_me";
    var o = "im_first";
    var u = ["im_drunk", "im_baked", "im_trippin", "im_blown"];
    var a = "mw-strobe_light";
    var f = "//s3.amazonaws.com/moovweb-marketing/playground/harlem-shake-style.css";
    var l = "mw_added_css";
    var b = g();
    var w = y();
    var C = document.getElementsByTagName("*");
    var k = null;
    for (var L = 0; L < C.length; L++) {
        var A = C[L];
        if (v(A)) {
            if (E(A)) {
                k = A;
                break
            }
        }
    }
    if (A === null) {
        console.warn("Could not find a node of the right size. Please try a different page.");
        return
    }
    c();
    S();
    var O = [];
    for (var L = 0; L < C.length; L++) {
        var A = C[L];
        if (v(A)) {
            O.push(A)
        }
    }
})()

141212 php的cli简介

admin阅读(598)

所有的PHP发行版,不论是编译自源代码的版本还是预创建的版本,都在默认情况下带有一个PHP可执行文件。这个可执行文件可以被用来运行命令行的PHP程序。

       要在你的系统上找到这个可执行文件,就要遵照下面的步骤:

       在Windows操作系统里,它被放在PHP主安装目录下,文件名是php.exe或者(在老版本的PHP里)是php-cli.exe。

        在Linux操作系统里,它被保存在PHP安装目录的bin/子目录下。

不论是在哪一个操作系统里,你都需要对它进行测试,以保证它能够正常运行,方法是用-v参数调用它:

shell> /path/to/php -v
PHP 5.0.0 (cli) (built: Jun 1 2005 18:32:10)
Copyright (c) 1997-2004 The PHP Group
Zend Engine v2.0.0, Copyright (c) 1998-2004 Zend Technologies

它应该会返回PHP的版本号。

一个简单的PHP CLI程序
一旦找到了这个CLI可执行文件,你就可以用一个简单的程序来使用一下。创建一个简单的文本文件,其中包含有以下PHP代码,并把它保存为hello.php:

<?php
echo "Hello from the CLI";
?>

现在,试着在命令行提示符下运行这个程序,方法是调用CLI可执行文件并提供脚本的文件名:

shell> /path/to/phphello.php
Hello from the CLI

使用标准的输入和输出

PHP CLI会定义三个常量,以便让在命令行提示符下与解释器进行交互操作更加容易。这些常量见表格A。

表格A

常量 说明
STDIN 标准的输入设备
STDOUT 标准的输出设备
STDERR 标准的错误设备

你可以在自己的PHP脚本里使用这三个常量,以接受用户的输入,或者显示处理和计算的结果。要更好地理解这一点,可以看看下面的脚本(列表A):

列表A

<?php
// ask for input
fwrite(STDOUT, "Enter your name: ");

// get input
$name = trim(fgets(STDIN));

// write input back
fwrite(STDOUT, "Hello, $name!");
?>
Look what happens when you run it:
shell> /path/to/phphello.php
Enter your name: Joe
Hello, Joe!

在这个脚本里,fwrite()函数首先会向标准的输出设备写一条消息,询问用户的姓名。然后它会把从标准输入设备获得的用户输入信息读取到一个PHP变量里,并它把合并成为一个字符串。然后就用fwrite()把这个字符串打印输出到标准的输出设备上。

使用命令行自变量
在命令行里输入程序参数来更改其运行方式是很常见的做法。你也可以对CLI程序这样做。PHP CLI带有两个特殊的变量,专门用来达到这个目的:一个是$argv变量,它通过命令行把传递给PHP脚本的参数保存为单独的数组元素;另一个是$ argc变量,它用来保存$argv数组里元素的个数。

用PHP脚本编写一段读取$argv并处理它所含参数的代码是很简单的。试试列表B里的示例脚本,看看它是如何工作的:

列表B

<?php
print_r($argv);
?>

Run this script by passing it some arbitrary values, and check the output:

shell> /path/to/phptest.php chocolate 276 "killer tie, dude!"
Array
( [0] => test.php
[1] => chocolate
[2] => 276
[3] => killer tie, dude!
)

正如你可以从输出的结果看到的,传递给test.php的值会自动地作为数组元素出现在$argv里。要注意的是,$argvis的第一个自变量总是脚本自己的名称。

下面是一个更加复杂的例子(列表C):

列表C

<?php
// check for all required arguments
// first argument is always name of script!
if ($argc != 4) {
die("Usage: book.php <check-in-date> <num-nights> <room-type> ");
}

// remove first argument
array_shift($argv);

// get and use remaining arguments
$checkin = $argv[0];
$nights = $argv[1];
$type = $argv[2];
echo "You have requested a $type room for $nights nights, checking in on $checkin. Thank you for your order! ";
?>

下面是其用法的示例:

shell> /path/to/phpbook.php 21/05/2005 7 single
You have requested a single room for 7 nights, checking in on 21/05/2005. Thank you for your order!

在这里,脚本首先会检查$argc,以确保自变量的数量符合要求。它然后会从$argv里提取出每一个自变量,把它们打印输出到标准的输出设备上。

注意:你可以用Console_Getopt PEAR类向PHP增加更加复杂的命令行参数。

使用CLI参数
除了用命令行传递PHP脚本参数,你还可以传递PHP CLI参数以更改其工作方式。表格B就是一些重要参数的列表:

表格B

参数 说明
-a 交互式运行Run interactively
-c path 从path读取php的.ini文件
-n 不用读取php的.ini文件就直接运行
-m 列出经过编译的模块
-i 显示有关PHP构建的信息
-l 检查PHP脚本的句法
-s 以彩色方式显示源代码
-w 显示去掉注释之后的源代码
-h 显示帮助

交互模式
你还可以以交互方式使用PHP CLI,也就是输入命令,马上获得结果。要得到这种效果,只需要使用一个参数调用CLI可执行文件就行了,就像下面这样:

shell> /path/to/php -a

你会看到一个空行,你可以在里面输入PHP代码。看看:

shell> /path/to/php -a
Interactive mode enabled
<?php
echo mktime();
1121187283
echo 2+2;
4
exit();
shell>

或者,你可以不使用-a参数就调用CLI可执行文件,直接输入完整的脚本或者代码段。用-D来结束代码段,并让CLI来执行它。见下面的例子:

shell> /path/to/php
<?php
echo date("d-M-Y h:i:s", time());
?>
<Ctrl-D>
12-Jul-2005 06:54:04

这就是PHP的命令行,现在你应该已经对PHP CLI有了足够的了解,并开始使用它了。

141211 百度地图API获取点击对象属性

admin阅读(546)

先看看地图有哪些事件,查看官网类参考,翻到事件

大家看到这里的参数了麽?

其实,在点击物体时,通过这些参数就能够判断所点击的物体是什么了。

用marker举例:

先创建一个marker

//覆盖物Marker
    var pmk = new BMap.Point(116.249472,39.946583);
    var mk = new BMap.Marker(pmk);
    map.addOverlay(mk);

然后对地图添加点击事件,如果判断出来是覆盖物,就弹出相应的对话框。

 map.addEventListener("click",function(e){
        if(e.overlay){
            alert('你点击的是覆盖物:'+e.overlay.toString());   
        }else{
            alert('你点击的是地图');
        }
    });

添加一堆覆盖物,然后给每个覆盖物写点击事件。

比如我点击了多边形,就会弹出这个。

全部源代码:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>点击事件</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?key=v=1.3"></script>
</head>

<body>
  <!--百度地图容器-->
  <div style="width:697px;height:550px;border:#ccc solid 1px;" id="dituContent"></div>
</body>
<script type="text/javascript">
    var map = new BMap.Map("dituContent");
    var point = new BMap.Point(116.331398,39.897445);
    map.centerAndZoom(point,12);
    map.enableScrollWheelZoom();

    map.addEventListener("click",function(e){
        if(e.overlay){
            alert('你点击的是覆盖物:'+e.overlay.toString());   
        }else{
            alert('你点击的是地图');
        }
    });

    //覆盖物Marker
    var pmk = new BMap.Point(116.249472,39.946583);
    var mk = new BMap.Marker(pmk);
    map.addOverlay(mk);

    //覆盖物Label
    var plb = new BMap.Point(116.408149,39.958087);
    var lb = new BMap.Label('我是覆盖物Label',{point:plb});
    map.addOverlay(lb);

    //覆盖物Polyline
    var pl = new BMap.Polyline([new BMap.Point(116.250047,39.919583),new BMap.Point(116.441494,39.919583)],{strokeWeight:10})
    map.addOverlay(pl);

    //覆盖物Polygon
    var pg = new BMap.Polygon([new BMap.Point(116.248323,39.893016),new BMap.Point(116.440344,39.893016),new BMap.Point(116.440344,39.811036),new BMap.Point(116.248323,39.811036)]);
    map.addOverlay(pg);

</script>
</html>

更多关于百度地图的完整Demo: http://www.80aj.com/demo/map.php

141208 PHP获取用户有效IP

张 清月阅读(584)

oschina看到一篇关于爆discuz后台的文章,一想不太对, discuz本身通过代码做了一层密码尝试过多干掉ip的功能,也就是表 pre_common_failedlogin

实际拿了代码跑了下竟然是可以的,具体看了下discuz代码.

source/class/discuz/discuz_application.php中:

private function _get_client_ip() {
                $ip = $_SERVER['REMOTE_ADDR'];
                if (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
                        $ip = $_SERVER['HTTP_CLIENT_IP'];
                } elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
                        foreach ($matches[0] AS $xip) {
                                if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
                                        $ip = $xip;
                                        break;
                                }
                        }
                }
                return $ip;
        }

获取ip的最后一段是根据头部x_forwarded_for做ip设置,所以在发送模拟post的时候增加HTTP_X_FORWARDED_FOR就能轻松跳过ip failed.

找了下资料在这里扒皮说下:


一、没有使用代理服务器的PHP获取客户端IP情况:

REMOTE_ADDR = 客户端IP
HTTP_X_FORWARDED_FOR = 没数值或不显示

二、使用透明代理服务器的情况:Transparent Proxies

REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 客户端真实 IP (经过多个代理服务器时,这个值类似:221.5.252.160, 203.98.182.163, 203.129.72.215)
这类代理服务器还是将客户端真实的IP发送给了访问对象,无法达到隐藏真实身份的目的.

三、使用普通匿名代理服务器的PHP获取客户端IP情况:Anonymous Proxies

REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP (经过多个代理服务器时,这个值类似:203.98.182.163, 203.98.182.163, 203.129.72.215)
这种情况下隐藏了客户端的真实IP,但是向访问对象透露了客户端是使用代理服务器访问它们的.

四、使用欺骗性代理服务器的情况:Distorting Proxies

REMOTE_ADDR = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP(经过多个代理服务器时,这个值类似:220.4.251.159, 203.98.182.163, 203.129.72.215)
这种情况下同样透露了客户端是使用了代理服务器,但编造了一个虚假的随机IP(220.4.251.159)代替客户端的真实IP来欺骗它.

五、使用高匿名代理服务器的PHP获取客户端IP情况:High Anonymity Proxies (Elite proxies)

REMOTE_ADDR = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 没数值或不显示

无论是REMOTE_ADDR还是HTTP_FORWARDED_FOR,这些头消息未必能够取得到,因为不同的浏览器不同的网络设备可能发送不同的IP头消息.因此PHP使用$_SERVER["REMOTE_ADDR"] 、$_SERVER["HTTP_X_FORWARDED_FOR"] 获取的值可能是空值也可能是“unknown”值.

 

在我们实际使用过程中,我们会有更多的选择如:

HTTP_X_REAL_IP

HTTP_CLIENT_IP

HTTP_X_FORWARDED_FOR

REMOTE_ADDR

推荐检查顺序从上往下, 最靠谱的是REMOTE_ADDR

文章参考:

修复discuz获取用户ipbug
HTTP_X_FORWARDED_FOR,REMOTE_ADDR区别
推荐get_real_ip()
暴力破解dz密码

141119 社区单点SSO登录

admin阅读(480)

 

单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。单点登录在大型网站里使用得非常频繁,例如像阿里巴巴这样的网站,在网站的背后是成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都需要用户认证,不仅用户会疯掉,各子系统也会为这种重复认证授权的逻辑搞疯掉。实现单点登录说到底就是要解决如何产生和存储那个信任,再就是其他系统如何验证这个信任的有效性,因此要点也就以下几个:

 

  • 存储信任
  • 验证信任

 

只要解决了以上的问题,达到了开头讲得效果就可以说是SSO。最简单实现SSO的方法就是用Cookie,实现流程如下所示:

 

不然发现以上的方案是把信任存储在客户端的Cookie里,这种方法虽然实现方便但立马会让人质疑两个问题:

 

  • Cookie不安全
  • 不能跨域免登

 

对于第一个问题一般都是通过加密Cookie来处理,第二个问题是硬伤,其实这种方案的思路的就是要把这个信任关系存储在客户端,要实现这个也不一定只能用Cookie,用flash也能解决,flash的Shared Object API就提供了存储能力。

 

一般说来,大型系统会采取在服务端存储信任关系的做法,实现流程如下所示:

 

以上方案就是要把信任关系存储在单独的SSO系统(暂且这么称呼它)里,说起来只是简单地从客户端移到了服务端,但其中几个问题需要重点解决:

 

  • 如何高效存储大量临时性的信任数据
  • 如何防止信息传递过程被篡改
  • 如何让SSO系统信任登录系统和免登系统

 

对于第一个问题,一般可以采用类似与memcached的分布式缓存的方案,既能提供可扩展数据量的机制,也能提供高效访问。对于第二个问题,一般采取数字签名的方法,要么通过数字证书签名,要么通过像md5的方式,这就需要SSO系统返回免登URL的时候对需验证的参数进行md5加密,并带上token一起返回,最后需免登的系统进行验证信任关系的时候,需把这个token传给SSO系统,SSO系统通过对token的验证就可以辨别信息是否被改过。对于最后一个问题,可以通过白名单来处理,说简单点只有在白名单上的系统才能请求生产信任关系,同理只有在白名单上的系统才能被免登录。

141017 PHP单链表结构

张 清月阅读(515)

单链表结构(建议最后阅读):

链表中的数据是以节点来表示的,每个节点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个节点的地址数据。

以“结点的序列”表示线性表称作线性链表(单链表)

单链表是链式存取的结构,为找第 i 个数据元素,必须先找到第 i-1 个数据元素。
因此,查找第 i 个数据元素的基本操作为:移动指针,比较 j 和 i

1秒看懂单链结构

object(singelLinkList)#1 (1) {
  ["header":"singelLinkList":private]=>
  object(node)#2 (3) {
    ["id"]=>
    NULL
    ["name"]=>
    NULL
    ["next"]=>
    object(node)#4 (3) {
      ["id"]=>
      int(1)
      ["name"]=>
      string(6) "aaaaaa"
      ["next"]=>
      object(node)#8 (3) {
        ["id"]=>
        int(2)
        ["name"]=>
        string(6) "bbbbbb"
        ["next"]=>
        object(node)#7 (3) {
          ["id"]=>
          int(3)
          ["name"]=>
          string(6) "cccccc"
          ["next"]=>
          object(node)#6 (3) {
            ["id"]=>
            int(4)
            ["name"]=>
            string(6) "dddddd"
            ["next"]=>
            object(node)#3 (3) {
              ["id"]=>
              int(5)
              ["name"]=>
              string(6) "eeeeee"
              ["next"]=>
              object(node)#5 (3) {
                ["id"]=>
                int(6)
                ["name"]=>
                string(6) "ffffff"
                ["next"]=>
                NULL
              }
            }
          }
        }
      }
    }
  }
}

PHP理解单链表应用



 //链表节点 
class node { 
    public $id; //节点id 
    public $name; //节点名称 
    public $next; //下一节点 
     
     public function __construct($id, $name) { 
        $this->id = $id; 
        $this->name = $name; 
        $this->next = null; 
    } 
} 
 //单链表 
class singelLinkList { 
    private $header; //链表头节点 
     
     //构造方法 
    public function __construct($id = null, $name = null) { 
        $this->header = new node ( $id, $name, null ); 
    } 

    //获取链表长度 
    public function getLinkLength() { 
        $i = 0; 
        $current = $this->header; 
        while ( $current->next != null ) { 
            $i ++; 
            $current = $current->next; 
        } 
        return $i; 
    } 

    //添加节点数据 
    public function addLink($node) { 
        $current = $this->header; 
        while ( $current->next != null ) { 
            if ($current->next->id > $node->id) { 
                break; 
            } 
            $current = $current->next; 
        } 
        $node->next = $current->next; 
        $current->next = $node; 
    } 

    //删除链表节点 
    public function delLink($id) { 
        $current = $this->header; 
        $flag = false; 
        while ( $current->next != null ) { 
            if ($current->next->id == $id) { 
                $flag = true; 
                break; 
            } 
            $current = $current->next; 
        } 
        if ($flag) { 
            $current->next = $current->next->next; 
        } else { 
            echo "未找到id=" . $id . "的节点!\n\r"; 
        } 
    } 

    //获取链表 
    public function getLinkList() { 
        $current = $this->header; 
        if ($current->next == null) { 
            echo ("链表为空!"); 
            return; 
        } 
        while ( $current->next != null ) { 
            echo 'id:' . $current->next->id . '   name:' . $current->next->name . "\n\r"; 
            if ($current->next->next == null) { 
                break; 
            } 
            $current = $current->next; 
        } 
    } 

    //获取节点名字 
    public function getLinkNameById($id) { 
        $current = $this->header; 
        if ($current->next == null) { 
            echo "链表为空!"; 
            return; 
        } 
        while ( $current->next != null ) { 
            if ($current->id == $id) { 
                break; 
            } 
            $current = $current->next; 
        } 
        return $current->name; 
    } 

    //更新节点名称 
    public function updateLink($id, $name) { 
        $current = $this->header; 
        if ($current->next == null) { 
            echo "链表为空!"; 
            return; 
        } 
        while ( $current->next != null ) { 
            if ($current->id == $id) { 
                break; 
            } 
            $current = $current->next; 
        } 
        return $current->name = $name; 
    } 
} 
 $lists = new singelLinkList (); 
$lists->addLink ( new node ( 5, 'eeeeee' ) ); 
$lists->addLink ( new node ( 1, 'aaaaaa' ) ); 
$lists->addLink ( new node ( 6, 'ffffff' ) ); 
$lists->addLink ( new node ( 4, 'dddddd' ) ); 
$lists->addLink ( new node ( 3, 'cccccc' ) ); 
$lists->addLink ( new node ( 2, 'bbbbbb' ) ); 

echo "\n\r-----------PHP数组--------------\n\r"; 

var_dump($lists);

echo "\n\r-----------节点列表--------------\n\r"; 

$lists->getLinkList (); 

echo "\n\r-----------删除节点--------------\n\r"; 
$lists->delLink ( 5 ); 
$lists->getLinkList (); 
 echo "\n\r-----------更新节点名称--------------\n\r"; 
$lists->updateLink ( 3, "222222" ); 
$lists->getLinkList (); 
 echo "\n\r-----------获取节点名称--------------\n\r"; 
echo $lists->getLinkNameById ( 5 ); 
 echo "\n\r-----------获取链表长度--------------\n\r"; 
echo $lists->getLinkLength (); 

一句话

单链结构即查找数据是依据指针移动实现

141008 PHP全局变量global详解

admin阅读(513)

简单的代码:为什么输出的却是0?!!

在用户自定义函数中,一个局部函数范围将被引入。任何用于函数内部的变量按缺省情况将被限制在局部函数范围内(包括include 和 require 导入的文件内的变量)!
解释:A.php文件的内Test_Global是定义好的第三方函数,该函数用include导入了B.php文件内的$a的global全局变量,所以$a被限制在Test_Global局部函数范围内,所以B.php文件内的$a的作用范围都在Test_Global内,而不是作用了整个A.php内….

解决方案:

冲出局部函数

	 //A.php 文件
	 
	<?php
	function Test_Global()
	{  
	Test();  
	}  
	include 'B.php';   //将include 从局部Test_Global函数中移出
	$a = 0 ;
	Test_Global();
	echo $a;
	?> 
	 
	//B.php 文件
	 
	<?php
	function Test()
	{
	 global $a;
	 $a =1;
	}
	 ?>

优秀的访问器

        //A.php 文件
	<?php
	include 'B.php'; 
	$a =0;
	Set_Global($a);
	echo $a;
	?> 
	 
	//B.php 文件
	 
	<?php
	function Set_Global(&$var)
	{
	   $var=1;
	}
	 ?>

140928 discuz应用更新提醒窗口的关闭方法

admin阅读(692)

导读: 用管理员帐号登录discuz的时候总有这个应用更新提示的小窗口, 因为不想更新所以觉得很烦. 决定把这个小窗口删除.关闭应用更新提醒窗口只要注释几行代码就可以了.

每次用管理员帐号登录discuz的时候总有这个应用更新提示的小窗口, 因为不想更新所以觉得很烦. 决定把这个小窗口删除.

关闭应用更新提醒窗口的方法:

打开 discuz网站目录/source/module/misc/misc_patch.php, 把if($newversion) {…}这里的代码全部注释掉, 保存上传, 更新一下缓存, 那个应用的更新提示就屏蔽了.

if($newversion) {
$lang = lang('forum/misc');
echo '<div "bm"><div "bm_h cl"><a href="javascript:;" "$('plugin_notice').style.display='none';setcookie('pluginnotice', 1, 86400)" "y" title="'.$lang['patch_close'].'">'.$lang['patch_close'].'</a>';
echo '<h2 "i">'.$lang['plugin_title'].'</h2></div><div "bm_c">';
echo '<div "cl bbda pbm">'.lang('forum/misc', 'plugin_memo', array('number' => $newversion)).'</div>';
echo '<div "ptn cl"><a href="admin.php?action=plugins" "xi2 y">'.$lang['plugin_link'].' &raquo;</a></div>';
echo '</div></div>';
}

注释代码的方法: 在每行前面加上双斜杠就表示屏蔽了.

140917 discuz解决开启远程静态文件无法适用复制功能

admin阅读(508)

最近发现discuz使用webkit内核的浏览器(火狐、Chrome、Safari等webkit内核的浏览器)来点击帖子的  [复制链接]  ,复制到剪切板的内容不是帖子标题和链接 ,而是:_level0.str

考虑到Discuz X2使用的是 [复制链接] 功能是使用了一个swf文件,而论坛刚刚好开启远程静态文件负载,这个swf文件就在远程服务器上了,考虑到了是不是因为这个原因导致这个功能在相应内核的浏览器上有些小问题呢?

接着测试而IE浏览器下却是正常的,关于这个我找了5个多小时的资料,都找不到解决方法。

最后做了尝试,把这个clipboard.swf文件放回 /static/image/common/ 目录里面去,接着修改/static/js/common_extra.js文件,

  1. var msg = ‘<div class=”c”><div style=”width: 200px; text-align: center; text-decoration:underline;”>点此复制到剪贴板</div>’ +
  2. AC_FL_RunContent(‘id’, ‘clipboardswf’, ‘name’, ‘clipboardswf’, ‘devicefont’, ‘false’, ‘width’, ’200′, ‘height’, ’40′, ‘src’, STATICURL + ‘image/common/clipboard.swf’, ‘menu’, ‘false’,  ‘allowScriptAccess’, ‘sameDomain’, ‘swLiveConnect’, ‘true’, ‘wmode’, ‘transparent’, ‘style’ , ‘margin-top:-20px’) + ‘</div>’;
  3. showDialog(msg, ‘info’);
  4. text = text.replace(/[\xA0]/g, ‘ ‘);
  5. CLIPBOARDSWFDATA = text;

复制代码

修改为:

  1. var msg = ‘<div class=”c”><div style=”width: 200px; text-align: center; text-decoration:underline;”>点此复制到剪贴板</div>’ +
  2. AC_FL_RunContent(‘id’, ‘clipboardswf’, ‘name’, ‘clipboardswf’, ‘devicefont’, ‘false’, ‘width’, ’200′, ‘height’, ’40′, ‘src’,  ‘/static/image/common/clipboard.swf’, ‘menu’, ‘false’,  ‘allowScriptAccess’, ‘sameDomain’, ‘swLiveConnect’, ‘true’, ‘wmode’, ‘transparent’, ‘style’ , ‘margin-top:-20px’) + ‘</div>’;
  3. showDialog(msg, ‘info’);
  4. text = text.replace(/[\xA0]/g, ‘ ‘);
  5. CLIPBOARDSWFDATA = text;

复制代码

即可解决问题。

140916 discuz对不起,您安装的不是正版应用修改

admin阅读(622)

Discuz! X2.5安装插件出现:对不起,您安装的不是正版应用的解决方法

discuz 社区在更新到2.0以上后,增加了对插件的版本检测,在安装时,可能会出现:“对不起,您安装的不是正版应用,安装程序无法继续执行”的提示,要解决这个其实挺容易的,找到以下文件:

/source/function/function_cloudaddons.php

找到文件中的cloudaddons_validator这个处理过程,将中间提示部份注释掉,改为像以下这样即可大功告成。。

---------------------------

function cloudaddons_validator($addonid) {
$array = cloudaddons_getmd5($addonid);
if(cloudaddons_open('&mod=app&ac=validator&addonid='.$addonid.($array !== false ? '&rid='.$array['RevisionID'].'&sn='.$array['SN'].'&rd='.$array['RevisionDateline'] : '')) === '0') {
/**
cpmsg('cloudaddons_genuine_message', '', 'error', array('addonid' => $addonid));
*/
}
}