C++

‘3’-‘0’,才表示字符c和字符0的ASCALL码差值.char转int。

char c=3 + ‘0’ int转char。

SyntaxHighlighter测试 ghost

ghost博客使用SyntaxHighlighter时写一些c++的代码时。在引入头文件是要加入<>符号。但是ghost会吧<>当成标签转义。所以应该用&lt;&gt;代替<>,如#include <string.h>改成#include &lt;string.h&gt;最后,就能完美显示了。

#include "stdafx.h"
#include 
#include 
#include 
#include 

using namespace std;

int main(void) {

    const char * image = "2.png";

    tesseract::TessBaseAPI  api;

//    api.Init("D:\\tesseract\\tessdata", "chi_sim", tesseract::OEM_DEFAULT);
    api.Init("D:\\tesseract\\tessdata", "eng", tesseract::OEM_DEFAULT);
    api.SetVariable("tessedit_char_whitelist", "0123456789.");

    STRING text_out;
    if (!api.ProcessPages(image, NULL, 0, &text_out))
    {
        system("pause");
        return 0;
    }
    printf(text_out.string());
    system("pause");
}

xss字符串替换

function xssCheck(str,reg){

return str ? str.replace(reg ||/[&<”>]/g,function (a, b) {

return {

‘<’:’<’,

‘&’:’&’,

‘“‘:’”‘,

‘>’:’>’

}[a]

}): ‘’;

}

Binary Tree Level Order Traversal--leetcode

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector> levelOrder(TreeNode* root) {
        vector> res;
        if (root == NULL) { return res; }
        vector list;
        list.push_back(root);
        vector temp2;
        temp2.push_back(root->val);
        res.push_back(temp2);
        while (list.size()!=0)
        {
            vector temp;
            vector temp2;
            for (size_t i = 0; i < list.size(); i++)
            {
                if (list[i]->left!=NULL) {
                    temp.push_back(list[i]->left);
                    temp2.push_back(list[i]->left->val);
                }
                if (list[i]->right != NULL) {
                    temp.push_back(list[i]->right);
                    temp2.push_back(list[i]->right->val);
                }
            }
            list = temp;
            if(temp.size()!=0){
                res.push_back(temp2);
            }

        }
        return res;
    }
};

generate-parentheses--LeetCode

试下node的C/C++ Addons的性能。

题目见generate-parentheses

js

"use strict";
    console.time();    
var generateParenthesis = function(n) {
var arr=[];
function run(left,right,str){
    if(left>0){
        run(left-1,right,str+"(");
    }
    if(right>0&&left<right){
        run(left,right-1,str+")");
    }
    if(left===0&&right===0){
        arr.push(str);
    }

}
run(n-1,n,"(");
return arr;
};
console.log(generateParenthesis(15).length)
console.timeEnd();

node C/C++ Addons

#ifdef WIN32
#pragma execution_character_set("utf-8") //配合v8使用。
#endif
#include<iostream>
#include <node.h>
#include <vector>

namespace demo {
    //using namespace std;
    using v8::Exception;
    using v8::FunctionCallbackInfo;
    using v8::Isolate;
    using v8::Local;
    using v8::Number;
    using v8::Array;
    using v8::Object;
    using v8::String;
    using v8::Value;

    class Solution {
    public:
        inline void run(int left, int right, std::string &str, std::vector<std::string> &arr) {
            if (left>0) {
                str.push_back('(');
                run(left - 1, right, str, arr);
                str.pop_back();
            }
            if (right>0 && left<right) {
                str.push_back(')');
                run(left, right - 1, str, arr);
                str.pop_back();
            }
            if (left == 0 && right == 0) {
                arr.push_back(str);
            }
        }
        std::vector<std::string> generateParenthesis(int n) {
            std::vector<std::string> arr;
            arr.reserve(10000000);
            std::string str = "(";
            run(n - 1, n, str, arr);
            return arr;
        }
    };
    void Method(const FunctionCallbackInfo<Value>& args) {
        Isolate* isolate = args.GetIsolate();
        std::vector<std::string> arr;
        int n = (int)args[0]->NumberValue();
        Solution s;
        arr= s.generateParenthesis(n);
        Local<v8::Array> v8arr=    Array::New(isolate,arr.size());
        //args.GetReturnValue().Set(v8arr);
        for (size_t i = 0; i < arr.size(); i++)
        {
            v8arr->Set(i, v8::String::NewFromUtf8(isolate, arr[i].c_str()));
        }
        args.GetReturnValue().Set(v8arr);
    }

    void init(Local<Object> exports) {
        NODE_SET_METHOD(exports, "hello", Method);
    }

    NODE_MODULE(addon, init)

} 

结果

在输出n等于15时候,返回900W+条,字符串。这里一比发现,js主要4秒左右。C/C++ Addons要15秒。原来在

在把C++的vector对象转成js的Array时,耗了大量的时间。C++得到900W+条vector时,其实只花了2s+的时间。

注意

传引用,传值,性能差距还是蛮大的,这里C++代码string str传值,会比js慢。

不安全的target="_blank"

原理

点击有target=”_blank”属性的超链接后,浏览器会单独新建一个标签页来显示该链接所指向的内容。但是请注意,在这一瞬间,浏览器会允许新建的标签页通过一个名为“window.opener”的浏览器API来与之前的网页进行短暂通信。这时候,在新的标签页执行了window.opener.location.href=”xxx”。原标签页就会跳转到xxx。

如下

qc

利用

可以把原来的网页,跳转到钓鱼网页,提示,登录过期,请重新登录。用户很容易就泄漏了自己的密码。

修复问题

这也就意味着,修复该问题的重担将落在网站管理员的身上了。实际上,修复该问题最简单的方法就是在网站所有的链接中加入rel=”noopener”属性。对于火狐浏览器而言,由于它并不完全支持该属性,所以开发人员应该使用rel=”noopenernoreferrer”属性作为代替。

请记住,当你每次使用window.open()接口来打开一个新的网页窗口时,你的安全性很有可能会受到这一API的影响,所以别忘了重置“opener”属性。

var newWnd = window.open();
newWnd.opener = null;

原文

链接地址中的target=”_blank”属性,为钓鱼攻击打开了大门
console.log(1)

white-space、word-wrap和word-break区别

word-wrap: normal | break-word;

  • normal :会换行,但是单词长度超过width时不折行,产生溢出
  • break-word :单词超长时,会折行把剩余的单词折行显示。

word-break:normal | break-all | keep-all (词内换行)

  • normal:如果是中文则到边界处的汉字换行,如果是英文整个词换行,注意:如果出现某个英文字符串长度超过边界,则后面的部分将撑开边框,如果边框为固定属性,则后面部分将无法显示.
  • break-all :强行换行,将截断英文单词
  • keep-all :不允许字断开。如果是中文将把前后标点符号内的一个汉字短语整个换行,英文单词也整个换行,注意:如果出现某个英文.字符串长度超过边界,则后面的部分将撑开边框,如果边框为固定属性,则后面部分将无法显示.

white-space(优先级最高)

  • inherit :指其值继承父元素对应属性的计算值。
  • initial :指其值为原始的值。
  • normal :默认,浏览器忽略空白符
  • nowrap :文本不会换行,文本会在在同一行上继续,直到遇到
    标签为止。
  • pre-line:合并空白符,但是保留换行符。
  • pre-wrap:保留空白符,但是正常地进行换行。

text-overflow : clip | ellipsis

  • clip:而只是简单的裁切,需要在一定的高度范围内配合overflow:hidden属性使用.
  • ellipsis:对象文本溢出时将显示省略标记(…),需要配合overflow:hidden;white-space:nowrap起使用才会有效果。

Node的C/C++ Addons在VS下调试

下载

去GitHubs下载源码nodejs,这是最新的node源码。其他的版本到https://nodejs.org下载。

配置

  • 在源码根目录(我放在D:\node-master),打开命令行。输入vcbuild.bat nosign Debug x64,成功后会生成一些文件和文件夹。
  • 在工作目录打开控制台。输入node-gyp clean configure –nodedir=”D:\node-master”(nodejs源码根目录)
  • 这时工作目录出现一个build文件夹,下面有个bind.sln。双击vs就打开了这个解决方案。

在打开项目的属性,如下图配置,确定。

  • 点击调试,出现node的命令行。这里调用方法,vs中打断点就能断点调试了。

babel-polyfill使用

Babel默认只转换新的JavaScript语法,而不转换新的API,比如Iterator、Generator、Set、Map、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的es5,es6的新方法(比如Object.assign,Array.from)都不会转码。这时就要安装babel-polyfill。

install

npm install –save babel-polyfill

2 entry

entry:['babel-polyfill','app.js']//单入口

entry:{
   page1: ['babel-polyfill', "./js/page1.js"],   //多人口文件
   page2: ['babel-polyfill',"./js/page2.js"]
},

3 在需要用新api的前面require(“babel-polyfill”);

nodejs多进程

node.js是单线程,异步架构,无法却利用多个核心。当然也有通过tagg,可以实现多线程。不过我还是觉得多进程+异步更好用,更简单地实现多核心编程。

子进程 child_process模块

这个可以创建子线程

  • spawn函数用给定的命令发布一个子进程,只能运行指定的程序,参数需要在列表中给出,如下:

    var child_process = require(‘child_process’);
    var child = child_process.spawn( command );
    child.stdout.on(‘data’, function(data) {
    console.log(data);
    });

  • exec也是一个创建子进程的函数,与spawn函数不同它可以直接接受一个回调函数作为参数,回调函数有三个参数,分别是err, stdout , stderr,基本使用方法如下:

    var child_process = require(‘child_process’);
    child_process.exec( command , function(err, stdout , stderr ) {
    console.log( stdout );
    });

  • execFileexecFile函数与exec函数类似,但execFile函数更显得精简,因为它可以直接执行所指定的文件,基本使用方法如下:

    var child_process = require(‘child_process’);
    child_process.execFile( file , function(err, stdout , stderr ) {
    console.log( stdout );
    });

  • forkfork函数可直接运行Node.js模块,所以我们可以直接通过指定模块路径而直接进行操作。使用方法如下:

    var child_process = require(‘child_process’);
    child_process.fork( modulePath );

该方法实现ChildProcess实例所具有的所有方法,最主要的是他可以在进程间通信。

cluster

cluster是Nodejs自带的多核处理模块。封装的child_process.fork方法。

官方api

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`);
  });
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world\n');
  }).listen(8000);
}
//输出
$ NODE_DEBUG=cluster node server.js
23521,Master Worker 23524 online
23521,Master Worker 23526 online
23521,Master Worker 23523 online
23521,Master Worker 23528 online

webpack+browser-sync

browser-sync介绍

Browsersync能让浏览器实时、快速响应您的文件更改(html、js、css、sass、less等)并自动刷新页面。更重要的是 Browsersync可以同时在PC、平板、手机等设备下进项调试。您可以想象一下:“假设您的桌子上有pc、ipad、iphone、android等设备,同时打开了您需要调试的页面,当您使用browsersync后,您的任何一次代码保存,以上的设备都会同时显示您的改动”。

有了它,您不用在多个浏览器、多个设备间来回切换,频繁的刷新页面。更神奇的是您在一个浏览器中滚动页面、点击等行为也会同步到其他浏览器和设备中,这一切还可以通过可视化界面来控制。

配合webpack使用。

  • npm install –save-dev browser-sync

  • npm install –save-dev browser-sync-webpack-plugin

    var BrowserSyncPlugin = require(‘browser-sync-webpack-plugin’);
    plugins: [
    new BrowserSyncPlugin({

       // browse to http://localhost:3000/ during development
        host: 'localhost',
        port: 3000, //代理后访问的端口
        proxy: 'localhost:80',//要代理的端口
    },
      // plugin options
      {
        // prevent BrowserSync from reloading the page
        // and let Webpack Dev Server take care of this
        reload: true
      })

    ]

  • webpack –watch

成功后,访问localhost:3000

这是页面右上角显示

访问localhost:3001

显示browser-sync后台,这里有很多选项。

browser-sync 最嗨的是可以同步浏览器操作。

linux部署shadowsocks

  • 检查服务器下Python 版本,要有2.6 or 2.7。我用的ubuntu12,自带的就是2.7。

    python –version
    Python 2.7.3

  • 然后安装pip,python的软件包管理(这个好比node的npm)。python-gevent这个最好也要加上。

apt-get install python-gevent python-pip

  • 下一步用pip安装shadowsocks

pip install shadowsocks

  • 然后在任意位置新建一个json文件,如xxx.json编辑如下内容,保存。

    {

    "server":"server_ip",
    "server_port":23456,
    "local_address": "127.0.0.1",
    "local_port":3333,
    "password":"xxxx",
    "timeout":300,
    "method":"aes-256-cfb",
    "fast_open": true,
    "workers":1  //??????

    }

  • 最后,用shadowsocks加载这个json文件,启动。

    ssserver -c ss5.json
    后台启动方式:
    nohup ssserver -c ss5.json 1>log 2>err &

https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt

JS笔记2

var a;
a||1+1 //2
1+a||1 //1[object Object]"  //1+(a||1)


(function() {
      var a = b = 5;   //b=5;var a=b;
  })();   
console.log(b);  //b=5  
console.log(a);  //a undefined



let命令下面一行的圆括号是必须的,否则会报错。因为解析器会将起首的大括号,理解成一个代码块,而不是赋值语句
let obj = {};
let arr = [];
({foo:obj.prop, bar:arr[0] } = {foo:123, bar:true})
////////////////
var {name}= obj;


js unicode编码
一种是"\u6d4b",还有一种是'\x68'
'\\u'+('0000' + '测'.charCodeAt(0).toString(16)).slice(-4)
'\\x'+'h'.charCodeAt(0).toString(16)

'\x'只能表示(0x20~0x7E)英文数字等特殊符号
'\u'是标准的unicode

npm config set unsafe-perm true

export NODE_ENV=production

x-requested-with:XMLHttpRequest  //表明是AJax异步

es6 装饰器-权限管理

var reduxStore={roles:['read']}  //redux-store存储用户的权限列表

function log(target, name, descriptor) {  
  var oldValue = descriptor.value;
  descriptor.value = function() {
    console.log(`"Call ${name}" arguments`, arguments);
    return oldValue.apply(null, arguments);
  };
  return descriptor;
}

function checkRole(role){  //检查权限  
    return (target, property, descriptor)=>{
        if(reduxStore.roles.indexOf(role)==-1){
            descriptor.value=function(){
                console.log('没有权限')
            };  //如果没有权限,改变方法。
        }
        return descriptor
    }
}
class Components{}

class AComponents extends Components{  
  constructor(){
    super()
  }
  @log
  log(arg){
    console.log('我执行有log记录的')
  }

  @checkRole('read')  //需要read权限才执行read()
  read(){
   console.log('read')
  }

  @checkRole('write')  //需要write权限才执行read()
  write(){
   console.log('write')
  }
  render(){}
}
var a = new AComponents();  
a.read();  
a.write();  
a.log('arg')  

上面的是一个模拟react的组件。并加入权限控制。在babel测试通过

escape;encodeURI;encodeURIComponent

  • escape
  • unescape
  • encodeURI
  • decodeURI
  • encodeURIComponent
  • decodeURIComponent

encodeURI方法不会对下列字符编码ASCII?????? ?????? ~!@#$&*()=:/,;?+'

encodeURIComponent方法不会对下列字符编码ASCII?????? ?????? ~!*()'

首先,escape unescape 已经被w3c废弃,是非标准的,应当避免使用。 encodeURI和encodeURIComponent的区别在于转义的范围不一样。

encodeURI一般用在 URL 上。因为一般url是https://www.baidu.com这种。encodeURI不会对: //字符转义

encodeURIComponent用在URL的参数上(get/post)。参数一般形式a=xxx&b=xxx,这时& =两个特殊符号很重要,如果xxx中有&就会导致参数中断,发的数据不全。这时要用encodeURIComponent转义,把xxx中的& =转掉。

decodeURI;decodeURIComponent反之。

html-webpack-plugin使用

一般,升级网站,要改js名字,加个版本号等。现在,有html-webpack-plugin,自动生成html。真正的前端自动化。

var path = require('path');  
var webpack = require('webpack');  
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {  
    entry: {
        page1: "./js/page1.js",   //人口文件
        page2:"./js/page2.js"
    },
    output: {
        path: __dirname + '/build',
        filename: "[hash:8].[name].bundle.js",
        publicPath: "/static/build/",
        chunkFilename:'[hash:8].[name].chunkbundle.js'
    },
    plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: "commons",
            filename: "[hash:8].commons.js",
            chunks: ['page1', 'page2']
        }),  //提取公共模块
        new HtmlWebpackPlugin({
            title:'平台',  //html的title
            inject:'body', //在body标签插入
            filename:'main.html',
            template:'htmlTemplate/template.html',  //模板
            chunks:['page1','commons'],  //页面需要的模块
            minify: { //压缩HTML文件
                removeComments: true, //移除HTML中的注释
                collapseWhitespace: false //删除空白符与换行符
            }
        }),
        new HtmlWebpackPlugin({
            title:'平台',
            inject:'body', //在body标签插入
            filename:'index.html',
            template:'htmlTemplate/template.html',
            chunks:['page2','commons'],
            minify: { //压缩HTML文件
                removeComments: true, //移除HTML中的注释
                collapseWhitespace: false //删除空白符与换行符
            }
        }),
    ]
};

提取公共模块:

new webpack.optimize.CommonsChunkPlugin("[hash:8].commons.js", ["page1", "page2"]),  //提取公共模块  
//这样虽然可以提取,但是html-webpack-plugin不能用,要用下面的写法,把name属性注明
        new webpack.optimize.CommonsChunkPlugin({
            name: "commons",
            filename: "[hash:8].commons.js",
            chunks: ['page1', 'page2']
        }),  

跨域(JSONP,CORS)

JSONP

服务器端:

router.get('/GET_XSS_project', function(req, res, next) {  
    db(function(err, connection) {
        connection.query( "select * from xssProject where id = ?",[req.query.xssProjectID], function(err, rows) {
            if(err){console.log(err)}
            connection.release();
            res.type('text/javascript');
            res.send(`${req.query.callback}(${JSON.stringify(rows)})`);
        });
    });
});

前端:

$.ajax({
   url:config.JSONP.GET_XSS_project.url,
    type:'get',
    dataType: "jsonp",
    jsonpCallback: "xssJsonpCallback",
}).done((data)=>{
    this.setState({xssProjectList:data})
})

CORS

只需在服务器端设置HTTP头,postAccess-Control-Allow-Origin:即可。生成环境,把换成你需要跨域的网站。

router.post('/CORS', function(req, res, next) {
     res.setHeader('Access-Control-Allow-Origin','*');
    res.send(`(${JSON.stringify({name:'CORS'})})`);
});

JavaScript与有限状态机

简单介绍一个有限状态机的函数库Javascript Finite State Machine

生成实例

var fsm = StateMachine.create();

创建

var state = StateMachine.create({  
    initial: 'null', //初始状态
    events: [
        { name: 'to_scene',  from: 'null',  to: 'scene' },
        { name: 'to_scene2', from: 'scene', to: 'scene2'},

    ],
    callbacks: {
        onto_scene:  function(event, from, to, msg) { console.log('to_scene ' + msg);               },
        onto_scene2:  function(event, from, to, msg) { console.log('to_scene2 ' + msg);            },
        onnull:  function(event, from, to, msg)      { console.log(to)    },
        onscene:    function(event, from, to)      { console.log(to)     },
        onscene2:    function(event, from, to)      { console.log(to)     },
    }
});

export default state  

触发

state.to_scene(1)  
state.to_scene2(2)  

触发

注意,onscene在onto_scene前面执行的。

其他API

  • fsm.current :返回当前状态。
  • fsm.is(s) :返回一个布尔值,表示状态s是否为当前状态。
  • fsm.can(e) :返回一个布尔值,表示事件e是否能在当前状态触发。
  • fsm.cannot(e) :返回一个布尔值,表示事件e是否不能在当前状态触发。

React-Router使用

百度搜出来的都是过时api。现在”react-router”: “^2.4.0”了。

1.activeClassName

以前的active是默认添加是active。 现在要手动开启了。

<Link activeClassName="link_active" to="/home" >首页</Link>  
<Link activeClassName="link_active" to="/addcase" >添加案例</Link>  
<Link activeClassName="link_active" to="/casequery" >ZZZZ</Link>  

2.默认路由

IndexRoute component={Home} /> 这个不能用了

<IndexRedirect to="home" /> 最新。

<Redirect from="/" to="home" />可以跳转,但是,不会为Link增加activeClassName。  

html5拖动文件上传

$(document).on({  //阻止默认行为
    dragleave:function(e){    //拖离
        e.preventDefault();
    },
    drop:function(e){  //拖后放
        e.preventDefault();
    },
    dragenter:function(e){    //拖进
        e.preventDefault();
    },
    dragover:function(e){    //拖来拖去
        e.preventDefault();
    }
});
var box = document.getElementById('drop_area'); //拖拽区域
box.addEventListener("drop",function(e){
    e.preventDefault(); //取消默认浏览器拖拽效果
    var fileList = e.dataTransfer.files; //获取文件对象
    console.log(fileList)
    //检测是否是拖拽文件到页面的操作
    if(fileList.length == 0){
        return false;
    }
    //检测文件是不是APK
   if(fileList[0].name.substring(fileList[0].name.lastIndexOf('.')+1).toLowerCase()!=='apk'){
        alert("您拖的不是APK!");
        return false;
    }
    var Form=new FormData();
    Form.append('file',fileList[0]);
    $.ajax({
        url: config.api.UPLOAD_APK.url,
        type: "POST",
        data: Form,
        processData: false,  // 告诉jQuery不要去处理发送的数据
        contentType: false   // 告诉jQuery不要去设置Content-Type请求头
    }).done(function (data) {
        if(data.status===0){
            Message.show(<span><i className="glyphicon glyphicon-ok"></i>文件上传成功</span>, "success")
            setTimeout(function () {
                $(".rct-message.rct-message-success").children('button').eq(0).click();
            },1000)
        }
    });
},false);