吕滔博客 https://www.lvtao.net/ zh-CN 记录一些工作或生活或爱好的地方 Thu, 13 Jul 2017 21:35:00 +0800 Thu, 13 Jul 2017 21:35:00 +0800 WEUI原生以及使用webuploader插件上传方法 https://www.lvtao.net/dev/weui-webuploader.html https://www.lvtao.net/dev/weui-webuploader.html Thu, 13 Jul 2017 21:35:00 +0800 memory 直接撸代码

$(function() {
        // 允许上传的图片类型
        var allowTypes = [ 'image/jpg', 'image/jpeg', 'image/png', 'image/gif' ];
        // 1024KB,也就是 1MB
        var maxSize = 1024 * 1024;
        // 图片最大宽度
        var maxWidth = 300;
        // 最大上传图片数量
        var maxCount = 6;
        $('.js_file').on('change', function(event) {
            var files = event.target.files;
            // 如果没有选中文件,直接返回
            if (files.length === 0) {
                return;
            }
            for (var i = 0, len = files.length; i < len; i++) {
                var file = files[i];
                var reader = new FileReader();
                // 如果类型不在允许的类型范围内
                if (allowTypes.indexOf(file.type) === -1) {
                    $.weui.alert({
                        text : '该类型不允许上传'
                    });
                    continue;
                }
                if (file.size > maxSize) {
                    $.weui.alert({
                        text : '图片太大,不允许上传'
                    });
                    continue;
                }
                if ($('.weui_uploader_file').length >= maxCount) {
                    $.weui.alert({
                        text : '最多只能上传' + maxCount + '张图片'
                    });
                    return;
                }
                reader.onload = function(e) {
                    var img = new Image();
                    img.onload = function() {
                        // 不要超出最大宽度
                        var w = Math.min(maxWidth, img.width);
                        // 高度按比例计算
                        var h = img.height * (w / img.width);
                        var canvas = document.createElement('canvas');
                        var ctx = canvas.getContext('2d');
                        // 设置 canvas 的宽度和高度
                        canvas.width = w;
                        canvas.height = h;
                        ctx.drawImage(img, 0, 0, w, h);
                        var base64 = canvas.toDataURL('image/png');

                        // 插入到预览区
                        var $preview = $('<li class="weui-uploader__file weui-uploader__file_status" style="background-image:url('
                                + base64 + ')"><div class="weui-uploader__file-content">0%</div></li>');

                        $('.weui-uploader__files').append($preview);

                        // 然后假装在上传,可以post base64格式,也可以构造blob对象上传,也可以用微信JSSDK上传
                        var progress = 0;
                        function uploading() {
                            $preview.find('.weui-uploader__file-content').text(++progress + '%');
                            if (progress < 100) {
                                setTimeout(uploading, 30);
                            } else {
                                // 如果是失败,塞一个失败图标
                                //$preview.find('.weui-uploader__file-content').html('<i class="weui_icon_warn"></i>');
                                $preview.removeClass('weui-uploader__file_status')
                                        .find('.weui-uploader__file-content')
                                        .remove();
                            }
                        }
                        setTimeout(uploading, 30);
                    };
                    img.src = e.target.result;
                };
                reader.readAsDataURL(file);
            }
        });
    });

前端

<div class="weui-cells weui-cells_form">
    <form method="post">
        <div class="weui-cells__title">照片</div>
        <div class="weui-cell">
            <div class="weui-cell__bd">
                <div class="weui-uploader__bd">
                    <ul class="weui-uploader__files"></ul>
                    <div class="weui-uploader__input-box">
                        <input id="uploaderInput" class="weui-uploader__input js_file" type="file" accept="image/*" multiple>
                    </div>
                </div>
            </div>
        </div>
        <div class="weui-btn-area"><a href="javascript:;" class="weui-btn weui-btn_primary">保存</a></div>
    </form>
</div>

来上webuploader的

var uploader = WebUploader.create({
        auto: true,
        swf: '/statics/webuploader-0.1.5/Uploader.swf',
        server: 'upload____url',
        pick: '#imgInput',
        accept: {
            title: 'Images',
            extensions: 'gif,jpg,jpeg,bmp,png',
            mimeTypes: 'image/*'
        },
        method: 'POST'
    });
    uploader.on('fileQueued', function(file) {
        var $preview = $('<li id="'+file.id+'" class="weui-uploader__file weui-uploader__file_status"><div class="weui-uploader__file-content">0%</div></li>');
        $('#imgList').append($preview);
        uploader.makeThumb(file, function( error, src) {
            $('#'+file.id).css('background-image','url('+src+')');
        }, 79, 79 );
    });
    uploader.on('uploadProgress', function(file, percentage ) {
        $('#'+file.id).find('.weui-uploader__file-content').html(percentage+'%');
    });
    uploader.on('uploadSuccess', function(file, response) {
        $('#'+file.id).removeClass('weui-uploader__file_status')
                .find('.weui-uploader__file-content')
                .remove();
        // 上传成功,想干点什么就在这里干吧
    });

前端

<div class="weui-cell">
    <div class="weui-cell__bd">
        <div class="weui-uploader__bd">
            <ul class="weui-uploader__files" id="imgList"></ul>
            <div class="weui-uploader__input-box">
                <div id="imgInput" class="weui-uploader__input">选择图片</div>
            </div>
        </div>
    </div>
</div>

我本地使用的

var num=0;
    var uploader = WebUploader.create({
        auto: true,
        swf: '/js/Uploader.swf',
        server: 'upurl',
        pick: '#imgInput',
        accept: {
            title: 'Images',
            extensions: 'gif,jpg,jpeg,bmp,png',
            mimeTypes: 'image/*'
        },
        method: 'POST',
        fileNumLimit:9
    });
    uploader.on('fileQueued', function(file) {
        var $preview = $('<li id="'+file.id+'" class="weui-uploader__file weui-uploader__file_status"><div class="weui-uploader__file-content">0%</div></li>');
        $('#imgList').append($preview);
        uploader.makeThumb(file, function( error, src) {
            $('#'+file.id).css('background-image','url('+src+')');
        }, 80, 80 );
    });
    uploader.on('uploadProgress', function(file, percentage ) {
        $('#'+file.id).find('.weui-uploader__file-content').html(percentage.toFixed(1) + '%');
    });
    uploader.on('uploadSuccess', function(file, response) {
        $('#'+file.id).removeClass('weui-uploader__file_status')
                .find('.weui-uploader__file-content')
                .remove();
        // 上传成功,想干点什么就在这里干吧
        $('#'+file.id).append('<input type="hidden" name="file[]" value="'+response.imgid+'"/>');
        num++;
        $("#number").html(num+'/9');
        if(num==9){
            $('.weui-uploader__input-box').hide();
        }
    });
]]>
0 https://www.lvtao.net/dev/weui-webuploader.html#comments https://www.lvtao.net/feed/dev/weui-webuploader.html
此内容被密码保护 https://www.lvtao.net/tool/mac-tor.html https://www.lvtao.net/tool/mac-tor.html Sun, 09 Jul 2017 06:44:00 +0800 memory

请输入密码访问

]]>
0 https://www.lvtao.net/tool/mac-tor.html#comments https://www.lvtao.net/feed/tool/mac-tor.html
分享一下替换了InitPHP中的邮件发送类 支持SSL https://www.lvtao.net/dev/php-mailclass-sendmail.html https://www.lvtao.net/dev/php-mailclass-sendmail.html Sat, 08 Jul 2017 07:10:23 +0800 memory 因为阿里云已经封了25端口,所以必须要上ssl的邮件类了,个人不喜欢那些动不动引入一堆文件的类,所以将InitPHP的自带邮件类换成了支持SSL的,方法使用上略有不同,但大致差不多

<?php
if (!defined('IS_INITPHP')) exit('Access Denied!');
/**
 * 邮件发送类
 * 支持发送纯文本邮件和HTML格式的邮件,可以多收件人,多抄送,多秘密抄送,带附件(单个或多个附件),支持到服务器的ssl连接
 * 需要的php扩展:sockets、Fileinfo和openssl。
 * 编码格式是UTF-8,传输编码格式是base64
 */
class emailInit {
    /**
     * @var string 邮件传输代理用户名
     * @access protected
     */
    protected $_userName;

    /**
     * @var string 邮件传输代理密码
     * @access protected
     */
    protected $_password;

    /**
     * @var string 邮件传输代理服务器地址
     * @access protected
     */
    protected $_sendServer;

    /**
     * @var int 邮件传输代理服务器端口
     * @access protected
     */
    protected $_port;

    /**
     * @var string 发件人
     * @access protected
     */
    protected $_from;

    /**
     * @var array 收件人
     * @access protected
     */
    protected $_to = array();

    /**
     * @var array 抄送
     * @access protected
     */
    protected $_cc = array();

    /**
     * @var array 秘密抄送
     * @access protected
     */
    protected $_bcc = array();

    /**
     * @var string 主题
     * @access protected
     */
    protected $_subject;

    /**
     * @var string 邮件正文
     * @access protected
     */
    protected $_body;

    /**
     * @var array 附件
     * @access protected
     */
    protected $_attachment = array();

    /**
     * @var reource socket资源
     * @access protected
     */
    protected $_socket;

    /**
     * @var reource 是否是安全连接
     * @access protected
     */
    protected $_isSecurity;

    /**
     * @var string 错误信息
     * @access protected
     */
    protected $_errorMessage;


    /**
     * 设置邮件传输代理,如果是可以匿名发送有邮件的服务器,只需传递代理服务器地址就行
     * @access public
     * @param string $server 代理服务器的ip或者域名
     * @param string $username 认证账号
     * @param string $password 认证密码
     * @param int $port 代理服务器的端口,smtp默认25号端口
     * @param boolean $isSecurity 到服务器的连接是否为安全连接,默认false
     * @return boolean
     */
    public function setServer($server, $username="", $password="", $port=25, $isSecurity=false) {
        $this->_sendServer = $server;
        $this->_port = $port;
        $this->_isSecurity = $isSecurity;
        $this->_userName = empty($username) ? "" : base64_encode($username);
        $this->_password = empty($password) ? "" : base64_encode($password);
        return true;
    }

    /**
     * 设置发件人
     * @access public
     * @param string $from 发件人地址
     * @return boolean
     */
    public function setFrom($from) {
        $this->_from = $from;
        return true;
    }

    /**
     * 设置收件人,多个收件人,调用多次.
     * @access public
     * @param string $to 收件人地址
     * @return boolean
     */
    public function setReceiver($to) {
        $this->_to[] = $to;
        return true;
    }

    /**
     * 设置抄送,多个抄送,调用多次.
     * @access public
     * @param string $cc 抄送地址
     * @return boolean
     */
    public function setCc($cc) {
        $this->_cc[] = $cc;
        return true;
    }

    /**
     * 设置秘密抄送,多个秘密抄送,调用多次
     * @access public
     * @param string $bcc 秘密抄送地址
     * @return boolean
     */
    public function setBcc($bcc) {
        $this->_bcc[] = $bcc;
        return true;
    }

    /**
     * 设置邮件附件,多个附件,调用多次
     * @access public
     * @param string $file 文件地址
     * @return boolean
     */
    public function addAttachment($file) {
        if(!file_exists($file)) {
            $this->_errorMessage = "file " . $file . " does not exist.";
            return false;
        }
        $this->_attachment[] = $file;
        return true;
    }

    /**
     * 设置邮件信息
     * @access public
     * @param string $body 邮件主题
     * @param string $subject 邮件主体内容,可以是纯文本,也可是是HTML文本
     * @return boolean
     */
    public function setMail($subject, $body) {
        $this->_subject = base64_encode($subject);
        $this->_body = base64_encode($body);
        return true;
    }

    /**
     * 发送邮件
     * @access public
     * @return boolean
     */
    public function sendMail() {
        $command = $this->getCommand();

        $this->_isSecurity ? $this->socketSecurity() : $this->socket();

        foreach ($command as $value) {
            $result = $this->_isSecurity ? $this->sendCommandSecurity($value[0], $value[1]) : $this->sendCommand($value[0], $value[1]);
            if($result) {
                continue;
            }
            else{
                return false;
            }
        }
        //其实这里也没必要关闭,smtp命令:QUIT发出之后,服务器就关闭了连接,本地的socket资源会自动释放
        $this->_isSecurity ? $this->closeSecutity() : $this->close();
        return true;
    }

    /**
     * 返回错误信息
     * @return string
     */
    public function error(){
        if(!isset($this->_errorMessage)) {
            $this->_errorMessage = "";
        }
        return $this->_errorMessage;
    }

    /**
     * 返回mail命令
     * @access protected
     * @return array
     */
    protected function getCommand() {
        $separator = "----=_Part_" . md5($this->_from . time()) . uniqid(); //分隔符

        $command = array(
            array("HELO sendmail\r\n", 250)
        );
        if(!empty($this->_userName)){
            $command[] = array("AUTH LOGIN\r\n", 334);
            $command[] = array($this->_userName . "\r\n", 334);
            $command[] = array($this->_password . "\r\n", 235);
        }

        //设置发件人
        $command[] = array("MAIL FROM: <" . $this->_from . ">\r\n", 250);
        $header = "FROM: <" . $this->_from . ">\r\n";

        //设置收件人
        if(!empty($this->_to)) {
            $count = count($this->_to);
            if($count == 1){
                $command[] = array("RCPT TO: <" . $this->_to[0] . ">\r\n", 250);
                $header .= "TO: <" . $this->_to[0] .">\r\n";
            }
            else{
                for($i=0; $i<$count; $i++){
                    $command[] = array("RCPT TO: <" . $this->_to[$i] . ">\r\n", 250);
                    if($i == 0){
                        $header .= "TO: <" . $this->_to[$i] .">";
                    }
                    elseif($i + 1 == $count){
                        $header .= ",<" . $this->_to[$i] .">\r\n";
                    }
                    else{
                        $header .= ",<" . $this->_to[$i] .">";
                    }
                }
            }
        }

        //设置抄送
        if(!empty($this->_cc)) {
            $count = count($this->_cc);
            if($count == 1){
                $command[] = array("RCPT TO: <" . $this->_cc[0] . ">\r\n", 250);
                $header .= "CC: <" . $this->_cc[0] .">\r\n";
            }
            else{
                for($i=0; $i<$count; $i++){
                    $command[] = array("RCPT TO: <" . $this->_cc[$i] . ">\r\n", 250);
                    if($i == 0){
                        $header .= "CC: <" . $this->_cc[$i] .">";
                    }
                    elseif($i + 1 == $count){
                        $header .= ",<" . $this->_cc[$i] .">\r\n";
                    }
                    else{
                        $header .= ",<" . $this->_cc[$i] .">";
                    }
                }
            }
        }

        //设置秘密抄送
        if(!empty($this->_bcc)) {
            $count = count($this->_bcc);
            if($count == 1) {
                $command[] = array("RCPT TO: <" . $this->_bcc[0] . ">\r\n", 250);
                $header .= "BCC: <" . $this->_bcc[0] .">\r\n";
            }
            else{
                for($i=0; $i<$count; $i++){
                    $command[] = array("RCPT TO: <" . $this->_bcc[$i] . ">\r\n", 250);
                    if($i == 0){
                        $header .= "BCC: <" . $this->_bcc[$i] .">";
                    }
                    elseif($i + 1 == $count){
                        $header .= ",<" . $this->_bcc[$i] .">\r\n";
                    }
                    else{
                        $header .= ",<" . $this->_bcc[$i] .">";
                    }
                }
            }
        }

        //主题
        $header .= "Subject: =?UTF-8?B?" . $this->_subject ."?=\r\n";
        if(isset($this->_attachment)) {
            //含有附件的邮件头需要声明成这个
            $header .= "Content-Type: multipart/mixed;\r\n";
        }
        elseif(false){
            //邮件体含有图片资源的,且包含的图片在邮件内部时声明成这个,如果是引用的远程图片,就不需要了
            $header .= "Content-Type: multipart/related;\r\n";
        }
        else{
            //html或者纯文本的邮件声明成这个
            $header .= "Content-Type: multipart/alternative;\r\n";
        }

        //邮件头分隔符
        $header .= "\t" . 'boundary="' . $separator . '"';

        $header .= "\r\nMIME-Version: 1.0\r\n";

        //这里开始是邮件的body部分,body部分分成几段发送
        $header .= "\r\n--" . $separator . "\r\n";
        $header .= "Content-Type:text/html; charset=utf-8\r\n";
        $header .= "Content-Transfer-Encoding: base64\r\n\r\n";
        $header .= $this->_body . "\r\n";
        $header .= "--" . $separator . "\r\n";

        //加入附件
        if(!empty($this->_attachment)){
            $count = count($this->_attachment);
            for($i=0; $i<$count; $i++){
                $header .= "\r\n--" . $separator . "\r\n";
                $header .= "Content-Type: " . $this->getMIMEType($this->_attachment[$i]) . '; name="=?UTF-8?B?' . base64_encode( basename($this->_attachment[$i]) ) . '?="' . "\r\n";
                $header .= "Content-Transfer-Encoding: base64\r\n";
                $header .= 'Content-Disposition: attachment; filename="=?UTF-8?B?' . base64_encode( basename($this->_attachment[$i]) ) . '?="' . "\r\n";
                $header .= "\r\n";
                $header .= $this->readFile($this->_attachment[$i]);
                $header .= "\r\n--" . $separator . "\r\n";
            }
        }

        //结束邮件数据发送
        $header .= "\r\n.\r\n";


        $command[] = array("DATA\r\n", 354);
        $command[] = array($header, 250);
        $command[] = array("QUIT\r\n", 221);

        return $command;
    }

    /**
     * 发送命令
     * @access protected
     * @param string $command 发送到服务器的smtp命令
     * @param int $code 期望服务器返回的响应吗
     * @return boolean
     */
    protected function sendCommand($command, $code) {
        echo 'Send command:' . $command . ',expected code:' . $code . '<br />';
        //发送命令给服务器
        try{
            if(socket_write($this->_socket, $command, strlen($command))){

                //当邮件内容分多次发送时,没有$code,服务器没有返回
                if(empty($code))  {
                    return true;
                }

                //读取服务器返回
                $data = trim(socket_read($this->_socket, 1024));
                echo 'response:' . $data . '<br /><br />';

                if($data) {
                    $pattern = "/^".$code."+?/";
                    if(preg_match($pattern, $data)) {
                        return true;
                    }
                    else{
                        $this->_errorMessage = "Error:" . $data . "|**| command:";
                        return false;
                    }
                }
                else{
                    $this->_errorMessage = "Error:" . socket_strerror(socket_last_error());
                    return false;
                }
            }
            else{
                $this->_errorMessage = "Error:" . socket_strerror(socket_last_error());
                return false;
            }
        }catch(Exception $e) {
            $this->_errorMessage = "Error:" . $e->getMessage();
        }
    }

    /**
     * 安全连接发送命令
     * @access protected
     * @param string $command 发送到服务器的smtp命令
     * @param int $code 期望服务器返回的响应吗
     * @return boolean
     */
    protected function sendCommandSecurity($command, $code) {
        echo 'Send command:' . $command . ',expected code:' . $code . '<br />';
        try {
            if(fwrite($this->_socket, $command)){
                //当邮件内容分多次发送时,没有$code,服务器没有返回
                if(empty($code))  {
                    return true;
                }
                //读取服务器返回
                $data = trim(fread($this->_socket, 1024));
                echo 'response:' . $data . '<br /><br />';

                if($data) {
                    $pattern = "/^".$code."+?/";
                    if(preg_match($pattern, $data)) {
                        return true;
                    }
                    else{
                        $this->_errorMessage = "Error:" . $data . "|**| command:";
                        return false;
                    }
                }
                else{
                    return false;
                }
            }
            else{
                $this->_errorMessage = "Error: " . $command . " send failed";
                return false;
            }
        }catch(Exception $e) {
            $this->_errorMessage = "Error:" . $e->getMessage();
        }
    }

    /**
     * 读取附件文件内容,返回base64编码后的文件内容
     * @access protected
     * @param string $file 文件
     * @return mixed
     */
    protected function readFile($file) {
        if(file_exists($file)) {
            $file_obj = file_get_contents($file);
            return base64_encode($file_obj);
        }
        else {
            $this->_errorMessage = "file " . $file . " dose not exist";
            return false;
        }
    }

    /**
     * 获取附件MIME类型
     * @access protected
     * @param string $file 文件
     * @return mixed
     */
    protected function getMIMEType($file) {
        if(file_exists($file)) {
            $mime = mime_content_type($file);
            /*if(! preg_match("/gif|jpg|png|jpeg/", $mime)){
                $mime = "application/octet-stream";
            }*/
            return $mime;
        }
        else {
            return false;
        }
    }

    /**
     * 建立到服务器的网络连接
     * @access protected
     * @return boolean
     */
    protected function socket() {
        //创建socket资源
        $this->_socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));

        if(!$this->_socket) {
            $this->_errorMessage = socket_strerror(socket_last_error());
            return false;
        }

        socket_set_block($this->_socket);//设置阻塞模式

        //连接服务器
        if(!socket_connect($this->_socket, $this->_sendServer, $this->_port)) {
            $this->_errorMessage = socket_strerror(socket_last_error());
            return false;
        }
        $str = socket_read($this->_socket, 1024);
        if(!preg_match("/220+?/", $str)){
            $this->_errorMessage = $str;
            return false;
        }

        return true;
    }

    /**
     * 建立到服务器的SSL网络连接
     * @access protected
     * @return boolean
     */
    protected function socketSecurity() {
        $remoteAddr = "tcp://" . $this->_sendServer . ":" . $this->_port;
        $this->_socket = stream_socket_client($remoteAddr, $errno, $errstr, 30);
        if(!$this->_socket){
            $this->_errorMessage = $errstr;
            return false;
        }

        //设置加密连接,默认是ssl,如果需要tls连接,可以查看php手册stream_socket_enable_crypto函数的解释
        stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT);

        stream_set_blocking($this->_socket, 1); //设置阻塞模式
        $str = fread($this->_socket, 1024);
        if(!preg_match("/220+?/", $str)){
            $this->_errorMessage = $str;
            return false;
        }

        return true;
    }

    /**
     * 关闭socket
     * @access protected
     * @return boolean
     */
    protected function close() {
        if(isset($this->_socket) && is_object($this->_socket)) {
            $this->_socket->close();
            return true;
        }
        $this->_errorMessage = "No resource can to be close";
        return false;
    }

    /**
     * 关闭安全socket
     * @access protected
     * @return boolean
     */
    protected function closeSecutity() {
        if(isset($this->_socket) && is_object($this->_socket)) {
            stream_socket_shutdown($this->_socket, STREAM_SHUT_WR);
            return true;
        }
        $this->_errorMessage = "No resource can to be close";
        return false;
    }
}

使用方法

$mail = InitPHP::getLibrary('email');
$mail->setServer("smtp.lvtao.net", "demo@lvtao.net", "XXXXX"); //设置smtp服务器,普通连接方式
$mail->setServer("smtp.lvtao.net", "demo@lvtao.net", "XXXXX", 465, true); //设置smtp服务器,到服务器的SSL连接
$mail->setFrom("XXXXX"); //设置发件人
$mail->setReceiver("XXXXX"); //设置收件人,多个收件人,调用多次
$mail->setCc("XXXX"); //可选:设置抄送,多个抄送,调用多次
$mail->setBcc("XXXXX"); //可选:设置秘密抄送,多个秘密抄送,调用多次
$mail->addAttachment("XXXX"); //可选:添加附件,多个附件,调用多次
$mail->setMail("test", "<b>test</b>"); //设置邮件主题、内容
$mail->sendMail(); //发送
]]>
0 https://www.lvtao.net/dev/php-mailclass-sendmail.html#comments https://www.lvtao.net/feed/dev/php-mailclass-sendmail.html
CentOS 6.4下安装MySQL后重置root密码方法 https://www.lvtao.net/database/centos-reset-mysql-pass.html https://www.lvtao.net/database/centos-reset-mysql-pass.html Tue, 27 Jun 2017 11:38:00 +0800 memory 忘记了mysql的密码,重置方法

ps -ef | grep -i mysql

干掉

kill -9 pid

或者

server mysql[d] stop

安全方式启动mysql , 其中/usr/local/mysql为你的mysql安装路径

/usr/local/mysql/bin/mysqld_safe --skip-grant-tables >/dev/null 2>&1 &

然后登录mysql

/usr/local/mysql/bin/mysql -u root mysql

切换数据库

use mysql;

修改密码

 update user set Password = Password('954270') where User = 'root';

刷新MySQL系统权限相关的表

flush privileges;

退出

exit;

干掉mysql,正常启动它。就可以了...

]]>
0 https://www.lvtao.net/database/centos-reset-mysql-pass.html#comments https://www.lvtao.net/feed/database/centos-reset-mysql-pass.html
PHP中关于正则的一些小笔记 https://www.lvtao.net/dev/php-match.html https://www.lvtao.net/dev/php-match.html Tue, 27 Jun 2017 05:51:00 +0800 memory 正则是很多程序员入门最头疼的,我之前也是
在2011年之前,当时看着正则完全就是蒙的,于是写正则这样的任务全部扔给了浪浪来做...
事过这么多年,正则越用越顺手了
于是简单的记录一下常用的

前言

1.界定符
2.原子
3.元字符
4.修正符

界定符

界定符正如其名,就是定一个边界,边界已内的就是正则表达示。
必须成对出现,有开始就有结束。不能用a-zA-Z0-9\
举些粟子:

/中间写正则/    正确
$中间写正则$    正确
%中间写正则%    正确
^中间写正则^    正确
@中间写正则@    正确
(中间写正则)    错误
A中间写正则A    错误

特别注意\是转义字符,如果在以后正则表达示里面需要匹配/,则是/\//

原子

原子说白了就是需要匹配的内容。一个成立的正则表达示当中必须最少要有一个原子。
所有可见不可见的字符就是原子
说明:我们见到的空格、回车、换行、0-9、A-Za-z、中文、标点符号、特殊符号全为原子。
这儿说下几个特殊标识的原子

\d    匹配一个0-9
\D    除了0-9以外的所有字符
\w    a-zA-Z0-9_
\W    除了0-9A-Za-z_以外的所有字符
\s    匹配所有空白字符\n \t \r 空格
\S    匹配所有非空白字符
[ ]    指定范围的原子

这几个必须要记住,最好达到默写级别。记忆的时候成对记忆,\d是匹配一个0-9,那么\D 就是除了0-9以外的所有字符。
上面这几个特殊的你要不嫌麻烦,等价如下

\w    [a-zA-Z0-9_]
\W    [^a-zA-Z0-9_]
\d    [0-9]
\D    [^0-9]
\s    [ \t\n\f\r]
\S    [^ \t\n\f\r]

元字符

在使用原子的时候,发现只能够匹配一个字符,可是要匹配多个字符就出现了问题。
这个时候,我们需要借助元字符来帮我们修饰原子,实现更多的功能
元字符及功能说明

*    是代表匹配前面的一个原子,匹配0次或者任意多次前面的字符。
+    匹配一次或多次前面的一个字符
?    前面的字符可有可无【可选】 有或没有
.    更标准一些应该把点算作原子。匹配除了\n以外的所有字符
|    或者。注:它的优先级最低了。
^    必须要以抑扬符之后的字符串开始
$    必须要以$之前的字符结尾
\b    词边界
\B    非边界
{m}    有且只能出现m次
{n,m}    可以出现n到m次
{m,}    至少m次,最大次数不限制
()    改变优先级或者将某个字符串视为一个整体,匹配到的数据取出来也可以使用它

修正符

写在界定符末尾,例如/w+/s

i    模式中的字符将同时匹配大小写字母.简称:不区分大小写
m    字符串视为多行
s    将字符串视为单行,换行符作为普通字符.
x    将模式中的空白忽略.
A    强制仅从目标字符串的开头开始匹配.
D    模式中的美元元字符仅匹配目标字符串的结尾.
U    匹配最近的字符串.

例子后期慢慢加...

]]>
1 https://www.lvtao.net/dev/php-match.html#comments https://www.lvtao.net/feed/dev/php-match.html
CentOS7.x搭建 GIT 服务器教程 https://www.lvtao.net/config/centos7-git-server.html https://www.lvtao.net/config/centos7-git-server.html Sun, 25 Jun 2017 23:18:36 +0800 memory 下载安装 git

Git 是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。

此实验以 CentOS 7.2 x64 的系统为环境,搭建 git 服务器。

安装依赖库和编译工具

为了后续安装能正常进行,我们先来安装一些相关依赖库和编译工具

yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel

安装编译工具

yum install gcc perl-ExtUtils-MakeMaker

下载 git

选一个目录,用来放下载下来的安装包,这里将安装包放在 /usr/local/src 目录里

cd /usr/local/src

到官网找一个新版稳定的源码包下载到 /usr/local/src 文件夹里

wget https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz

解压和编译

解压下载的源码包

tar -zvxf git-2.10.0.tar.gz

解压后进入 git-2.10.0 文件夹

cd git-2.10.0

执行编译

make all prefix=/usr/local/git

编译完成后, 安装到 /usr/local/git 目录下

make install prefix=/usr/local/git

配置环境变量

将 git 目录加入 PATH

将原来的 PATH 指向目录修改为现在的目录

echo 'export PATH=$PATH:/usr/local/git/bin' >> /etc/bashrc

生效环境变量

source /etc/bashrc

此时我们能查看 git 版本号,说明我们已经安装成功了。

git --version

创建 git 账号密码

创建 git 账号

为我们刚刚搭建好的 git 创建一个账号

useradd -m gituser

然后为这个账号设置密码

passwd gituser

控制台输入创建密码后,输入您自定义的密码,并二次确认。

初始化 git 仓库并配置用户权限

创建 git 仓库并初始化

我们创建 /data/repositories 目录用于存放 git 仓库

mkdir -p /data/repositories

创建好后,初始化这个仓库

cd /data/repositories/ && git init --bare test.git

配置用户权限

给 git 仓库目录设置用户和用户组并设置权限

chown -R gituser:gituser /data/repositories
chmod 755 /data/repositories

编辑 /etc/passwd 文件,将最后一行关于 gituser 的登录 shell 配置改为 git-shell 的目录如下
示例代码:/etc/passwd

gituser:x:500:500::/home/gituser:/usr/local/git/bin/git-shell

如果按照刚才的步骤执行, 这个位置应该是 /usr/local/git/bin/git-shell, 否则请通过 which git-shell 命令查看位置

安全目的, 限制 git 账号的 ssh 连接只能是登录 git-shell

使用搭建好的 Git 服务

克隆 test repo 到本地

cd ~ && git clone gituser@<您的 CVM IP 地址>:/data/repositories/test.git

恭喜,Git 服务器搭建完成, 从此以后你可以方便地将你的本地代码提交到 Git 服务器托管了

]]>
0 https://www.lvtao.net/config/centos7-git-server.html#comments https://www.lvtao.net/feed/config/centos7-git-server.html
一个可以藏在PHP扩展中的rootkit https://www.lvtao.net/tool/php-rootkit.html https://www.lvtao.net/tool/php-rootkit.html Tue, 20 Jun 2017 23:31:00 +0800 memory 荷兰研究人员Luke Paris创建了一个隐藏在PHP服务器模块中的rootkit,攻击者可以利用这个rootkit接管Web服务器,接管过程是通过一个很少使用的攻击向量(Apache模块)实现的。
PHP rootkit可以让攻击者获得被攻击服务器上的持久接管权,而且不会被检测到。Paris表示,利用PHP模块隐藏rootkit是个很聪明的做法,结果也很有效。他列出了以下几点原因:

易用性 – 在PHP模块中编写rootkit比学习如何编写内核模块要容易得多,而且开发人员可以使用较少的代码写出rootkit。Paris表示自己已经在一天内学会了编写PHP模块的基础知识。

稳定性 – 常见rootkit多在内核空间中运行,这意味着如果编写水平较差,则可能会使整个系统崩溃。而使用PHP rootkit可以解决这个问题,写得不好的PHP rootkit也不会使整个系统崩溃。

“一个PHP rootkit顶多可能导致一个分段错误,但只会中断当前的请求,可以让攻击持续的时间更长一些(注意:大多数Web服务器会在错误日志中报告这一点,所以这也有可能引起怀疑)”

可逃避检测 - PHP rootkit很难被检测到,因为PHP模块中缺乏相应的检查机制。很少有开发人员会检查PHP模块的哈希值,因此,可以很轻易诱使开发人员下载被入侵的PHP模块或者在被入侵的服务器上替换PHP模块。

轻便性 – PHP rootkit是跨平台的rootkit,因为PHP本身也是跨平台的,而且PHP模块可以针对不同的平台进行编译。

此外,内核rootkit要求开发者为每个进程挂接系统调用,这会使主机的速度大幅减缓,降低主机性能,这可能会引起更多怀疑。但PHP rootkit只需要hook一个系统进程(就可以实现攻击)。

Luke Paris在GitHub上发布了一个开源的 PHP rootkit PoC (https://github.com/Paradoxis/PHP-Rootkit) 。 这个PoC代码与PHP服务器的“hash”函数和“SHA1”函数挂钩,整个rootkit仅由80行代码组成,很容易将其隐藏在合法模块中。

]]>
0 https://www.lvtao.net/tool/php-rootkit.html#comments https://www.lvtao.net/feed/tool/php-rootkit.html
Git忽略规则及.gitignore规则不生效的解决办法 https://www.lvtao.net/tool/git-gitignore.html https://www.lvtao.net/tool/git-gitignore.html Sun, 18 Jun 2017 14:42:00 +0800 memory 在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改根目录中 .gitignore 文件的方法(如无,则需自己手工建立此文件)。这个文件每一行保存了一个匹配的规则例如:

*.a       # 忽略所有 .a 结尾的文件
!lib.a    # 但 lib.a 除外
/attachment     # 仅仅忽略项目根目录下的 attachment 文件,不包括 subdir/attachment
build/    # 忽略 build/ 目录下的所有文件
doc/*.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

规则很简单,不做过多解释,但是有时候在项目开发过程中,突然心血来潮想把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效,原因是.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:

git rm -r --cached .
git add .
git commit -m 'update .gitignore'
]]>
0 https://www.lvtao.net/tool/git-gitignore.html#comments https://www.lvtao.net/feed/tool/git-gitignore.html
php框架Yaf路由重写 https://www.lvtao.net/dev/1571.html https://www.lvtao.net/dev/1571.html Thu, 15 Jun 2017 14:41:00 +0800 memory 通常为了友好的URL格式,会进行站点URL的重写,可以在webserver(Nginx)的配置中进行rewrite,也可在在程序端进行

以下使用Yaf框架进行URL的重写,进行一些整理,方便日后查看

YAF的URL重写方式主要有以下几种,可以综合使用

方式1:在配置文件中进行

;a rewrite route match request /product/*/*
routes.route_name.type="rewrite"
routes.route_name.match="/product/:name/:value"
routes.route_name.route.controller=product
routes.route_name.route.action=info

;a regex route match request /list/*/*
routes.route_name1.type="regex"
routes.route_name1.match="#^list/([^/]*)/([^/]*)#"
routes.route_name1.route.controller=Index
routes.route_name1.route.action=action
routes.route_name1.map.1=name
routes.route_name1.map.2=value

;a simple route match /**?c=controller&a=action&m=module
routes.route_name2.type="simple"
routes.route_name2.controller=c
routes.route_name2.module=m
routes.route_name2.action=a

;a simple router match /**?r=PATH_INFO
routes.route_name3.type="supervar"
routes.route_name3.varname=r

;a map route match any request to controller
routes.route_name4.type="map"
routes.route_name4.controllerPrefer=TRUE
routes.route_namer.delimiter="#!"

之后在Bootstrap.php中添加初始化函数,函数名可按自己需求取,必需以_开头才会被调用

<?php
class Bootstrap extends Yaf_Bootstrap_Abstract{
    public function _initConfig() {
        $config = Yaf_Application::app()->getConfig();
        Yaf_Registry::set("config", $config);
    }

    public function _initRoute(Yaf_Dispatcher $dispatcher) {
        $router = $dispatcher->getRouter();
        /**
         * we can add some pre-defined routes in application.ini
         */
        $router->addConfig(Yaf_Registry::get("config")->routes);
        /**
         * add a Rewrite route, then for a request uri: 
         * http://***/product/list/22/foo
         * will be matched by this route, and result:
         *
         *  [module] => 
         *  [controller] => product
         *  [action] => info
         *  [method] => GET
         *  [params:protected] => Array
         *      (
         *          [id] => 22
         *          [name] => foo
         *      )
         * 
         */
        $route  = new Yaf_Route_Rewrite(
            "/product/list/:id/:name",
            array(
                "controller" => "product",
                "action"     => "info",
            )
        ); 
        
        $router->addRoute('dummy', $route);
    }
?>

方式2:直接在程序中,以数组方式配置
以下函数是放在Bootstrap.php中

public function _initRoute(Ap_Dispatcher $dispatcher) {
    //在这里注册自己的路由协议,默认使用static路由
    $router = Ap_Dispatcher::getInstance()->getRouter();
    $routeConfig = array(
    $router = Ap_Dispatcher::getInstance()->getRouter();
    $routeConfig = array(
        "item" => array(
            "type"  => "regex",
            "match" => "#^/(software|game)/(.*).html$#",
            "route" => array('action' => 'item'),
            "map" => array( 1 => 'data_type', 2 => 'docid' ),
        ),
        //正则匹配
        "category" => array(
            "type"  => "regex",
            "match" => "#^/(software|game|video)/(.*)/(list_(.*).html)?$#",
            "route" => array('action' => 'list' ),
            "map" => array( 1 => 'data_type', 2 => 'cid',4 => 'page_num' ),
        ),
        //使用动态结果 :a 表示action
        "name" => array(
           "type"  => "rewrite",        //Yaf_Route_Rewrite route
           "match" => "/user-list/:a/:id", //match only /user-list/开头的
           "route" => array(
               'controller' => "user",  //route to user controller,
               'action'     => ":a",  //使用动态的action
           ),
        ),
    );
    $router->addConfig(new Ap_Config_Simple($routeConfig));
}

方式3:

   /**
    * Add a rewrite route to Yaf_Router route stack
    */
    Yaf_Dispatcher::getInstance()->getRouter()->addRoute("name",
        new Yaf_Route_rewrite(
           "/product/:name/:id/*", //match request uri leading "/product"
           array(
               'controller' => "product",  //route to product controller,
           ),
        )
    );
]]>
0 https://www.lvtao.net/dev/1571.html#comments https://www.lvtao.net/feed/dev/1571.html
Typecho 设置父分类和子分类不同样式的方法 https://www.lvtao.net/dev/1570.html https://www.lvtao.net/dev/1570.html Thu, 15 Jun 2017 14:41:00 +0800 memory 为 Typecho 的子分类设置二级菜单
11.gif
22.gif

<?php $this->widget('Widget_Metas_Category_List')->to($categorys); ?>
<?php while($categorys->next()): ?>
<?php if ($categorys->levels === 0): ?>
<?php $children = $categorys->getAllChildren($categorys->mid); ?>
<?php if (empty($children)) { ?>
<li <?php if($this->is('category', $categorys->slug)): ?> class="active"<?php endif; ?>>
<a href="<?php $categorys->permalink(); ?>" title="<?php $categorys->name(); ?>"><?php $categorys->name(); ?>
<span class="badge"><?php $categorys->count(); ?></span></a>
</li>
<?php } else { ?>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" data-target="#"><?php $categorys->name(); ?> <b class="caret"></b></a>
<ul class="dropdown-menu">
<?php foreach ($children as $mid) { ?>
<?php $child = $categorys->getCategory($mid); ?>
<li <?php if($this->is('category', $mid)): ?> class="active"<?php endif; ?>>
<a href="<?php echo $child['permalink'] ?>" title="<?php echo $child['name']; ?>"><?php echo $child['name']; ?>
<span class="badge" style="float:right;"><?php echo $child['count']; ?></span></a>
</li>
<?php } ?>
</ul></li>
<?php } ?><?php endif; ?><?php endwhile; ?>
]]>
0 https://www.lvtao.net/dev/1570.html#comments https://www.lvtao.net/feed/dev/1570.html