分类目录归档:开发技术&电脑使用

记录开发相关的文章

让FPM以root用户运行

fpm默认是不能以root用户运行的,会报:
ERROR: [pool www] please specify user and group other than root

如果有特殊原因,需要以root用户运行,需要修改配置,以让fpm支持以root用户的方式运行fpm
vim /lib/systemd/system/php-fpm.service
把:
ExecStart=/usr/sbin/php-fpm –nodaemonize
修改成:
ExecStart=/usr/sbin/php-fpm -R –nodaemonize

改完后,需要执行:
systemctl daemon-reload
以生效修改

再执行,重启fpm进程
systemctl restart php-fpm

如果之前的fpm是手动运行的,需要以发送Linux信号的方式停止fpm服务,如果开启的fpm进程较多,要多等一会儿,等子进程完了再systemctl start php-fpm,不然会出现端口被占用,无法启动的情况
kill -SIGKILL [fpm master的进程号]

正则手记

这几个老是容易忘记

  • 在多个字符串中选择一个字符串匹配
    111(?:abc|def)222
  • 只匹配hello php和java中的hello, 不匹配hello python中的hello
    hello (?=php|java)
  • 只匹配除 hello python和javascript外的其它串中的hello
    hello (?!python|javascript)
  • 只匹配dan或john is a good man中的is a good man
    (?<=dan|john) is a good man
  • 只匹配除dan和john以外中的is a good man
    (?<!dan|john) is a good man 

 

CURL报”426 Unsupported SSL protocol TLSv1.2″时,升级curl, openssl, php-curl

服务器上php 5.6调用curl时,返回”426 Unsupported SSL protocol TLSv1.2, Upgrade to TLSv1.3 is required”.

用”openssl ciphers -V | column -t“ 查看,原来是openssl不支持TLSv1.3,需要升级,但由于PHP的CURL扩展是调用的Curl,Curl再调用的openssl,所以需要把openssl和curl升级,把php-curl重新编译.

思路是重新安装openssl和curl到新目录,以防止破坏以前的依赖,不然就容易翻车。

一、升级openssl

去https://www.openssl.org/source/下载v1版本,因为我是php5,系统也比较老,下载v1保险一些。
./config –prefix=/usr/local/openssl
make
make install

完成后测试下: /usr/local/openssl/bin/openssl version,
可能会报错:
bin/openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
建立软链
ln -s /usr/local/openssl/lib/libssl.so.1.1 /usr/lib64/libssl.so.1.1
ln -s /usr/local/openssl/lib/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1

二、升级CURL

去官网下载最新的curl,按标准安装方法,把curl安装到/usr/local/curl目录,需要指定上面新的openssl目录
./configure –prefix=/usr/local/curl –with-ssl=/usr/local/openssl

完成后可以测试一下,是否可以下载TLSv1.3的URL内容,如果没有问题就到三步

三、重新编译php-curl

去PHP官网下载和你当前版本一样的原码,解压,注意要指定新的curl目录
/root/software/php-5.6.40/ext/curl
phpize
./configure –with-curl=/usr/local/curl/
make
make install

如果是php8的curl扩展到这一步要报错:

checking for cURL support… yes, shared
checking for libcurl >= 7.29.0… no
configure: error: Package requirements (libcurl >= 7.29.0) were not met:

No package ‘libcurl’ found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables CURL_CFLAGS
and CURL_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.

要这样才可以
export PKG_CONFIG_PATH=/usr/local/curl/lib/pkgconfig

报下面的错误的话要这样:
libtool: compile: cc -I. -I/root/software/php-8.3.1/ext/curl -I/root/software/php-8.3.1/ext/curl/include -I/root/software/php-8.3.1/ext/curl/main -I/root/software/php-8.3.1/ext/curl-I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/lib -I/usr/local/curl/include/ -DHAVE_CONFIG_H -g -O2 -D_GNU_SOURCE -DZEND_COMPILE_DL_EXT=1 -c /root/software/php-8.3.1/ext/curl/interface.c -MMD -MF interface.dep -MT interface.lo -fPIC -DPIC -o .libs/interface.o
/root/software/php-8.3.1/ext/curl/interface.c:58:28: fatal error: zend_smart_str.h: No such file or directory
./configure –with-curl=/usr/local/curl –with-php-config=/opt/remi/php83/root/bin/php-config

报下面的错误的话要这样make:
/root/software/php-8.3.1/ext/curl/multi.c: In function ‘curl_multi_get_gc’:
/root/software/php-8.3.1/ext/curl/multi.c:572:2: error: ‘for’ loop initial declarations are only allowed in C99 mode

或者修改代码,把那一行的行内定义提出去,或者用下面的命令编译:
make CFLAGS=-std=c99

最后测试一下:
php -r “phpinfo();” | grep cURL
输出
cURL support => enabled
cURL Information => 8.2.1

没有问题,如果是fpm,要重启fpm。

其它的问题
如果在编译的时候出现很多语法错误,有可能是系统安装了多个php版本,引用到了错误的php头文件,在.configure的时候,要指定–with-php-config
安装好扩展之后,但加载扩展如果出现下面的错误,是因为php扩展和curl的版本不对,需要下载新的curl版本重新安装。
PHP Warning: PHP Startup: Unable to load dynamic library ‘curl’ (tried: /opt/remi/php83/root/usr/lib64/php/modules/curl (/opt/remi/php83/root/usr/lib64/php/modules/curl: cannot openshared object file: No such file or directory), /opt/remi/php83/root/usr/lib64/php/modules/curl.so (/opt/remi/php83/root/usr/lib64/php/modules/curl.so: undefined symbol: curl_easy_escape)) in Unknown on line 0

MySQL大表改结构(pt-online-schema-change)

yum install -y https://repo.percona.com/yum/percona-release-latest.noarch.rpm

yum install percona-toolkit

https://www.percona.com/doc/percona-toolkit/LATEST/pt-online-schema-change.html

pt-online-schema-change –user=xxx –password=”xxx” –host=”xxx” –alter=”ADD bbb INT NULL DEFAULT ‘0’” D=dmp_main,t=test –execute

使用bootstrap的分裂式下拉菜单右边的下拉箭头不居中的问题

今天在写个东西,用到了bootstrap的分裂式下拉菜单,在使用的时候,出现了下面的问题:

折腾了好我,右边的箭头始终无法对齐,把官网的代码复制下来一行一行的删除查找,后面发下是因为没有在html的第一行加上:
<!doctype html>
导致。。。。

他规定了浏览器的解析规范,具体有哪些规范也搞不懂,反正一定要加上就对了。

PHP防止重复运行代码

/**
 * 获取当前程序运行了多少个进程
 * @param $processName 程序进程名,要唯一
 */
function GetInstancePids($processName)
{
    // 把文件放到外面去,防止发布版本把状态文件搞没了
    $dir = dirname(dirname(dirname(dirname(__FILE__)))).'/data'.'/pids';
    $file = $dir . DIRECTORY_SEPARATOR . $processName;
    $pinfo = getCurrentProcessInfo();

    if (!file_exists($file)) {
        file_put_contents($file, "{$pinfo['pid']}\t{$pinfo['cmd']}\n");
        return true;
    }

    $i = 0;
    $pidfile = fopen($file, 'r+');
    do {
        if (flock($pidfile, LOCK_EX)) {
            break;
        } else {
            if ($i++ == 10) {
                exit('try 10 times to lock pid file,faild');
            }
            usleep(1000);
        }
    } while (true);

    $read = fread($pidfile, 10240);
    rewind($pidfile);
    $read = explode("\n", trim($read));
    $process_info = [];
    foreach ($read as $index => $line) {
        list($pid, $cmd) = explode("\t", $line);
        if (!empty($pid) && isPidExists($pid, $cmd)) {
            $process_info[] = "{$pid}\t{$cmd}";
        }
    }
    
    $process_info[] = "{$pinfo['pid']}\t{$pinfo['cmd']}";
    ftruncate($pidfile,0);
    fwrite($pidfile, implode("\n", $process_info));
    fflush($pidfile);
    flock($pidfile, LOCK_UN);
    fclose($pidfile);

    return true;
}

/**
 * 返回自身进程信息
 */
function getCurrentProcessInfo()
{
    $mypid = getmypid();
    $outputs = [];
    exec('ps -ax | grep -E "^\s*' . $mypid . '\s+"', $outputs);
    $matched = [];
    preg_match('/^\s*(\S+?)\s+?\S+?\s+?(\S+?)\s+?\S+?\s+?(.+)/', $outputs[0], $matched);
    return [
        'pid' => $matched[1],
        'uptime' => $matched[2],
        'cmd' => $matched[3],
    ];
}

function isPidExists($pid, $cmd)
{
    exec('ps -ax | grep -E "^\s?'. $pid . '.+?'.$cmd.'"', $result);
    return isset($result[0]);
}

 

使用的时候:

$pids = GetInstancePids(“xxx”);
if (count($pids) > 1) die(“程序运行中”);

nginx规则笔记[转]

转自:https://www.cnblogs.com/qinyujie/p/8979464.html

1、location [=|~|~*|^~] /uri/ { … }

语法规则: location [=|~|~*|^~] /uri/ { … }

  • = 开头表示精确匹配
  • ^~ 开头表示uri以某个常规字符串开头,理解为匹配 url路径即可。nginx不对url做编码,因此请求为/static/20%/aa,可以被规则^~ /static/ /aa匹配到(注意是空格)。以xx开头
  • ~ 开头表示区分大小写的正则匹配                     以xx结尾
  • ~* 开头表示不区分大小写的正则匹配                以xx结尾
  • !~!~*分别为区分大小写不匹配及不区分大小写不匹配 的正则
  • / 通用匹配,任何请求都会匹配到。
location  = / {
  # 精确匹配 / ,主机名后面不能带任何字符串
  [ configuration A ] 
}
location  / {
  # 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求
  # 但是正则和最长字符串会优先匹配
  [ configuration B ] 
}
location /documents/ {
  # 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
  # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
  [ configuration C ] 
}
location ~ /documents/Abc {
  # 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
  # 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
  [ configuration CC ] 
}
location ^~ /images/ {
  # 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。
  [ configuration D ] 
}
location ~* \.(gif|jpg|jpeg)$ {
  # 匹配所有以 gif,jpg或jpeg 结尾的请求
  # 然而,所有请求 /images/ 下的图片会被 config D 处理,因为 ^~ 到达不了这一条正则
  [ configuration E ] 
}
location /images/ {
  # 字符匹配到 /images/,继续往下,会发现 ^~ 存在
  [ configuration F ] 
}
location /images/abc {
  # 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在
  # F与G的放置顺序是没有关系的
  [ configuration G ] 
}
location ~ /images/abc/ {
  # 只有去掉 config D 才有效:先最长匹配 config G 开头的地址,继续往下搜索,匹配到这一条正则,采用
    [ configuration H ] 
}
location ~* /js/.*/\.js

2、符号解释

=      开头表示精确匹配

^~      开头表示url以某个常规字符串开头,理解为匹配url路径即可,nginx不对url做编码,因此请求为/static/20%/aa,可以被规则 ^$ /static/ /aa 匹配到

~      区分大小写的正则匹配

~*      不区分大小写的正则匹配

!~ !~*    区分大小写不匹配及不区分大小写不匹配的正则

/       通用匹配,任何请求都会匹配到

location = / {多个location配置的情况下匹配顺序为首先匹配 = 其次匹配 ^~ 其次是按文件中的顺序的正则匹配,最后是交给 / 通用匹配。 当匹配成功的时候,停止匹配,按当前匹配规则处理请求。

   #规则A
}
location = /login {
   #规则B
}
location ^~ /static/ {
   #规则C
}
location ~ \.(gif|jpg|png|js|css)$ {
   #规则D
}
location ~* \.png$ {
   #规则E
}
location !~ \.xhtml$ {
   #规则F
}
location !~* \.xhtml$ {
   #规则G
}
location / {
   #规则H
}

那么产生的效果如下:
访问根目录/, 比如http://localhost/ 将匹配规则A
访问 http://localhost/login 将匹配规则B,http://localhost/register 则匹配规则H
访问 http://localhost/static/a.html 将匹配规则C
访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用,而http://localhost/static/c.png 则优先匹配到规则C
访问 http://localhost/a.PNG 则匹配规则E,而不会匹配规则D,因为规则E不区分大小写。
访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。
访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为反向代理服务器存在。

所以实际使用中,个人觉得至少有三个匹配规则定义,如下:
直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。
这里是直接转发给后端应用服务器了,也可以是一个静态首页

第一个必选规则
location = / {
proxy_pass http://tomcat:8080/index
}
第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
root /webroot/static/;
}
location ~* .(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
第三个规则就是通用规则,用来转发动态请求到后端应用服务器
非静态文件请求就默认是动态请求,自己根据实际把握
毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
proxy_pass http://tomcat:8080/
}

3、rerite语法

rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。rewrite只能放在server{},location{},if{}中,并且只能对域名后边的除去传递的参数外的字符串起作用,例如 http://seanlook.com/a/we/index.php?id=1&u=str 只对/a/we/index.php重写。语法rewrite regex replacement [flag];

如果相对域名或参数字符串起作用,可以使用全局变量匹配,也可以使用proxy_pass反向代理。
表明看rewrite和location功能有点像,都能实现跳转,主要区别在于rewrite是在同一域名内更改获取资源的路径,而location是对一类路径做控制访问或反向代理,可以proxy_pass到其他机器。很多情况下rewrite也会写在location里,它们的执行顺序是:
执行server块的rewrite指令
执行location匹配
执行选定的location中的rewrite指令
如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件;循环超过10次,则返回500 Internal Server Error错误。

server {
listen 80;
server_name start.igrow.cn;
index index.html index.php;
root html;
if ($http_host !~ “^star\.igrow\.cn$&quot {
rewrite ^(.*) http://star.igrow.cn$1 redirect;
}
}

4、flag标志位

last – 基本上都用这个Flag。
break – 中止Rewirte,不在继续匹配
redirect – 返回临时重定向的HTTP状态302
permanent – 返回永久重定向的HTTP状态301

因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。这里 last 和 break 区别有点难以理解:
last一般写在server和if中,而break一般使用在location中
last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
break和last都能组织继续执行后面的rewrite指令

5、if指令与全局变量

语法为if(condition){…},对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:

当表达式只是一个变量时,如果值为空或任何以0开头的字符串都会当做false
直接比较变量和内容时,使用=或!=
~正则表达式匹配,~*不区分大小写的匹配,!~区分大小写的不匹配

1、下面是可以用来判断的表达式:
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行

2、下面是可以用作判断的全局变量

 

if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含"MSIE",rewrite请求到/msid/目录下
if ($http_cookie ~* "id=([^;]+)(?:;|$)") {
    set $id $1;
 } //如果cookie匹配正则,设置变量$id等于正则引用部分
if ($request_method = POST) {
    return 405;
} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
if ($slow) {
    limit_rate 10k;
} //限速,$slow可以通过 set 指令设置
if (!-f $request_filename){
    break;
    proxy_pass  http://127.0.0.1; 
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
if ($args ~ post=140){
    rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com
location ~* \.(gif|jpg|png|swf|flv)$ {
    valid_referers none blocked www.jefflei.com www.leizhenfang.com;
    if ($invalid_referer) {
        return 404;
    } //防盗链
}

例:http://localhost:88/test1/test2/test.php
$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:D:\nginx/html
$request_filename:D:\nginx/html/test1/test2/test.php

6、防盗链

location ~* \.(gif|jpg|swf)$ {
valid_referers none blocked start.igrow.cn sta.igrow.cn;
if ($invalid_referer) {
rewrite ^/ http://$host/logo.png;
}
}

7、根据文件类型设置过期时间

location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {
if (-f $request_filename) {
expires 1h;
break;
}
}

8、常用变量

$args : #这个变量等于请求行中的参数,同$query_string
$content_length : 请求头中的Content-length字段。
$content_type : 请求头中的Content-Type字段。
$document_root : 当前请求在root指令中指定的值。
$host : 请求主机头字段,否则为服务器名称。
$http_user_agent : 客户端agent信息
$http_cookie : 客户端cookie信息
$limit_rate : 这个变量可以限制连接速率。
$status  请求状态
$body_bytes_sent 发送字节
$request_method : 客户端请求的动作,通常为GET或POST。
$remote_addr : 客户端的IP地址。
$remote_port : 客户端的端口。
$remote_user : 已经经过Auth Basic Module验证的用户名。
$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
$scheme : HTTP方法(如http,https)。
$server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
$server_name : 服务器名称。
$server_port : 请求到达服务器的端口号。
$request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri : 与$uri相同。

写一个Composer包的Composer.json模板

目录结构

{
    "name": "myjoyoo/affiliate-sdk",
    "description": "如LinkShare、CJ、PJ、Awin之类的联盟的SDK接口封装",
    "type": "l",
    "require": {
        "php": ">=8.0",
        "guzzlehttp/guzzle": "^7.3",
        "nesbot/carbon": "^2.48"
    },
    "license": "Apache",
    "authors": [
        {
            "name": "myjoyoo",
            "email": "[email protected]"
        }
    ],
    "minimum-stability": "dev",
    "autoload": {
        "psr-4": {
            "AffiliateSDK\\": "src"
        },
        "files": ["src/include/commonFunction.php"]
    }
}

改了之后,需要执行下面的命令去生效
composer dump-auotload

Postman里计算md5到form表单里

FORM表单里有一个字段是根据几个字段hash得到的值,每次去算hash很不方便,可以这样去设置。

在pre-request script里输入:

var data = request.data.c_source + 
request.data.c_affiliate_id + 
request.data.c_order_id + 
'xxxxx';

var hash = CryptoJS.MD5(data).toString();
pm.environment.set("token", hash);

// 常用操作
// 获取query参数
var str = pm.request.url.query.get("version");

// 获取post表单里的值
var str = request.data.字段名

// 获取提交的json数据
var post = JSON.parse(pm.request.body.raw);

// 向header加头
pm.request.headers.add({
    key: 'x-ShareASale-Date',
    value: myTimeStamp
});

在Form表单里输入: {{token}} 就可以自动计算了

怎么取值,可以参考PostMan的官方文档

https://learning.postman.com/docs/writing-scripts/script-references/postman-sandbox-api-reference/#scripting-with-request-data

自动计算token并加到postman的请求里:

var salt = "xxxx";
var post = JSON.parse(pm.request.body.raw);
var hash = CryptoJS.MD5(post.source_account_id + salt).toString();
post.token = hash;
pm.request.body.raw = JSON.stringify(post);

// 更多的加密方法 SHA256
var SHA256 = CryptoJS.SHA256(str).toString();
// BASE64
const data = CryptoJS.enc.Utf8.parse("test")
const base64 = CryptoJS.enc.Base64.stringify(data)

在PostMan里使用请求获取到的token当成认证参数

// linkhaitao
var new_Client_id = "x"
var new_Client_secret = "x"
var username = "x"
var scope = "x"

var token = MyUtils.BASE64(new_Client_id+":"+new_Client_secret)

// 请求可以参考: http://www.postmanlabs.com/postman-collection/Request.html#~definition

var postData = [
    {key: 'grant_type', value: 'password'},
    {key: 'username', value: username},
    {key: 'scope', value: scope}
];

var requestOption = {
    url: 'https://api.xxx.com/token',
    method: 'POST',
    header: {
        "Authorization": "Basic " + token,
        "Content-Type": "application/json"
    },
    body: {
        mode: 'urlencoded', // 这里为什么值,下面就为什么key,如果raw, formdata, urlencoded之类
        urlencoded: postData
        // mode: 'raw',
        // raw: JSON.stringify(postData)
    }
}

pm.sendRequest(requestOption, function (err, res) {
    console.log("获取到的token", res.json());
    pm.environment.set("token", res.json().access_token)
    pm.request.headers.add({
        key: "Authorization",
        value: "Bearer " + res.json().access_token
    });
})

向PostMan的Query地址里加参数

let token = "xxoo"

pm.request.addQueryParams({
    key: "token",
    value: token
});

 

PostMan里定义和使用全局函数

在某一个文件夹里的”pre request script”里,定义下面的内容

MyUtils = {
    SHA256: function SHA256(s){
        var chrsz = 8;
        var hexcase = 0;
        function safe_add (x, y) {
            var lsw = (x & 0xFFFF) + (y & 0xFFFF);
            var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
            return (msw << 16) | (lsw & 0xFFFF);
        }
        function S (X, n) { return ( X >>> n ) | (X << (32 - n)); }
        function R (X, n) { return ( X >>> n ); }
        function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); }
        function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); }
        function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }
        function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }
        function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }
        function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }
        function core_sha256 (m, l) {
            var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2);
            var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
            var W = new Array(64);
            var a, b, c, d, e, f, g, h, i, j;
            var T1, T2;
            m[l >> 5] |= 0x80 << (24 - l % 32);
            m[((l + 64 >> 9) << 4) + 15] = l;
            for ( var i = 0; i<m.length; i+=16 ) {
            a = HASH[0];
            b = HASH[1];
            c = HASH[2];
            d = HASH[3];
            e = HASH[4];
            f = HASH[5];
            g = HASH[6];
            h = HASH[7];
            for ( var j = 0; j<64; j++) {
                if (j < 16) W[j] = m[j + i];
                else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
                T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
                T2 = safe_add(Sigma0256(a), Maj(a, b, c));
                h = g;
                g = f;
                f = e;
                e = safe_add(d, T1);
                d = c;
                c = b;
                b = a;
                a = safe_add(T1, T2);
            }
            HASH[0] = safe_add(a, HASH[0]);
            HASH[1] = safe_add(b, HASH[1]);
            HASH[2] = safe_add(c, HASH[2]);
            HASH[3] = safe_add(d, HASH[3]);
            HASH[4] = safe_add(e, HASH[4]);
            HASH[5] = safe_add(f, HASH[5]);
            HASH[6] = safe_add(g, HASH[6]);
            HASH[7] = safe_add(h, HASH[7]);
            }
            return HASH;
        }
        function str2binb (str) {
            var bin = Array();
            var mask = (1 << chrsz) - 1;
            for(var i = 0; i < str.length * chrsz; i += chrsz) {
            bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
            }
            return bin;
        }
        function Utf8Encode(string) {
            string = string.replace(/\r\n/g,"\n");
            var utftext = "";
            for (var n = 0; n < string.length; n++) {
            var c = string.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            }
            return utftext;
        }
        function binb2hex (binarray) {
            var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
            var str = "";
            for(var i = 0; i < binarray.length * 4; i++) {
            str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
            hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
            }
            return str;
        }
        s = Utf8Encode(s);
        return binb2hex(core_sha256(str2binb(s), s.length * chrsz));
    }
}