微信小程序navigator组件传递参数

QQ截图20180512103131.png



在做一个项目的时候发现URL传参的话会出现“乱码”。后来想想觉得实际挺有意思。首先这个传参的方法实际是http的get传参。所以url在分享的时候会变成URL编码。这样的话中文需要解码。


在JavaScript里面有这么一个函数:decodeURIComponent

decodeURIComponent(URIstring)


URIstring就是需要解码的文本。

java 绕过ssl访问webservice

private static void trustAllHttpsCertificates() throws Exception {
    javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
    javax.net.ssl.TrustManager tm = new miTM();
    trustAllCerts[0] = tm;
    javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, null);
    javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
static class miTM implements javax.net.ssl.TrustManager, javax.net.ssl.X509TrustManager {
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }
    public boolean isServerTrusted(java.security.cert.X509Certificate[] certs) {
        return true;
    }
    public boolean isClientTrusted(java.security.cert.X509Certificate[] certs) {
        return true;
    }
    public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
        throws java.security.cert.CertificateException {
        return;
    }
    public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
        throws java.security.cert.CertificateException {
        return;
    }
}


在你要

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

以前,运行下面几行代码:

trustAllHttpsCertificates();
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
    return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);

所包含的包:

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;


另一种方法

SSLSocketFactory.getSocketFactory().setHostnameVerifier(new AllowAllHostnameVerifier());


ECSHOP 配送插件二次开发

昨天网上找单位,一家单位问我会不会ecshop,直接“凉凉”。于是来研究下吧。首先安装很简单,在官网下载即可,这里有个小技巧,官网下载需要登录,但是仔细查看URL会发现下载地址直接给出了。所以直接截取就好了。下载地址如下:

ECSHOP3.0下载地址:http://update.shopex.com.cn/version/program/ECShop/download_ecshop_300.php

ECSHOP2.7下载地址:http://download.ecshop.com/2.7.3/ECShop_V2.7.3_UTF8_release1106.rar


ECSHOP安装

下载完之后是一个压缩包,直接全部解压到你的网站根目录即可。然后访问你的网站URL。会显示如下。

QQ截图20180503194519.png


这里是显示安装必须的一些信息,点击下一步开始配置系统。然后按要求填写后会出现如下图。


QQ截图20180503195026.png


全部成功以后,会出现下面这张需要注册云起的图,实际这个让你登录只是为了对接一些信息。

QQ截图20180503195133.png


这里我们只是研究只用,所以不需要,不用管。直接在访问你的网站URL。这时候就会出现你的ECSHOP了。


222.png


上图就是你的ECSHOP了。


ECSHOP配送插件开发

网上没有找到文档,于是只能大致看一下怎么写,如有错误还望指出。首先在后台找到配送插件的位置。

33.png

这里可以看到有一个第三方写的插件叫“中通快递”、我们先要找到它的实现代码。对着卸载或者安装或者设置区域等等位置,点击鼠标右键点击审查元素。可以看到如下JavaScript代码:

<a href="javascript:confirm_redirect(lang_removeconfirm,'shipping.php?act=uninstall&amp;code=zto')">卸载</a>

可以看到有一个实现php:shipping.php。这个文件位于:admin/shipping.php。看一下这个的实现代码:

首先要遍历:$modules = read_modules('../includes/modules/shipping');这个文件。所以我们可以参考一下其中已经编写完毕的代码(下面是中通的):

<?php
/**
 * ECSHOP 中通速递插件
 * ============================================================================
 * * 版权所有 2005-2012 上海商派网络科技有限公司,并保留所有权利。
 * 网站地址: http://www.ecshop.com;
 * ----------------------------------------------------------------------------
 * 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和
 * 使用;不允许对程序代码以任何形式任何目的的再发布。
 * ============================================================================
 * $Author: liubo $
 * $Id: zto.php 17217 2011-01-19 06:29:08Z liubo $
*/
$shipping_lang = ROOT_PATH.'languages/' .$GLOBALS['_CFG']['lang']. '/shipping/zto.php';
if (file_exists($shipping_lang))
{
    global $_LANG;
    include_once($shipping_lang);
}
/* 模块的基本信息 */
if (isset($set_modules) && $set_modules == TRUE)
{
    include_once(ROOT_PATH . 'languages/' . $GLOBALS['_CFG']['lang'] . '/admin/shipping.php');
    $i = (isset($modules)) ? count($modules) : 0;
    /* 配送方式插件的代码必须和文件名保持一致 */
    $modules[$i]['code']    = 'zto';
    
    $modules[$i]['version'] = '1.0.0';
    /* 配送方式的描述 */
    $modules[$i]['desc']    = 'zto_desc';
    /* 是否支持保价 */
    $modules[$i]['insure']  = '2%';
    /* 配送方式是否支持货到付款 */
    $modules[$i]['cod']     = false;
    /* 插件的作者 */
    $modules[$i]['author']  = '蓝色黯然';
    /* 插件作者的官方网站 */
    $modules[$i]['website'] = 'http://www.ecshop.com';
    /* 配送接口需要的参数 */
    $modules[$i]['configure'] = array(
                                    array('name' => 'item_fee',     'value'=>15),    /* 单件商品配送的价格 */
                                    array('name' => 'base_fee',    'value'=>10),    /* 1000克以内的价格 */
                                    array('name' => 'step_fee',     'value'=>5),    /* 续重每1000克增加的价格 */
                                );
    /* 模式编辑器 */
    $modules[$i]['print_model'] = 2;
    /* 打印单背景 */
    $modules[$i]['print_bg'] = '/images/receipt/dly_zto.jpg';
   /* 打印快递单标签位置信息 */
    $modules[$i]['config_lable'] = 't_shop_province,' . $_LANG['lable_box']['shop_province'] . ',116,30,296.55,117.2,b_shop_province||,||t_customer_province,' . $_LANG['lable_box']['customer_province'] . ',114,32,649.95,114.3,b_customer_province||,||t_shop_address,' . $_LANG['lable_box']['shop_address'] . ',260,57,151.75,152.05,b_shop_address||,||t_shop_name,' . $_LANG['lable_box']['shop_name'] . ',259,28,152.65,212.4,b_shop_name||,||t_shop_tel,' . $_LANG['lable_box']['shop_tel'] . ',131,37,138.65,246.5,b_shop_tel||,||t_customer_post,' . $_LANG['lable_box']['customer_post'] . ',104,39,659.2,242.2,b_customer_post||,||t_customer_tel,' . $_LANG['lable_box']['customer_tel'] . ',158,22,461.9,241.9,b_customer_tel||,||t_customer_mobel,' . $_LANG['lable_box']['customer_mobel'] . ',159,21,463.25,265.4,b_customer_mobel||,||t_customer_name,' . $_LANG['lable_box']['customer_name'] . ',109,32,498.9,115.8,b_customer_name||,||t_customer_address,' . $_LANG['lable_box']['customer_address'] . ',264,58,499.6,150.1,b_customer_address||,||t_months,' . $_LANG['lable_box']['months'] . ',35,23,135.85,392.8,b_months||,||t_day,' . $_LANG['lable_box']['day'] . ',24,23,180.1,392.8,b_day||,||';
    return;
}
class zto
{
    /*------------------------------------------------------ */
    //-- PUBLIC ATTRIBUTEs
    /*------------------------------------------------------ */
    /**
     * 配置信息
     */
    var $configure;
    /*------------------------------------------------------ */
    //-- PUBLIC METHODs
    /*------------------------------------------------------ */
    /**
     * 构造函数
     *
     * @param: $configure[array]    配送方式的参数的数组
     *
     * @return null
     */
    function zto($cfg = array())
    {
        foreach ($cfg AS $key=>$val)
        {
            $this->configure[$val['name']] = $val['value'];
        }
    }
    /**
     * 计算订单的配送费用的函数
     *
     * @param   float   $goods_weight   商品重量
     * @param   float   $goods_amount   商品金额
     * @param   float   $goods_number   商品件数
     * @return  decimal
     */
    function calculate($goods_weight, $goods_amount, $goods_number)
    {
        if ($this->configure['free_money'] > 0 && $goods_amount >= $this->configure['free_money'])
        {
            return 0;
        }
        else
        {
            @$fee = $this->configure['base_fee'];
            $this->configure['fee_compute_mode'] = !empty($this->configure['fee_compute_mode']) ? $this->configure['fee_compute_mode'] : 'by_weight';
            if ($this->configure['fee_compute_mode'] == 'by_number')
            {
                $fee = $goods_number * $this->configure['item_fee'];
            }
            else
            {
                if ($goods_weight > 1)
                {
                    $fee += (ceil(($goods_weight - 1))) * $this->configure['step_fee'];
                }
            }
            return $fee;
        }
    }
    /**
     * 查询发货状态
     *
     * @access  public
     * @param   string  $invoice_sn     发货单号
     * @return  string
     */
    function query($invoice_sn)
    {
        $str = '<form style="margin:0px" methods="post" '.
            'action="http://www.zto.cn/bill.asp" name="queryForm_' .$invoice_sn. '" target="_blank">'.
            '<input type="hidden" name="ID" value="' .str_replace("<br>","\n",$invoice_sn). '" />'.
            '<a href="javascript:document.forms[\'queryForm_' .$invoice_sn. '\'].submit();">' .$invoice_sn. '</a>'.
            '<input type="hidden" name="imageField.x" value="26" />'.
            '<input type="hidden" name="imageField.x" value="43" />'.
            '</form>';
        return $str;
    }
    /**
     * 计算保价费用
     * 保价费不低于100元,保价金额不得高于10000元,保价金额超过10000元的,超过的部分无效
     * @access  public
     * @param   int     $goods_amount       保价费用
     * @param   int     $insure             保价比例
     *
     * @return void
     */
    function calculate_insure ($goods_amount, $insure)
    {
        if ($goods_amount > 10000)
        {
            $goods_amount = 10000;
        }
        $fee = $goods_amount * $insure;
        if ($fee < 100)
        {
            $fee = 100;
        }
        return $fee;
    }
}
?>


基本上只是填充一些信息,定义一个类对象。但是其中有一些表单位置定位信息这个教大家如何找一下,还是在shipping里面找,下面有一个操作数据库的代码。

    //保存
    $sql = "UPDATE " .$ecs->table('shipping'). " SET print_bg = '$src' WHERE shipping_id = '$shipping_id'";
    $res = $db->query($sql);

可以看到在shipping这个表里面的config_lable里面的数据。

QQ截图20180504153336.png


其中就有定位坐标,但是有些中文是用的变量代替的,这些变量如下:

    [lable_box] => Array
        (
            [shop_country] => 网店-国家
            [shop_province] => 网店-省份
            [shop_city] => 网店-城市
            [shop_name] => 网店-名称
            [shop_district] => 网店-区/县
            [shop_tel] => 网店-联系电话
            [shop_address] => 网店-地址
            [customer_country] => 收件人-国家
            [customer_province] => 收件人-省份
            [customer_city] => 收件人-城市
            [customer_district] => 收件人-区/县
            [customer_tel] => 收件人-电话
            [customer_mobel] => 收件人-手机
            [customer_post] => 收件人-邮编
            [customer_address] => 收件人-详细地址
            [customer_name] => 收件人-姓名
            [year] => 年-当日日期
            [months] => 月-当日日期
            [day] => 日-当日日期
            [order_no] => 订单号-订单
            [order_postscript] => 备注-订单
            [order_best_time] => 送货时间-订单
            [pigeon] => √-对号
        )

获取这些变量的方法很简单,只要打印$_LANG就可以。打印方法如下:

echo "<pre>";print_r($_LANG);echo "<pre>";

将上述代码插入到配送插件里面的任意位置即可。

QQ截图20180504154630.png

cli在ssh(xshell)关闭后websocket无法连接

如果你用Xshell连接你服务器以后(SSH连接),输入PHP CLI命令运行起WebSocket代码。然后直接关闭Xshell。你会发现你的WebSocket无法连接了。只能重新登录服务器 Kill 掉进程,然后重启WebSocket。造成这个问题的原因可以参考:http://www.ruanyifeng.com/blog/2016/02/linux-daemon.html 介绍的比较详细。


解决这个问题需要使用tmux/screen/byobu只是其中一种方法,这种方法是保护你的会话,让会话一直存在下去。当然你也可以使用守护进程之类的方法。


在这里我是用的screen,安装方法如下:

1、如果你使用yum软件包管理工具:yum install screen
2、如果你使用APT软件包管理工具:apt-get install screen


然后直接运行 screen php s.php就可以了。

微信小程序WebSocket开发

QQ截图20180406191419.png


让我们来实现一个简单的微信小程序WebSocket。WebSocket是一种没有被规范化的网络协议,不过网络上又有文章说是2011年被国际化。不过不管怎么样它摆脱了Http的无状态特性。什么是无状态,我看文章的时候有句话好经典:“人生若只如初见”。这句话完美的诠释了无状态。而WebSocket可以建立一种双向通道,即客户端可以通过此通道(Tcp)与服务器相互沟通,而服务器也可以通过此通道(Tcp)实现与服务器的沟通。而不必等待客户端的请求后再沟通。


注意WebSocket是一种协议,所以你需要让你的服务器能够解析这个协议。由于是Tcp为底层的,所以解析这个协议主要是“握手”。由于我的后台采用PHP编写,所以主要讲一下PHP的WebSocket利用。这个搭建过程你可以参考:http://www.iwonmo.com/archives/1287.html


两点注意:1、使用php cli模式来运行你的WebSocket代码。2、new对象的时候要new swoole_websocket_server。


如果你看过搭建过程了的话,那么下面这段代码你并不陌生了。

$server = new swoole_websocket_server("0.0.0.0", 你的WebSocket端口);
$server->on('open', function (swoole_websocket_server $server, $request) {
    echo "server: handshake success with fd{$request->fd}\n";
});
$server->on('message', function (swoole_websocket_server $server, $frame) {
    echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
    $server->push($frame->fd, "this is server");
});
$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});
$server->start();

这里要注意你的nginx的反射端口,如果这个不会配置的话,可以留言。我将我的配置文档发送给你。

要实现微信小程序访问wss你还需要在你的微信小程序后台也就是微信的网站页面添加你的wss地址。这里的地址你可以通过nginx来设置,不过要注意要有ssl证书,这个证书你可以在阿里云申请。然后你可以新建你的小程序了。


注意swoole官网的一段话。

onRequest回调

swoole_websocket_server 继承自 swoole_http_server

  • 设置了onRequest回调,websocket服务器也可以同时作为http服务器

  • 未设置onRequest回调,websocket服务器收到http请求后会返回http 400错误页面

  • 如果想通过接收http触发所有websocket的推送,需要注意作用域的问题,面向过程请使用globalswoole_websocket_server进行引用,面向对象可以把swoole_websocket_server设置成一个成员属性


所以说如果你访问网址后出现400错误,不要惊慌。因为你查看request你会发现你并没有实现它。如果实现了就不会出现400。而是空白。

<?php
$server = new swoole_websocket_server("0.0.0.0", 你的WebSocket端口);
//握手完毕后回调函数
$server->on('open', function (swoole_websocket_server $server, $request) {
        echo "server: handshake success with fd{$request->fd}\n";
        // $server->push($request->fd, "this is server");
    });
//有消息到达时的回调函数
$server->on('message', function (swoole_websocket_server $server, $frame) {
        echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
        $server->push($frame->fd, "客户端消息:receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n");
        $server->push($frame->fd, "my server\n");
    });
//关闭时的一个回调
$server->on('close', function ($ser, $fd) {
        echo "client {$fd} closed\n";
    });
//协议头
$server->on('request', function (swoole_http_request $request, swoole_http_response $response) {
        global $server;//调用外部的server
        // $server->connections 遍历所有websocket连接用户的fd,给所有用户推送
        foreach ($server->connections as $fd) {
            $server->push($fd, $request->get['message']);
        }
    });
$server->start();

上述代码是我服务器的一段代码。可以看到首先New了一个swoole对象。然后接管了几个回调。注意的是swoole的websocket向客户端发送数据采用的是push而不是send。在来看一下微信小程序的JavaScript代码。

wx.connectSocket({
      url: 'wss://xxxxxx.com'
    })
    wx.onSocketOpen(function (res) {
      console.log('WebSocket连接已打开!')
      wx.sendSocketMessage({
        data: "aa"
      })
    })
    wx.onSocketMessage(function (res) {
      console.log('收到服务器内容:' + res.data)
      wx.closeSocket()
    })
    wx.onSocketClose(function (res) {
      console.log('WebSocket 已关闭!')
    })
    wx.onSocketError(function (res) {
      console.log('WebSocket连接打开失败,请检查!')
    })

基本上都是官网的代码。代码里的方法可以参考微信小程序官网的API文档来查看。我这里主要是发送了一个文本数据给swoole框架,然后框架解析出我的数据类型与数据相关的一些信息。这个在swoole的官网API有解释。

onMessage

当服务器收到来自客户端的数据帧时会回调此函数。

function onMessage(swoole_server $server, swoole_websocket_frame $frame)
  • $frame 是swoole_websocket_frame对象,包含了客户端发来的数据帧信息

  • onMessage回调必须被设置,未设置服务器将无法启动

  • 客户端发送的ping帧不会触发onMessage,底层会自动回复pong

swoole_websocket_frame

共有4个属性,分别是

  • $frame->fd,客户端的socket id,使用$server->push推送数据时需要用到

  • $frame->data,数据内容,可以是文本内容也可以是二进制数据,可以通过opcode的值来判断

  • $frame->opcode,WebSocket的OpCode类型,可以参考WebSocket协议标准文档

  • $frame->finish, 表示数据帧是否完整,一个WebSocket请求可能会分成多个数据帧进行发送(底层已经实现了自动合并数据帧,现在不用担心接收到的数据帧不完整)

$data 如果是文本类型,编码格式必然是UTF-8,这是WebSocket协议规定的

OpCode与数据类型

  • WEBSOCKET_OPCODE_TEXT = 0x1 ,文本数据

  • WEBSOCKET_OPCODE_BINARY = 0x2 ,二进制数据


小问题:如果会话关闭后,cli也关闭了。导致无法访问,你可以尝试下面这个方法:http://www.iwonmo.com/archives/1292.html


Swoole开发文档:https://wiki.swoole.com/wiki/page/397.html

微信小程序WebSocket开发文档:https://developers.weixin.qq.com/miniprogram/dev/api/network-socket.html


 

阿里云使用swoole

最近要写一个websocket程序,想来想去就用了swoole这个框架。于是在自己服务器上搭建一下。搭建过程如下。


由于swoole已经作为php的一个扩展,所以你可以直接使用:

pecl install swoole

这条命令安装,最后的结果如下显示

Build process completed successfully
Installing '.../swoole.so'
install ok: ...
configuration option "php_ini" is not set to php.ini location
You should add "extension=swoole.so" to php.ini


不过要想在php中使用,你还需要添加extension=swoole.so到你的php.ini文件当中。然后重启php。如果你不知道自己的php文件位置,可以使用如下命令

php -i |grep


添加完成之后你php -m后会发现,你的php已经集成了swoole扩展。然后测试一下:

<?php
$server = new swoole_websocket_server("0.0.0.0", 2563);
$server->on('open', function($server, $req) {
    echo "connection open: {$req->fd}\n";
});
$server->on('message', function($server, $frame) {
    echo "received message: {$frame->data}\n";
    $server->push($frame->fd, json_encode(["hello", "world"]));
});
$server->on('close', function($server, $fd) {
    echo "connection close: {$fd}\n";
});
$server->start();

将以上代码保存为php文件。例如为s.php。然后在输入命令:php s.php运行起这个php。然后直接访问ip:2563就会发现能够访问。只不过显示错误。


问题:

有的说端口无法访问,没有对外网映射。实际我看了一下阿里的安全组。

QQ截图20180405204055.png

你会发现实际全部打开了。很奇葩。但是仔细看了一下授权对象:0.0.0.0。于是就把

swoole_websocket_server

第一个函数的ip就换成了0.0.0.0,结果就可以了。你也可以看一下你服务器开启的端口对应的ip。你会发现也是0.0.0.0。

php 运算与变量引用

在加群的时候遇到一个问题:

$a=1;
$b=&$a;
$c=$b++ + ++$a;

问:$c=?如果你放倒ide里去做,那么很容易可以得到是4;不过具体是怎么实现的。这里随便说一说。

首先$b=&$a;。注意这里的&在php里是引用的意思,相当于取内存空间领空地址。也就是指针。所以操作$b也相当于操作$a。$b++ + ++$a;这里是运算符优先级的问题。首先$b++实际是$b先参与运算,然后再自增。后面一个++$a正好相反。也就是相当于$c=1+3。


Excel读写之一个编码思路问题

昨天晚上需要写一个Excel小工具来辅助自己工作。问题是这样的。

问题:

有这样一堆数据(格式如同excel格式):

QQ图片20180324212520.png

这样的数据大概有1000行。然后又有一个excel。需要将表中的数据填入到里面,具体的单元格如下。

QQ图片20180324212708.png

如要注意的是,每填完所有的单元格后自动新建另一个Excel,表1的数据继续往下遍历,继续将数据填充新的表格。


请问你会怎么写这个逻辑代码?

Android 计算标准差

public static float StandardDiviation(float[] x) {
    int m = x.length;
    float sum = 0;
    for (int i = 0; i < m; i++) {//求和
        sum += x[i];
    }
    float dAve = sum / m;//求平均值
    //修约平均值为2位小数  规范要求
    float dAve1 = RoundLib.rFloat(dAve, 2);
    dAve=dAve1;
    float dVar = 0;
    for (int i = 0; i < m; i++) {//求方差
        dVar += (x[i] - dAve) * (x[i] - dAve);
    }
    dVar/=m-1;
    double ret_sd = Math.sqrt(dVar);
    Log.e("b",String.valueOf(ret_sd).toString());
    BigDecimal b = new BigDecimal(String.valueOf(ret_sd));
    float fl = b.floatValue();
    b = null;
    return fl;
}


qemu 出错解决办法

运行qemu的时候提示134错误。百度搜索了一下发现没有这方面的解决文章。于是只能自己解决了。方法很简单,如下更改Graphics模式就可以了。

屏幕快照 2018-03-11 下午6.17.36.png

Android 调用系统文字分享

QQ图片20180309141506.png

实现代码如下:

Intent StringIntent = new Intent(Intent.ACTION_SEND);
StringIntent.setType("text/plain");
StringIntent.putExtra(Intent.EXTRA_TEXT, ShareStr);
this.startActivity(Intent.createChooser(StringIntent, "分享")); // 创建选择器

第一条语句:

Intent StringIntent = new Intent(Intent.ACTION_SEND);

这句话的意思是新建一个Intent类对象,注意这里给它传递了一个参数ACTION_SEND。

这一个参数类型是文本型(String)其具体数值为:"android.intent.action.SEND"。

官网解释:ACTION_SEND : Activity Action: Deliver some data to someone else.  意思大概是将一些数据提供给其它的App。

第二条语句:

StringIntent.setType("text/plain");

函数原型:

Intent setType(String type) 'Set an explicit MIME data type.

这句话的意思是设置MIME类型。MIME类型包括如下:

常见的MIME类型(通用型):
超文本标记语言文本 .html text/html
xml文档 .xml text/xml
XHTML文档 .xhtml application/xhtml+xml
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
PDF文档 .pdf application/pdf
Microsoft Word文件 .word application/msword
PNG图像 .png image/png
GIF图形 .gif image/gif
JPEG图形 .jpeg,.jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG文件 .mpg,.mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz application/x-gzip
TAR文件 .tar application/x-tar

我们这里要设置的意图类型是文本型,所以选择“text/plain”。但是要注意setType是区分大小写的。所以要特别注意一下。

第三条语句:

StringIntent.putExtra(Intent.EXTRA_TEXT, ShareStr);

putExtra是复写的函数,所以它有很多定义,有的是两个参数,有的是一个参数。有的第二个参数类型不一样。这个要注意一下。但是大致也可以看的出,第一个参数是定义你往意图(Intent)上附加(Extra)数据的类型。这里传入的参数是Intent.EXTRA_TEXT。很明显这是一个android提供的常量数据。

官网解释:EXTRA_TEXT:A constant CharSequence that is associated with the Intent, used with ACTION_SEND to supply the literal data to be sent.
(大致意思:与ACTION_SEND一起用于提供要发送的文字数据。)

第四条语句:

this.startActivity(Intent.createChooser(StringIntent, "分享"));

这一条语句相当简单,实际就是打开一个活动视图。注意这个视图是通过createChooser函数创建的,看名知意。这个函数是创建了一个选择器。第一个参数类型是Intent,第二个类似一个标题的文本型数据。


总结一下:首先新建一个意图类型。然后设置意图的附加数据类型(MIME类型)。第三步依照设置的数据类型添加数据。最后创建一个选择器,将意图分发出去。

特别注意:setType这个函数,在官网有这么一句话:This method automatically clears any data that was previously set (for example by setData(Uri)).

大致意思:此方法会清楚你前面所有设置的数据,例如用setData设置的Uri数据。所以这个函数的使用必须在putExtra前面。

Intent介绍http://android.xsoftlab.net/reference/android/content/Intent.html


Yii2使用方法

QQ截图20180301104601.png


YII2官网下载地址:http://www.yiiframework.com/download/ 首先进入官网下载最新的YII2源码。这里使用的版本是:yii-1.1.19.5790cb

一:生成目录结构

这里生成目录结构需要使用Yii自带的批处理文件。我们先来看一下。这个批处理的目录在:framework文件夹里。名字为:yiic.bat。用记事本打开代码如下:

@echo off
rem -------------------------------------------------------------
rem  Yii command line script for Windows.
rem
rem  This is the bootstrap script for running yiic on Windows.
rem
rem  @author Qiang Xue <qiang.xue@gmail.com>
rem  @link http://www.yiiframework.com/
rem  @copyright 2008 Yii Software LLC
rem  @license http://www.yiiframework.com/license/
rem  @version $Id$
rem -------------------------------------------------------------
@setlocal
set YII_PATH=%~dp0
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
"%PHP_COMMAND%" "%YII_PATH%yiic" %*
@endlocal

可以发现其中调用了PHP.exe,所以需要把php.exe加入到环境变量。或者你可以手动更改批处理文件php调用路径。加入环境变量方法:

path环境变量的位置:我的电脑->属性->高级->环境变量->系统变量->Path     变量名:Path


加入完成之后打开cmd,切换到Yii的framework文件夹里,输入yiic webapp ../app 这条命令主要是传递参数,利用yiic去创建目录结构。如下图

QQ截图20180301100714.png

可以看到是各种mkdir创建文件夹的指令,最后生成一些php文件。生成之后会在yii-1.1.19.5790cb文件夹里面多出一个app文件夹,并且app文件夹里面已经有了一个Simple工程。

QQ截图20180301100733.pngQQ截图20180301100752.png

各个文件夹的含义如下(每个版本可能略有不同):

app--------------------应用程序目录
  assets---------------第三方资源包*******
  css------------------样式表*******
  images---------------图片*******
  protected------------应用程序
    commands-----------系统命令
    components---------组件目录(自定义类)*******
      Controller.php---所有控制器的父类
    config-------------配置文件夹*******
      main.php---------全局配置文件
    controllers--------控制器*******
    data---------------数据库脚本*******
    extensions---------扩展类
    messages-----------翻译过的信息
    migrations---------数据库移植文件
    models-------------模型*******
    runtime------------运行时
    views--------------视图*******
      layouts----------布局文件夹
  themes---------------主题目录
  index.php------------入口文件
framework--------------yii资源包

二:访问

这个时候就可以直接访问app目录了,直接在浏览器输入地址定位到app目录,就会出现一个简单的网页程序。

QQ截图20180301101002.png

很漂亮的感觉,还不错。

三:修改默认控制器

应该都知道Yii2是mvc架构,所以我们可以修改它的默认控制器。路径在:app\protected\controllers里面的SiteController.php文件。这里直接新建一个同样的文件,取名IwonmoController.php控制器。注意控制器命名规则采用大驼峰方式。里面的内容我们照抄SiteController.php。只不过要把类名改一下,基类不要改。

QQ截图20180301105812.png

改成如下

QQ截图20180301105846.png

下面还要改一个地方,及配置文件。如果你不知道它的配置文件在哪里的话,你可以去看入口文件:index.php

<?php
// change the following paths if necessary
$yii=dirname(__FILE__).'/../framework/yii.php';
$config=dirname(__FILE__).'/protected/config/main.php';
// remove the following lines when in production mode
defined('YII_DEBUG') or define('YII_DEBUG',true);
// specify how many levels of call stack should be shown in each log message
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
require_once($yii);
Yii::createWebApplication($config)->run();

可以看到配置文件是在$config=dirname(__FILE__).'/protected/config/main.php';。这里,于是我们更改一下就好了。

QQ截图20180301110039.png

但是你如果访问的话,会报错。

w.png

这里看错误的样子是View没有找到,cannot find。因为我们要在Views目录下建立属于这个控制器的单独视图文件,并放到以控制器名字命名的文件夹里,如下图。

QQ截图20180301110334.png

然后你在访问一下,就会发现控制器已经更改了,如果效果不明显,你可以在默认方法里加入一句代码看一看。

echo "我是默认控制器显示的页面";

QQ截图20180301110458.png

然后在看网页效果。

QQ截图20180301110652.png


aop 横向切面编程

psb.png

外国人提倡的一种思想,不在采用线性编程,而是采用横向编程。采用交叉点与织入点编程。具体的思路如下。

1、创建一个接口
2、创建一个数据库类
3、创建好一个实现xml
4、获取bean
5、bean实现接口方法

一、 创建接口方法

package aoptomybatis;
import aoptomybatis.user;
public interface userdao {
public user getUser(int i); //定义dao接口
}

二、创建一个数据库类

package aoptomybatis; 
public class user { //实现接口返回操作
//这个名字必须和数据库一致
private int id;
    private String user;
    private String pass; 
 
    public String get() {
        return user;
    }    
}



三 、
创建好一个实现xml

<?xml version="1.0" encoding="UTF-8"?>
<beans  
    xmlns="http://www.springframework.org/schema/beans"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:p="http://www.springframework.org/schema/p"  
    xmlns:aop="http://www.springframework.org/schema/aop"   
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans   
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
    http://www.springframework.org/schema/tx   
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd   
    http://www.springframework.org/schema/aop    
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">  
     <!-- 让aop支持aspectj动态代理 -->
     <aop:aspectj-autoproxy />
<!-- 配置数据源-->  
    <bean id="jdbcDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    <property name="driverClassName">  
        <value>org.gjt.mm.mysql.Driver</value>  
    </property>  
    <property name="url">  
        <value>jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8</value>  
 
    </property>  
    <property name="username">  
        <value>root</value>  
    </property>  
    <property name="password">  
        <value>root</value>  
    </property>  
</bean>  
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
    <property name="dataSource" ref="jdbcDataSource" />  
    <property name="configLocation" value="mbtcon.xml"></property>  
</bean>  
<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">  
    <property name="mapperInterface" value="aoptomybatis.userdao"></property>  
    <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>  
</bean>  
</beans>



四、扫描mybatis的xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC  
    "-//mybatis.org//DTD Config 3.0//EN"  
    "http://mybatis.org/dtd/mybatis-3-config.dtd">  
<configuration>  
    <mappers>  
        <mapper resource="umap.xml"/>  
    </mappers>  
</configuration>



五、sql xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"   
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
<mapper namespace="aoptomybatis.userdao">
    <select id="getUser" parameterType="int" 
        resultType="aoptomybatis.user">
        select * from mbt where id=#{id}
    </select>
</mapper>



六、获取bean

package aoptomybatis;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class mybatis {
public static void main(String[] args) throws IOException {
ApplicationContext ctx=null;
        ctx=new ClassPathXmlApplicationContext("aopxml.xml");
userdao userDao=(userdao) ctx.getBean("userDao");
System.out.print(userDao.getUser(0).get()); //通过aop去获取
  
    }
}
 

官方网站

这个网站是给公司做的一个新闻类型的官网。很久了,也没具体的上线。听说是不会部署服务器。此效果是我在本地部署的样子。代码语言采用:PHP+MVC

QQ截图20180224203532.png

首页,一个轮播动画,几组新闻页面。

QQ截图20180224203636.png

文章阅读页面

QQ截图20180224202855.png后台文章编写

QQ截图20180224202912.png后台文章编写功能页面,可以选择发布的类型,并且可以上传图片决定是否在首页轮播动画显示。


对流量精灵的一份分析

流量精灵:http://www.spiritsoft.cn/


这类软件基本上都是“我为人人,人人为我”的原则,你帮我刷,我帮你刷。这么浅显的原则,我们还分析它什么?实际呢,我们分析它的是怎么去掉自己刷的这个功能,因为我们需要刷的网址都是从服务器获取的,如果说其中有什么恶意网址,让自己的电脑中毒了呢,这跟我们的初衷是有违背的。于是带着怎么取消这个功能的目的。来探究一下。只让它实现刷自己的网址,而不刷别人的网址。


版本:2016.3.20.103。最新的一份程序


首先用PEID查一下壳,由于我的PEID是从百度软件里面下载的,可能特征码库不是很全。所以没识别出来。

QQ截图20180224134252.png

看一下几个区段。

QQ截图20180224134258.png

都很正常,感觉没有加壳的样子。用ollydbg载入一下吧。注:ollydbg版本用的是吾爱破解的据说很强

QQ截图20180224134550.png

开头直接call了一个地址,算是直接运行了一个函数。开头直接call的。感觉只有net有这种怪样式。一般其他程序push ebp比较多。因为ebp是一个比较重要的寄存器,压栈后可以寻找参数什么的。但是如果是unicode编码格式的又另当别论了,所以直接搜索一下中文Unicode吧。

QQ截图20180224134822.png

有惊喜,有内容。看着是明文,那就是没加壳的可能性比较大。实际本文用ollydbg的机会很少,这里只是演示一下一般流程。


http代理型分析软件:fiddle


分析这类程序,直接用http拦截工具就行。但是发现fiddle会漏掉一下tcp形式的发送。所以不用fiddle了。用另一款HttpAnalyzerStdV7。基于TCP的拦截,更全,更强大。

QQ截图20180224135307.png

拦截到两个post。很关键。第一个post是将我们要刷的网址,还有类型发送给服务器。128b205这几个字符是随机的。

QQ截图20180224135333.png

上述内容就是post data


我们来看post之后它又干了什么。访问了一个网址:http://urlspirit.spiritsoft.cn/urlcore/olcfgs.dat?q=41   

注意这个网址是get方式,所以我们可以直接用浏览器去访问。是一段加密文件,可以猜测,基本上是先从这个文件获取到点什么然后才开始的大面积刷网页。