]*?zm-item-title[^>]*?>\s*(.*?)#is';
56 |
57 | if( preg_match_all($pattern, $content, $matches) ) {
58 | foreach($matches[0] as $key => $val) {
59 | echo "{$matches[2][$key]}({$matches[1][$key]})\n";
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/demo/8_webqq.php:
--------------------------------------------------------------------------------
1 | getLineBreak();
17 |
18 | //测试发送信息
19 | for($i = 1; $i <= 3; $i++) {
20 | $message = rawurlencode(date('Y-m-d H:i:s') . ': message_' . $i);
21 | $curl1 = "curl 'http://d1.web2.qq.com/channel/send_qun_msg2' -H 'Host: d1.web2.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Referer: http://d1.web2.qq.com/proxy.html?v=20151105001&callback=1&id=2' -H 'Cookie: ts_uid=6512215782; ts_refer=www.popoho.com/tool/denglu/; p_uin=o01000088; p_skey=miwiAfcSoDeZCoFJa6OefkUZ7w03HWmRVKzLxUZZ-1U_; pt4_token=we*K*xMoPd5*BqM4m16h8yI*NSvonZ3MjeyEb5r90sw_; pgv_info=ssid=s4959849500; pgv_pvid=649892905; pt2gguin=o01000088; uin=o01000088; skey=@a5s8A3qb3; ptisp=cnc; RK=YIGuZAlSQS; ptwebqq=37848925dee6af86f6579c9c46fed9f19a; o_cookie=1000088' --data 'r=%7B%22group_uin%22%3A3978381470%2C%22content%22%3A%22%5B%5C%22{$message}%5C%22%2C%5B%5C%22font%5C%22%2C%7B%5C%22name%5C%22%3A%5C%22%E5%AE%8B%E4%BD%93%5C%22%2C%5C%22size%5C%22%3A10%2C%5C%22style%5C%22%3A%5B0%2C0%2C0%5D%2C%5C%22color%5C%22%3A%5C%22000000%5C%22%7D%5D%5D%22%2C%22face%22%3A0%2C%22clientid%22%3A53999199%2C%22msg_id%22%3A20080001%2C%22psessionid%22%3A%228368046764001d636f6e6e7365727665725f77656271714031302e3133332e34312e383400001ad00000066b026e040015808a206d0000000a406172314338344a69526d000000285918d94e66218548d1ecb1a12513c86126b3afb97a3c2955b1070324790733ddb059ab166de6857%22%7D'";
22 |
23 | //注:频繁发送会导致账号锁定,慎用!!!
24 | $msg = rawurlencode(date('Y-m-d H:i:s ') . '我轰死你个煞笔' . $i);
25 | $curl1 = "curl 'http://d1.web2.qq.com/channel/send_buddy_msg2' -H 'Host: d1.web2.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Referer: http://d1.web2.qq.com/proxy.html?v=20151105001&callback=1&id=2' -H 'Cookie: ts_uid=6512215782; ts_refer=www.popoho.com/tool/denglu/; p_uin=o01000088; p_skey=2rnpdQKMZJz2IP9zqvixxKNUVgm2DwFNm2NiHEH0F0E_; pt4_token=ArYeZZXriUbYi157LEY2QhbQKHIwvEUdWDyNFpEgSPw_; pgv_info=ssid=s1842987996; pgv_pvid=5589981100; pt2gguin=o01000088; uin=o01000088; skey=@9KF9yztXZ; ptisp=cnc; RK=mIGmcAlTQS; ptwebqq=1554f1205a9ff09c1ce44' -H 'Connection: keep-alive' --data 'r=%7B%22to%22%3A3820995309%2C%22content%22%3A%22%5B%5C%22{$msg}%5C%22%2C%5B%5C%22font%5C%22%2C%7B%5C%22name%5C%22%3A%5C%22%E5%AE%8B%E4%BD%93%5C%22%2C%5C%22size%5C%22%3A10%2C%5C%22style%5C%22%3A%5B0%2C0%2C0%5D%2C%5C%22color%5C%22%3A%5C%22000000%5C%22%7D%5D%5D%22%2C%22face%22%3A0%2C%22clientid%22%3A53999199%2C%22msg_id%22%3A45070001%2C%22psessionid%22%3A%228368046764001d636f6e6e7365727665725f77656271714031302e3133332e34312e383400001ad00000066b026e040015808a206d0000000a406172314338344a69526d000000285918d94e66218548d1ecb1a12513c86126b3afb97a3c2955b1070324790733ddb059ab166de6857%22%7D'";
26 | $content = $autologin->execCurlWithCookie($curl1);
27 | var_dump($content);
28 | sleep(rand(3, 5));
29 | }
30 |
--------------------------------------------------------------------------------
/demo/11_cnblogLogin/11_cnbloglogin.php:
--------------------------------------------------------------------------------
1 | execCurl($curl1);
28 |
29 | //获取VerificationToken
30 | $pattern = "#'VerificationToken': '([^']+)'#is";
31 | if(!preg_match($pattern, $content, $match)) {
32 | exit('无法解析获得登录页VerificationToken');
33 | //throw new Exception('无法解析获得登录页VerificationToken');
34 | }
35 |
36 | $verificationToken = $match[1];
37 |
38 | //基于node.js获取登录加密结果
39 | $content = file_get_contents("http://localhost:8111?input1={$username}&input2={$password}");
40 | $encryptInfo = json_decode($content, true);
41 | $postData = sprintf('{"input1":"%s","input2":"%s","remember":false}', $encryptInfo['input1'], $encryptInfo['input2']);
42 | $contentLength = strlen($postData);
43 |
44 | //提交登录信息
45 | $curl2 = "curl 'https://passport.cnblogs.com/user/signin' -X POST -H 'Host: passport.cnblogs.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:48.0) Gecko/20100101 Firefox/48.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json; charset=utf-8' -H 'VerificationToken: {$verificationToken}' -H 'X-Requested-With: XMLHttpRequest' -H 'Referer: https://passport.cnblogs.com/user/signin?ReturnUrl=http%3A%2F%2Fwww.cnblogs.com%2F&AspxAutoDetectCookieSupport=1' -H 'Content-Length: {$contentLength}' -H 'Cookie: AspxAutoDetectCookieSupport=1; SERVERID=d0849c852e6ab8cf0cebe3fa386ea513|1476439733|1476438874' -H 'Connection: keep-alive'";
46 | $content = $autologin->execCurl($curl2, function($parseCurlResult) use ($postData) {
47 | $parseCurlResult['post'] = $postData;
48 | return $parseCurlResult;
49 | });
50 |
51 | $autologin->lockLastCookieFile();
52 |
53 | $homeUrl = 'http://i.cnblogs.com/';
54 | $isLogin = $autologin->assertContainStr($autologin->getUrl($homeUrl), '修改密码');
55 |
56 | if($isLogin) {
57 | echo "已登录\n";
58 | } else {
59 | exit("未登录,请检查账号密码\n");
60 | }
61 |
62 | file_put_contents($loginCookieFile, $autologin->getLastCookieContent());
63 | }
64 |
65 | $autologin->setLastCookieFile($loginCookieFile);
66 |
67 | //获取我的随笔
68 | $url = 'https://i.cnblogs.com/';
69 | $content = $autologin->getUrl($url);
70 |
71 | $pattern = '#\s*]*>(.*?)#is';
72 |
73 | if( preg_match_all($pattern, $content, $matches) ) {
74 | foreach($matches[0] as $key => $val) {
75 | echo "{$matches[2][$key]}({$matches[1][$key]})\n";
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/demo/2_wxqq.php:
--------------------------------------------------------------------------------
1 | getLineBreak();
25 | //复制浏览器登录成功后,访问https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn的curl命令
26 | $curl = "curl 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn' -H 'Host: wx.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/46.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Cookie: pgv_info=ssid=s7821947904; pgv_pvid=7479620263 ...' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'";
27 |
28 | $content = $autologin->execCurl($curl, function($parseCurlResult) {
29 | $parseCurlResult['header'][] = $parseCurlResult['cookie'];
30 | return $parseCurlResult;
31 | });
32 | $res = $autologin->assertContainStr($content, '请不要在该网页上填写QQ账号及密码');
33 | if($res) {
34 | echo "Yes" . $lineBreak;
35 | } else {
36 | echo "No" . $lineBreak;
37 | }
38 |
39 |
40 |
41 | //方法二 直接调用parseCurl对curl命令进行解析,并组装包含cookie的header头进行请求
42 | $autologin = new PHPCurl\CurlAutoLogin();
43 | //复制浏览器登录成功后,访问 https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn 的curl命令
44 | $curl = "curl 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn' -H 'Host: wx.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/46.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Cookie: pgv_info=ssid=s7821947904; pgv_pvid=7479620263 ...' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'";
45 | $url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn';
46 | //仅用来解析头
47 | $curlInfo = $autologin->parseCurl($curl);
48 | $header = array_merge((array)$curlInfo['header'], array($curlInfo['cookie']));
49 | $content = $autologin->getUrl($url, $header);
50 | $res = $autologin->assertContainStr($content, '请不要在该网页上填写QQ账号及密码');
51 | if($res) {
52 | echo "Yes" . $lineBreak;
53 | } else {
54 | echo "No" . $lineBreak;
55 | }
56 |
57 | //方法三 直接调用execCurlWithCookie调用
58 | $autologin = new PHPCurl\CurlAutoLogin();
59 | //复制浏览器登录成功后,访问 https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn 的curl命令
60 | $curl = "curl 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fwww.zjmainstay.cn' -H 'Host: wx.qq.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:47.0) Gecko/20100101 Firefox/46.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Cookie: pgv_info=ssid=s7821947904; pgv_pvid=7479620263 ...' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'";
61 | $content = $autologin->execCurlWithCookie($curl);
62 | $res = $autologin->assertContainStr($content, '请不要在该网页上填写QQ账号及密码');
63 | if($res) {
64 | echo "Yes" . $lineBreak;
65 | } else {
66 | echo "No" . $lineBreak;
67 | }
68 |
--------------------------------------------------------------------------------
/demo/41_cli.im.php:
--------------------------------------------------------------------------------
1 | execCurl($curl);
17 |
18 | // echo "1. " . $content . "\n";
19 |
20 | $delimiter = '-----------------------------' . rand(1000000000, 9999999999) . rand(1000000000, 9999999999) . rand(10000000, 99999999);
21 | $filePath = __DIR__ . '/../images/php-curl-qrcode.png';
22 | $data = buildFileUploadData($delimiter, 'Filedata', $filePath);
23 | $contentType = 'multipart/form-data; boundary=' . $delimiter;
24 | $contentLength = strlen($data);
25 |
26 | $apiUrl = 'https://upload.api.cli.im/upload.php?kid=cliim';
27 |
28 | //2. 上传图片
29 | $curl = "curl '{$apiUrl}' -H 'Accept: */*' --compressed -H 'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' -H 'Connection: keep-alive' -H 'Cookie: koa.sid=6fuuKG4qGhJg2CFP0Y3Go1X92QKNjlI2; koa.sid.sig=FqGx8un0r_LBzf_60ROuaik-pPE' -H 'Origin: https://cli.im' -H 'Referer: https://cli.im/deqr' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:59.0) Gecko/20100101 Firefox/59.0' -H 'Content-Type: {$contentType}' -H 'Content-Length: {$contentLength}'";
30 | // die(var_dump($curl));
31 | $content = $autologin->execCurl($curl, function($parseCurlResult) use ($data) {
32 | $parseCurlResult['post'] = $data;
33 | return $parseCurlResult;
34 | });
35 |
36 | echo "2. " . $content . "\n";
37 |
38 | $imgInfo = json_decode($content, true);
39 | $imgUrl = urlencode($imgInfo['data']['path']);
40 |
41 | //3. 解析二维码
42 | $curl = "curl 'https://cli.im/apis/up/deqrimg' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2' --compressed -H 'Referer: https://cli.im/deqr' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Cookie: _ga=GA1.2.612629640.1509329069; Hm_lvt_cb508e5fef81367bfa47f4ec313bf68c=1536997019; SERVERID=845671255dd12630e5f3f4b14406bdaa|1536997573|1536996809; PHPSESSID=57fn56uo3ca1e1pcb1aan1as71; Hm_lpvt_cb508e5fef81367bfa47f4ec313bf68c=1536997782; climanager_v2=%7B%22manager_id%22%3A%2211%22%2C%22type%22%3A%221%22%2C%22weight%22%3A%220%22%2C%22nickname%22%3A%22%u5C0F%u8D75%22%2C%22realname%22%3A%22%u8D75%u8FD0%22%2C%22star_text%22%3A%22%u4E13%u5C5E%u987E%u95EE%22%2C%22vcard_pic%22%3A%22https%3A//static.clewm.net/cli/images/contact/kefu-default@2x.png%22%2C%22logo_pic%22%3A%22https%3A//static.clewm.net/cli/images/contact/logo-zy@2x.png%22%2C%22telphone%22%3A%220574-55330927%22%2C%22qq%22%3A%222852371507%22%2C%22contact_link%22%3A%22https%3A//q.url.cn/s/mjzkTcm%22%2C%22group_link%22%3A%22//q.url.cn/s/wGb3v6m%22%2C%22complete%22%3A0%7D; text-content-words=33; qrs=157961239; _gat=1' -H 'Connection: keep-alive' --data 'img={$imgUrl}'";
43 | $content = $autologin->execCurl($curl);
44 |
45 | echo "3. " . $content . "\n";
46 |
47 | /**
48 | * 构建文件上传数据
49 | * @param [type] $delimiter [description]
50 | * @param [type] $inputName [description]
51 | * @param [type] $file [description]
52 | * @return [type] [description]
53 | */
54 | function buildFileUploadData($delimiter, $inputName, $file) {
55 | $data = '';
56 | $data .= "--" . $delimiter . "\r\n";
57 | $data .= 'Content-Disposition: form-data; name="' . $inputName . '";' .
58 | ' filename="' . basename($file) . '"' . "\r\n";
59 | $data .= 'Content-Type: ' . mime_content_type($file) . "\r\n";
60 | $data .= "\r\n";
61 | $data .= file_get_contents($file) . "\r\n";
62 | $data .= "--" . $delimiter . "--\r\n";
63 |
64 | return $data;
65 | }
66 |
--------------------------------------------------------------------------------
/demo/15_downloadWizNote.php:
--------------------------------------------------------------------------------
1 | getLineBreak();
34 |
35 | // 步骤1:登录网页版为知笔记 https://note.wiz.cn/web
36 | // 步骤2:查看近期笔记,并下拉刷新直到全部显示笔记
37 | // 步骤3:利用下面的js,在控制台运行得到所有的笔记链接
38 | // 步骤4:将上面得到的笔记地址,填入$notes数组
39 | // 步骤5:运行php 15_downloadWizNote.php开始下载笔记 (注:加密笔记无法下载正确内容,考虑临时取消加密)
40 | // 步骤6:解析笔记json,存储为html
41 | /*
42 |
43 | //控制台运行js代码
44 | var res = '';
45 | var token = document.cookie.match(/token=([^;]+)/)[1]
46 | $(".note-list-item").each(function(){
47 | var title = $(this).find(".title").attr('title');
48 | res += '"https://note.wiz.cn/api/document/info?client_type=web2.0&api_version=6&token='
49 | +token+'&kb_guid='+$(this).attr('data-kbguid')+'&document_guid='+$(this).attr('data-docguid')
50 | +'&_='+(Math.floor(new Date().getTime() / 1000))+(parseInt(Math.random()*1000))+'", //' +title+ "\n";
51 | });
52 | console.log(res);
53 |
54 | */
55 |
56 | //所有笔记采集链接,利用js在控制台运行获取
57 | $notes = array(
58 | 'https://note.wiz.cn/api/document/info?client_type=web2.0&api_version=6&token=ebeda6e29d35b1d113a7190ce8fd268at75l8wpsw8ybta&kb_guid=781635a1-97b6-44ee-a2c9-33ead2a3ab1e&document_guid=31efcb50-36dc-4c1c-9576-6b103cd219e1&_=1481679224449',
59 | 'https://note.wiz.cn/api/document/info?client_type=web2.0&api_version=6&token=ebeda6e29d35b1d113a7190ce8fd268at75l8wpsw8ybta&kb_guid=781635a1-97b6-44ee-a2c9-33ead2a3ab1e&document_guid=10de4633-d3ed-441b-ac1a-9e899cda640b&_=1481679224449',
60 | );
61 |
62 | //测试发送信息
63 | foreach($notes as $noteUrl) {
64 | //网页版登录后,获取一条笔记加载的curl命令
65 | $curl = "curl 'https://note.wiz.cn/api/document/info?client_type=web2.0&api_version=6&token=ebeda6e29d35b1d113a7190ce8fd268at75l8wpsw8ybta&kb_guid=781635a1-97b6-44ee-a2c9-33ead2a3ab1e&document_guid=fcb921c1-8dbd-46a1-af24-7a43343c18c5&_=1481679224449' -H 'Accept: application/json, text/javascript, */*; q=0.01' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Cookie: Hm_lvt_df6808d18fab4a1df17434a064069692=1481528227,1481678379; Hm_lpvt_df6808d183a14a1dfa7454a064069692=1481679228; token=ebeda6e29d35b1d113a7190ce8fd268at75l8wpsw8ybta; wizID=1000000%40qq.com; CertNo=dd233f28e1460fde5ef72d63c00a1e6f13d3790cf90a0e2d0f0c148a504adee3b893423f0d4341aad03470f6c79b620b; express:sess=eyJrYnMiOiIsNzExMmQ1Yj15Y2VjZSZkYzA3OTdkZjMxN2YwMTE0YTUifQ==; express:sess.sig=ioeZRP1j19691rDqGo6ZOnjHTUQ' -H 'Host: note.wiz.cn' -H 'Referer: https://note.wiz.cn/web?dc=f2b91bc1-8d1d-46a1-aff4-7a43c44c28c5&cmd=kw%2C&kb=78125a1-97b6-441e-12c9-33e322a3ab1e' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:50.0) Gecko/20100101 Firefox/50.0' -H 'X-Requested-With: XMLHttpRequest'";
66 | $content = $autologin->execCurlWithCookie($curl);
67 | //锁定cookie
68 | $autologin->lockLastCookieFile();
69 |
70 | //替换为最新的token
71 | $tokenPattern = '#token=([^&]+)#';
72 | preg_match($tokenPattern, $curl, $tokenMatch);
73 | $noteUrl = preg_replace($tokenPattern, 'token=' . $tokenMatch[1], $noteUrl);
74 |
75 | //替换为最新的kb_guid
76 | $kbGuidPattern = '#kb_guid=([^&]+)#';
77 | preg_match($kbGuidPattern, $curl, $kbGuidMatch);
78 | $noteUrl = preg_replace($tokenPattern, 'kb_guid=' . $kbGuidMatch[1], $noteUrl);
79 |
80 | echo "正在下载笔记:{$noteUrl}\n";
81 |
82 | $noteContent = $autologin->getUrl($noteUrl);
83 |
84 | //使用文档id作为文件名
85 | preg_match('#document_guid=([^&]+)#', $noteUrl, $documentGuidMatch);
86 | $filename = $documentGuidMatch[1] . '.json';
87 |
88 | //存储笔记json
89 | file_put_contents($jsonDir . $filename, $noteContent);
90 | }
91 |
92 | //解析json存入html文件
93 | foreach(glob($jsonDir . '*.json') as $file) {
94 | $htmlFile = str_replace('/json/', '/html/', substr($file, 0, -4) . 'html');
95 | $content = file_get_contents($file);
96 | $dataArr = json_decode($content, true);
97 | if(empty($dataArr['document_info']['document_body'])) {
98 | echo "{$file} 无法解析,请确认是否为加密笔记,加密笔记无法下载内容。\n";
99 | continue;
100 | }
101 | $document = $dataArr['document_info']['document_body'];
102 | file_put_contents($htmlFile, $document);
103 | }
104 | die;
105 |
--------------------------------------------------------------------------------
/demo/19_www.tianyancha.com.php:
--------------------------------------------------------------------------------
1 | execCurl($curl);
28 | // var_dump($content);
29 |
30 | //2. 统计
31 | /*
32 | //对应js
33 | _tongJi = function(companyName, service, $q) {
34 | var deferred = $q.defer();
35 | return service.tongji(companyName).then(function(data) {
36 | for (var arr = data.data.data.v.split(","), fnStr = "", i = 0; i < arr.length; i++) fnStr += String.fromCharCode(arr[i]);
37 | eval(fnStr),
38 | deferred.resolve()
39 | },
40 | function(e) { (403 == e.status || 404 == e.status || 501 == e.status || 502 == e.status || 503 == e.status || 504 == e.status) && QueryService.errorMassageSend(e.status)
41 | }),
42 | deferred.promise
43 | }
44 | */
45 | $random = time() . rand(100,999);
46 | $curl = "curl 'http://www.tianyancha.com/tongji/{$searchKey}.json?random={$random}' -H 'Host: www.tianyancha.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Tyc-From: normal' -H 'Referer: http://www.tianyancha.com/search?key={$searchKey}&checkFrom=searchBox' -H 'Cookie: aliyungf_tc=AQAAAPZekiabgwQAyl8XDgCN/TtlujOh; TYCID=387bf43d7b7b483ebcdf4e877a912dc6; tnet=14.23.95.202; _pk_id.1.e431=06a39c0c47b56b73.1492395992.1.1492398258.1492395992.; _pk_ses.1.e431=*; gr_user_id=bea87b53-255e-4110-b23a-0be163ed57f1; gr_session_id_869c1f8ef123f88b=fe5a8a32-50d0-4eac-b30c-5c9c0c674712; Hm_lvt_e92c8d65d92d534b0fc290df538b4758=1492395993; Hm_lpvt_e92c8d65d92d534b0fc290df538b4758=1492398258; paaptp=dc8bd40bc98ddb35b74c80efedd60de3ed9ccf63c705bc19e815b79e5729b; token=b9bef624b51d4d278827803ed618f2b3; _utm=03492b4af4b3429ea43988dc944b8f43; _pk_id.6835.e431=1d6b2bfd25408756.1492396001.1.1492398258.1492396001.; _pk_ses.6835.e431=*; RTYCID=a5c8142e447f4601859c85d0ba826e29' -H 'Connection: keep-alive'";
47 | $content = $autologin->execCurl($curl);
48 | $dataArr = json_decode($content, true);
49 | $charsArr = explode(',', $dataArr['data']['v']);
50 | $realChar = '';
51 | foreach($charsArr as $char) {
52 | $realChar .= chr($char);
53 | }
54 | preg_match("#token=([^;]+)#", $realChar, $match);
55 | $token = $match[1];
56 |
57 | //3. 数据
58 | $curl = "curl 'http://www.tianyancha.com/v2/search/{$searchKey}.json?' -H 'Host: www.tianyancha.com' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Tyc-From: normal' -H 'loop: null' -H 'CheckError: check' -H 'Referer: http://www.tianyancha.com/search?key={$searchKey}&checkFrom=searchBox' -H 'Cookie: aliyungf_tc=AQAAAPZekiabgwQAyl8XDgCN/TtlujOh; TYCID=387bf43d7b7b483ebcdf4e877a912dc6; tnet=14.23.95.202; _pk_id.1.e431=06a39c0c47b56b73.1492395992.1.1492398732.1492395992.; _pk_ses.1.e431=*; gr_user_id=bea87b53-255e-4110-b23a-0be163ed57f1; gr_session_id_869c1f8ef123f88b=fe5a8a32-50d0-4eac-b30c-5c9c0c674712; Hm_lvt_e92c8d65d92d534b0fc290df538b4758=1492395993; Hm_lpvt_e92c8d65d92d534b0fc290df538b4758=1492398732; paaptp=4fd9f7303262c59b3d0fc19092ffd756ba8731bc790119a4fa15b79e573f9; token=669baeb13d1d4979b19ce6aa4d0164c2; _utm=e30a65104ce74c8a85a2d855cfcec817; _pk_id.6835.e431=1d6b2bfd25408756.1492396001.1.1492398258.1492396001.; _pk_ses.6835.e431=*; RTYCID=a5c8142e447f4601859c85d0ba826e29' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0'";
59 | $content = $autologin->execCurl($curl, function($parseCurlResult) use ($token) {
60 | $parseCurlResult['header'][] = "Cookie:token={$token}";
61 | return $parseCurlResult;
62 | });
63 |
64 | var_dump($content);
65 |
--------------------------------------------------------------------------------
/demo/16_commonCurl/curlPage.php:
--------------------------------------------------------------------------------
1 | $value) {
64 | curl_setopt($ch, $key, $value); //自定义OPT
65 | }
66 | }
67 | //执行
68 | $content = curl_exec($ch);
69 | if($error = curl_error($ch)) {
70 | //log error
71 | error_log($error);
72 | }
73 | curl_close($ch);
74 |
75 | return $content;
76 | }
77 |
78 | #测试http
79 | $url = 'http://api.zjmainstay.cn';
80 | echo "http url ok: ", curlPage($url) , "\n";
81 |
82 | #测试https
83 | $url = 'https://api.zjmainstay.cn';
84 | echo "https url ok: ", curlPage($url) , "\n";
85 |
86 | #测试缺少referere
87 | $url = 'http://demo.zjmainstay.cn/php/curl/search_refer.php';
88 | $post = array(
89 | 'wd' => urlencode('php'),
90 | );
91 | echo "no referer fail: ", substr(curlPage($url, $post), 0, 100) , "\n";
92 |
93 | #测试使用referer 和 post数据
94 | $url = 'http://demo.zjmainstay.cn/php/curl/search_refer.php';
95 | $post = array(
96 | 'wd' => urlencode('php'),
97 | );
98 | $header = array(
99 | 'Referer: http://demo.zjmainstay.cn/',
100 | );
101 | echo "referer in header ok: ", preg_replace('#\s+#', '', substr(curlPage($url, $post, $header), 0, 100)) , "\n";
102 |
103 | #测试超时
104 | $url = 'http://demo.zjmainstay.cn/php/curl/sleep3seconds.php';
105 | echo "timeout in 1's fail: ", substr(curlPage($url, $post, $header, array(), false, false, 1), 0, 100) , "\n";
106 |
107 | #测试gzip正常
108 | $url = 'http://news.sohu.com/';
109 | echo "gzip is ok: ", substr(curlPage($url), 0, 100) , "\n";
110 |
111 | #测试301正常(没有看到301 Move)
112 | $url = 'http://zjmainstay.cn';
113 | echo "301 is ok: ", substr(curlPage($url), 0, 100) , "\n";
114 |
115 | #测试存储cookie成功
116 | $url = 'http://demo.zjmainstay.cn/jquery/autoCheckCaptcha/createcode.php?t=' . rand(100000, 999999);
117 | $saveCookieFile = __DIR__ . '/curlPage.cookie.txt';
118 | if(file_exists($saveCookieFile)) { @unlink($saveCookieFile); }
119 | $imgContent = curlPage($url, false, false, array(), $saveCookieFile);
120 | $codeFile = __DIR__ . '/code.png';
121 | file_put_contents($codeFile, $imgContent);
122 | echo "save cookie is ok: ", file_get_contents($saveCookieFile) , "\n";
123 |
124 | echo "请输入一个验证码( {$codeFile} ):";
125 | $code = trim(fgets(STDIN));
126 |
127 | #测试使用cookie
128 | $url = 'http://demo.zjmainstay.cn/jquery/autoCheckCaptcha/checkcode.php';
129 | $post = array(
130 | 'code' => $code, //手动填写验证码并提交运行
131 | );
132 | echo "use cookie is ok when status=1: ", curlPage($url, $post, false, array(), false, $saveCookieFile) , "\n";
133 |
134 | #测试添加额外opt
135 | $url = 'http://zjmainstay.cn';
136 | $content = curlPage($url, array(), false, array(
137 | CURLOPT_FOLLOWLOCATION => FALSE,
138 | CURLOPT_HEADER => TRUE,
139 | ));
140 | echo "get url with no follow(302) and get header info: \n" , substr($content, 0, 200), "\n";
141 |
--------------------------------------------------------------------------------
/demo/parseCurlGetPhpCode.php:
--------------------------------------------------------------------------------
1 | 16384) {
100 | exit('curl内容过长');
101 | }
102 | if(!isset($_POST['withCookie'])) {
103 | $_POST['withCookie'] = false;
104 | }
105 | if(!isset($_POST['timeout']) || !abs((int)$_POST['timeout'])) {
106 | $_POST['timeout'] = 10;
107 | }
108 |
109 | if(empty($_POST['share'])) {
110 | highlight_string(parseCurlToCode($_POST['curl'], (bool)$_POST['withCookie'], $_POST['timeout']));
111 | exit;
112 | }
113 |
114 | //分享
115 | ob_start();
116 | highlight_string(parseCurlToCode($_POST['curl'], (bool)$_POST['withCookie'], $_POST['timeout']));
117 | $content = ob_get_contents();
118 | ob_clean();
119 |
120 | $filename = md5(implode('_', [$_POST['curl'], (int)$_POST['withCookie'], $_POST['timeout']])) . '.html';
121 |
122 | $dir = __DIR__ . '/parseCurlCode/' . date('Ymd/');
123 | if(!is_dir($dir)) {
124 | @mkdir($dir, 0777);
125 | }
126 |
127 | @file_put_contents( $dir . $filename, $content);
128 |
129 | header('Location: ./parseCurlCode/' . date('Ymd/') . $filename);
130 | exit;
131 | }
132 | ?>
133 |
134 |
135 |
136 |
137 | 基于cURL命令解析获得PHP代码
138 |
139 |
140 |
147 |
148 |
149 |
150 |
151 | 如何从浏览器获取cURL命令
152 |
153 | 利用浏览器的开发者工具(控制台),Firefox如下图:
154 |
155 |
156 |
157 |
158 | 更多PHP cURL内容,请查看博客《PHP cURL实现模拟登录与采集使用方法详解》
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # php-curl
2 | PHP利用cURL实现模拟登录与采集,提供大量示例。(关键词:php curl login)
3 |
4 | 了解PHP cURL使用请参考:《[PHP cURL实现模拟登录与采集使用方法详解](http://www.zjmainstay.cn/php-curl)》
5 |
6 | 基于浏览器cURL命令快速生成PHP代码:[基于cURL命令解析获得PHP代码](http://demo.zjmainstay.cn/php/github/php-curl/demo/parseCurlGetPhpCode.php)
7 |
8 | 自动模拟登录+批量请求示例:[模拟登录后批量下载笔记](https://github.com/Zjmainstay/php-curl/blob/master/demo/62_curlmulti/62_wiz.cn.php)
9 |
10 | ## 依赖
11 |
12 | PHP: >=5.4
13 |
14 | ## 单独使用
15 |
16 | ```php
17 | git clone https://github.com/Zjmainstay/php-curl.git
18 | cd php-curl
19 | composer install
20 | #测试
21 | php demo/1_simpleAutoLogin.php
22 | ```
23 |
24 | ## composer引入
25 |
26 | ```php
27 | composer require zjmainstay/php-curl
28 |
29 | #测试
30 | cd vendor/zjmainstay/php-curl
31 | composer install
32 | php demo/1_simpleAutoLogin.php
33 | ```
34 |
35 | ## 直接引入类
36 |
37 | ```php
38 | require_once __DIR__.'/../src/CurlAutoLogin.php'; # 使用时注意路径
39 | $autologin = new PHPCurl\CurlAutoLogin();
40 |
41 | # 参考demo/0_simpleAutoLogin.php
42 | ```
43 |
44 |
45 |
46 | ## CurlAutoLogin 介绍
47 |
48 | ### 属性
49 |
50 | ```php
51 | //最后一次cookie存储文件
52 | protected $lastCookieFile = '';
53 | //登录成功后,锁定cookie的更新
54 | protected $lockedLastCookieFile = false;
55 | //日志路径
56 | protected $logPath = '';
57 | //全局opt,方便使用代理之类的请求
58 | protected $globalOpts = [];
59 | //最后一次请求参数,用于重放请求
60 | protected $lastExecParams = [];
61 | ```
62 |
63 | ### 方法
64 |
65 | ```php
66 | // ================== 1.常用方法 ==================
67 | //根据curl信息执行并解析结果,核心方法常用方法之一
68 | public function execCurl($curlContent, $callbackBefore = false, $callbackAfter = false, $storeParams = true)
69 |
70 | //携带cookie执行curl命令,核心方法常用方法之一,直接利用curl命令里的header头cookie参数
71 | public function execCurlWithCookie($curlContent, $callbackBefore = false, $callbackAfter = false)
72 |
73 | // ================== 2.普通公用方法 ==================
74 | //设置全局请求opt(方便使用代理之类的请求)
75 | public function setGlobalOpts($opts = [])
76 |
77 | //重放请求,依赖登录的场景出现登录失败的情况,重新登录后,调用此方法重试上一次的请求
78 | public function repeatRequest()
79 |
80 | //获取最后一次请求参数,用于重放请求
81 | public function getLastExecParams()
82 |
83 | //主动销毁最后一次请求参数
84 | public function unsetLastExecParams()
85 |
86 | //解析curl信息,返回结果包含url/header/post/opt/cookie,post是post提交的数据,opt是curl备用扩展
87 | public function parseCurl($curlContent)
88 |
89 | //设置日志路径
90 | public function setLogPath($logPath)
91 |
92 | //获取上一次存储cookie的文件
93 | public function getLastCookieFile()
94 |
95 | //获取最后一次存储的cookie内容
96 | public function getLastCookieContent()
97 |
98 | //手动追加cookie内容到最后一次存储的cookie文件
99 | public function appendCookieContent($content)
100 |
101 | //设置上一次存储cookie的文件
102 | public function setLastCookieFile($cookieFile)
103 |
104 | //清空上次存储的cookie
105 | public function removeLastCookie()
106 |
107 | //登录成功后,锁定上一次存储cookie的文件,避免覆盖
108 | public function lockLastCookieFile()
109 |
110 | //解锁上一次存储cookie的文件
111 | public function unlockLastCookieFile()
112 |
113 | //登录成功后,锁定cookie,可以基于get方式获取url信息
114 | public function getUrl($url, $header = false)
115 |
116 | //登录成功后,锁定cookie,可以基于post方式获取url信息
117 | public function postUrl($url, $postData = false, $header = false)
118 |
119 | //断言内容中包含某个字符(判断登录信息,如“退出”字眼)
120 | public function assertContainStr($content, $substr)
121 |
122 | //获取换行符,用于输出信息显示换行
123 | public function getLineBreak()
124 |
125 | //格式化header头cookie成文件存储格式
126 | public function formatHeaderCookieToFileContent($headerCookie, $domain)
127 |
128 | //从curl内容解析cookie内容并追加保存到cookie文件
129 | public function addCookieFromCurl($curlContent, $domain)
130 |
131 | // ================== 3.底层方法 ==================
132 | //执行curl请求,底层核心方法,内置了请求的cookie存储与跟踪上一次请求的cookie,实现模拟登录cookie依赖
133 | protected function _execCurl($parseCurlResult)
134 |
135 | //记录日志,底层方法,出现异常时记录日志
136 | protected function _log($msg)
137 | ```
138 |
139 |
140 |
141 | ## demo介绍
142 |
143 | ```php
144 | //简易模拟登录示例,直接引用CurlAutoLogin类进行调用
145 | 0_simpleAutoLogin.php
146 |
147 | //简易模拟登录示例,基于composer引用CurlAutoLogin类进行调用
148 | //简介:包含execCurl回调$callbackBefore实现curl请求前替换用户名
149 | 1_simpleAutoLogin.php
150 |
151 | //浏览器登录微信,利用登录后cookie进行后续访问
152 | //简介:【代码已不可用,参考思路】
153 | //方法一:利用execCurl前置回调添加cookie到header中
154 | //方法二:直接调用parseCurl对curl命令进行解析,并组装包含cookie的header头进行请求
155 | //方法三:直接调用execCurlWithCookie调用
156 | 2_wxqq.php
157 |
158 | //预加载cookie,然后访问其他页面
159 | //简介:模拟登录有时候依赖首页或者其他页面的cookie,所以需要调用execCurl先请求一次,存下该页面的cookie,再做后续的请求
160 | 3_preloadCookieAndVisit.php
161 |
162 | //中国知网下载
163 | //简介:增加CURLOPT_HEADER属性返回请求头信息,然后解析下载地址进行下载请求
164 | 7_cnki.net.php
165 |
166 | //webqq发送消息
167 | //简介:【功能已不可用】基于web2 qq 发送群消息和个人消息(注:频繁发送会导致账号锁定,慎用!!!)
168 | 8_webqq.php
169 |
170 | //博客园模拟登录
171 | //简介:【网站改版,功能已不可用】
172 | //基于nodejs提供js加密处理,返回结果给php请求登录使用
173 | 11_cnblogLogin
174 |
175 | //(验证码)坐车网登录
176 | //简介:坐车网网页显示验证码,用户手动录入后提交给程序,实现模拟登录
177 | 12_zuocheWithCaptcha.php
178 |
179 | //模拟登录360doc
180 | //简介:360doc登录,中间有一层cookie依赖,类似demo 3_preloadCookieAndVisit.php
181 | 14_360doc.php
182 |
183 | //为知笔记内容下载
184 | //简介:利用js在控制台运行获取所有笔记采集链接,然后下载对应笔记
185 | 15_downloadWizNote.php
186 |
187 | //页面采集通用方法
188 | //简介:日常使用curl请求可用
189 | 16_commonCurl/curlPage.php
190 |
191 | //(验证码)命令行下输入验证码登录dev.360.cn
192 | //简介:命令行执行获取验证码,写入到文件,命令行等待录入验证码,录入后提交给程序,实现模拟登录
193 | 17_dev.360.cn_STDINCaptcha.php
194 |
195 | //天眼查关键词搜索
196 | //简介:【功能已不可用】天眼查关键词搜索,最终数据页有token依赖,提取后通过$callbackBefore传入
197 | 19_www.tianyancha.com.php
198 |
199 | //(验证码)木蚂蚁用户登录
200 | //简介:木蚂蚁用户登录,网页显示验证码,用户手动录入后提交给程序,实现模拟登录
201 | 20_u.mumayi.com_OnlineCaptcha.php
202 |
203 | //环球外汇网即时行情数据采集
204 | //简介:【页面改版已不需要这么复杂】
205 | //加载页面,解析出js,调用phantomjs执行js获取cookie加密结果,交给php模拟程序调用
206 | 22_tools.cnforex.com-phantomjs-parse-js.php
207 |
208 | //(验证码)好单库登录
209 | //简介:命令行执行获取验证码,写入到文件,命令行等待录入验证码,录入后提交给程序,实现模拟登录
210 | 26_publish.haodanku.com.php
211 |
212 | //阿里文学js解密
213 | //简介:阿里文学网小说解析,基于phantomjs执行js进行内容解析
214 | 34_www.aliwx.com.cn
215 |
216 | //图床图片上传
217 | //简介:【网站502功能已不可用】访问初始页获取x-csrf-token,解析后通过$callbackBefore传入,实现模拟请求上传图片到图床网站
218 | 38_upload.otar.im_image_upload.php
219 |
220 | //草料图片上传二维码解析
221 | //简介:上传图片到草料,然后利用上传结果调用解析接口,获得解析结果
222 | 41_cli.im.php
223 |
224 | //重放请求
225 | //简介:首先模拟无登录态请求,异常后模拟登录,然后重放请求得到正常结果
226 | 48_request_repeat.php
227 |
228 | //tophub.today抓取demo
229 | //简介:知乎热榜网站抓取
230 | 61_tophub.today.php
231 |
232 | //【精华推荐】为知笔记模拟登录后,批量下载笔记
233 | //简介:本示例实现模拟登录与ares333/php-curl批量执行类库结合,演示如何模拟登录后,基于登录态进行批量下载笔记
234 | 62_curlmulti/62_wiz.cn.php
235 |
236 | //基于curl解析得到PHP代码
237 | parseCurlGetPhpCode.php
238 |
239 | ```
240 |
241 |
--------------------------------------------------------------------------------
/demo/17_dev.360.cn_STDINCaptcha.php:
--------------------------------------------------------------------------------
1 | getLineBreak();
17 |
18 | $username = urlencode('100000@qq.com'); //登录邮箱
19 | $password = '密码加密串'; //利用浏览器登录后,复制加密密码串填入
20 |
21 | //0. 未登录
22 | $getDataUrl = "curl 'http://dev.360.cn/dev/getuser?callback=onData&_=1489659410069' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Cache-Control: max-age=0' -H 'Connection: keep-alive' -H 'Cookie: test_cookie_enable=null' -H 'Host: dev.360.cn' -H 'Referer: http://dev.360.cn/mod/developer/?_=186613593&from=mobile' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0'";
23 | echo 'Before Login: ' . $autologin->execCurl($getDataUrl) . $lineBreak;
24 |
25 | //1. 首页
26 | $curl1 = "curl 'http://dev.360.cn/' -H 'Host: dev.360.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'";
27 | $content = $autologin->execCurl($curl1);
28 |
29 | //2. 获取验证码链接
30 | $curl2 = "curl 'http://login.360.cn/?callback=jQuery19109780439789015878_1489658824142&src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=http&o=sso&m=checkNeedCaptcha&account=hzgdys%40163.com&captchaApp=i360&_=1489658824143' -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Host: login.360.cn' -H 'Referer: http://dev.360.cn/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0'";
31 | $content = $autologin->execCurl($curl2);
32 | $json = substr(str_replace('jQuery19109780439789015878_1489658824142(', '', $content), 0, -1);
33 | $jsonToArr = json_decode($json, true);
34 |
35 | $captchaUrl = $jsonToArr['captchaUrl'];
36 |
37 | //3. 读取验证码
38 | $curl3 = "curl '{$captchaUrl}' -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Host: passport.360.cn' -H 'Referer: http://dev.360.cn/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0'";
39 | $content = $autologin->execCurl($curl3);
40 | $codeFile = __DIR__ . '/code.png';
41 | file_put_contents($codeFile, $content);
42 | echo "请输入一个验证码( {$codeFile} ):";
43 | $captcha = trim(fgets(STDIN));
44 |
45 | //4. 获取token
46 | $curl4 = "curl 'https://login.360.cn/?func=jQuery19109780439789015878_1489658824142&src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=https&o=sso&m=getToken&userName={$username}&_=1489658824144' -H 'Host: login.360.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://dev.360.cn/' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Connection: keep-alive'";
47 | $content = $autologin->execCurl($curl4);
48 | $json = substr(str_replace('jQuery19109780439789015878_1489658824142(', '', $content), 0, -1);
49 | $jsonToArr = json_decode($json, true);
50 | $token = $jsonToArr['token'];
51 |
52 | //5. 提交
53 | $curl5 = "curl 'https://login.360.cn/' -H 'Host: login.360.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://dev.360.cn/' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Content-Type: application/x-www-form-urlencoded' --data 'src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=https&o=sso&m=login&lm=0&captFlag=1&rtype=data&validatelm=0&isKeepAlive=1&captchaApp=i360&userName={$username}&type=normal&account={$username}&password={$password}&captcha={$captcha}&token={$token}&proxy=http%3A%2F%2Fdev.360.cn%2Fpsp_jump.html&callback=QiUserJsonp658825108&func=QiUserJsonp658825108'";
54 | $content = $autologin->execCurl($curl5);
55 | // var_dump($content);
56 |
57 | //6. 回调1 login.360.cn
58 | $curl6 = "curl 'https://login.360.cn/?func=jQuery19109780439789015878_1489658824152&src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=https&o=sso&m=setcookie&s=c3k%3Ce%2CA%3Bgjhi3%3EtN-%7C+dHG*j*%22UkWCe%5Cw%7C_1rT%2BRGBZz%7Bqe%40m%60o%22s0!u)dr%3A8GOvKA_T%2B%23wA%3AgPKAJxN%2BH%7C%24aMR%5Cc_79ssF4k%3Ey+J(7!%24H1Jr%3EIbH%2F7%256s.RV%23%5Cdtc!pB%3A%3FBnh3gqq%5Dm!+T(ppp%2FS1SM%25_Jb4Rdx%3F8L%3DLyO8eyith_8F%5C-%7CCrcP*7%3BBFe%40z!hq%261%2B%3Fe%5D4am%7D)b%22A_%40%3F%3CbPjNx%26%7DFe(DPzLn%5C0z%2F&_=1489658824153' -H 'Host: login.360.cn' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0' -H 'Accept: */*' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://dev.360.cn/' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Connection: keep-alive'";
59 | $content = $autologin->execCurl($curl6);
60 |
61 | //7. 回调2 login.360.cn
62 | $curl7 = "curl 'http://login.360.cn/?callback=jQuery19109780439789015878_1489658824154&src=pcw_open_app&from=pcw_open_app&charset=UTF-8&requestScema=http&o=sso&m=info&show_name_flag=1&head_type=b&_=1489658824160' -H 'Accept: */*' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3' -H 'Connection: keep-alive' -H 'Cookie: __guid=69710341.1799766187254211600.1489658825084.8904' -H 'Host: login.360.cn' -H 'Referer: http://dev.360.cn/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:52.0) Gecko/20100101 Firefox/52.0'";
63 | $content = $autologin->execCurl($curl7);
64 | // var_dump($content);
65 |
66 | //8. 登录成功,锁定cookie的更新,直接访问已登录页面内容(类似采集内容),演示cookie锁定多次采集效果与cookie失效效果
67 | $autologin->lockLastCookieFile();
68 | echo 'After Login 1(with_cookie): ' . $autologin->execCurl($getDataUrl) . $lineBreak;
69 | $autologin->removeLastCookie();
70 | echo 'After Login 2(without_cookie): ' . $autologin->execCurl($getDataUrl) . $lineBreak;
71 |
--------------------------------------------------------------------------------
/demo/62_curlmulti/62_wiz.cn.php:
--------------------------------------------------------------------------------
1 | setLastCookieFile($loginCookieFile);
35 | $resArr = json_decode(file_get_contents($loginResultFile), true);
36 | }
37 |
38 | if(empty($resArr['result']['kbGuid'])) {
39 | exit("未登录成功,请检查帐号和密码是否正确\n");
40 | }
41 |
42 | $kbGuid = $resArr['result']['kbGuid'];
43 | $wizToken = $resArr['result']['token'];
44 |
45 | //加载全部笔记数据
46 | $size = 100;
47 | $i = 0;
48 | $docGuidArr = [];
49 | while(true){
50 | $start = $i * $size;
51 | $curl = <<execCurl($curl);
68 | $resArr = json_decode($content, true);
69 | //登录态丢失自动登录,然后返回重新请求
70 | if(isset($resArr['returnMessage']) && $resArr['returnMessage'] == 'Invalid token') {
71 | $resArr = doLogin($autoLogin, $username, $password, $loginResultFile, $loginCookieFile);
72 | if(empty($resArr['result']['kbGuid'])) {
73 | exit("未登录成功,请检查帐号和密码是否正确\n");
74 | }
75 | $kbGuid = $resArr['result']['kbGuid'];
76 | $wizToken = $resArr['result']['token'];
77 | continue;
78 | }
79 | if(empty($resArr['result'])) {
80 | break;
81 | }
82 | $docGuidArr = array_merge($docGuidArr, array_column($resArr['result'], 'title', 'docGuid'));
83 | // file_put_contents(__DIR__ . '/result.log', $content . "\n\n", 8);
84 | $i++;
85 | }
86 |
87 | //单个下载示例
88 | //测试下载460个文档,耗时370秒
89 | //$start = microtime(true);
90 | //echo "逐个请求,开始:" . date('Y-m-d H:i:s') . "\n";
91 | //foreach($docGuidArr as $docGuid => $title) {
92 | // $curl = <<execCurl($curl);
109 | // $resArr = json_decode($content, true);
110 | // $dir = __DIR__ . '/cache/type_1/' . ltrim($resArr['info']['category'], '/');
111 | // if(!is_dir($dir)) {
112 | // mkdir($dir, 0755, true);
113 | // }
114 | // if(!empty($resArr['html'])) {
115 | // file_put_contents($dir . str_replace("/", ":", $resArr['info']['title']), $resArr['html']);
116 | // } else {
117 | // echo "empty content: {$resArr['info']['category']}{$title}\n";
118 | // }
119 | //}
120 | //echo "逐个请求,结束:" . date('Y-m-d H:i:s') . "\n";
121 | //$timeCost = microtime(true) - $start;
122 | //echo "逐个请求,耗时:" . $timeCost . "秒 \n";
123 |
124 | //批量下载示例
125 | //测试下载460个文档,耗时45秒
126 | $multiStart = microtime(true);
127 | echo "批量请求,开始:" . date('Y-m-d H:i:s') . "\n";
128 |
129 | //解析下载url,获取url、header等信息,由于url是依赖每个笔记的ID,因此埋入一个替换标记[docGuid]
130 | $curl = <<parseCurl($curl);
146 |
147 | $multiCurl = new \Ares333\Curl\Curl();
148 | //回调打印最后一个下载完成的时间
149 | $multiCurl->onInfo = function($info, $_this, $isLast) {
150 | global $multiStart;
151 | if($isLast) {
152 | echo "批量请求,结束:" . date('Y-m-d H:i:s') . "\n";
153 | $timeCost = microtime(true) - $multiStart;
154 | echo "批量请求,耗时:" . $timeCost . "秒 \n";
155 | }
156 | };
157 | $docCount = count($docGuidArr);
158 | echo "开始下载文档,共{$docCount}个\n";
159 | $index = 0;
160 | //把全部下载地址加入批量下载队列
161 | foreach ($docGuidArr as $docGuid => $title) {
162 | //替换文档ID变量,得到真实下载地址
163 | $url = str_replace('[docGuid]', $docGuid, $curlInfo['url']);
164 | //加入下载队列
165 | $multiCurl->add([
166 | 'opt' => array(
167 | CURLOPT_URL => $url, //指定下载地址
168 | CURLOPT_HTTPHEADER => $curlInfo['header'], //引用下载header参数
169 | CURLOPT_COOKIEFILE => $autoLogin->getLastCookieFile(), //引用前面模拟登录的cookie
170 | CURLOPT_RETURNTRANSFER => true, //抓取结果不直接输出,返回内容
171 | ),
172 | 'args' => [ //下载完成回调参数,传入一下后续要用的参数,方便打印记录
173 | 'index' => $index + 1,
174 | 'title' => $title,
175 | ],
176 | ], 'parseDocResult');
177 | $index++;
178 | }
179 | //开始下载
180 | $multiCurl->start();
181 |
182 | //功能函数
183 | /**
184 | * 文档下载结果解析
185 | * @param $r
186 | * @param $args
187 | */
188 | function parseDocResult($r, $args) {
189 | if($r['info']['http_code'] == 200) {
190 | $resArr = json_decode($r['body'], true);
191 | $dir = __DIR__ . '/cache/type_2/' . ltrim($resArr['info']['category'], '/');
192 | if (!is_dir($dir)) {
193 | mkdir($dir, 0755, true);
194 | }
195 | if(!empty($resArr['html'])) {
196 | echo "下载第[{$args['index']}]个文档: {$resArr['info']['category']}{$args['title']}\n";
197 | file_put_contents($dir . str_replace("/", ":", $resArr['info']['title']), $resArr['html']);
198 | } else {
199 | echo "下载第[{$args['index']}]个文档: {$resArr['info']['category']}{$args['title']},无内容\n";
200 | }
201 | } else {
202 | echo "fail {$r['info']['url']}\n";
203 | }
204 | }
205 |
206 | /**
207 | * 执行登录
208 | * @param $username
209 | * @param $password
210 | */
211 | function doLogin($autoLogin, $username, $password, $loginResultFile, $loginCookieFile)
212 | {
213 | echo "无登录态,模拟登录...\n";
214 | $curl = <<execCurl($curl);
234 | $resArr = json_decode($content, true);
235 | file_put_contents($loginResultFile, $content); //存储登录结果
236 | file_put_contents($loginCookieFile, $autoLogin->getLastCookieContent()); //存储登录后的cookie
237 |
238 | return $resArr;
239 | }
240 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/src/CurlAutoLogin.php:
--------------------------------------------------------------------------------
1 | removeCookieFileAtDestruct = $removeCookieFileAtDestruct;
27 | if(!empty($logPath) && is_writable($logPath)) {
28 | $this->logPath = $logPath;
29 | } else {
30 | $this->logPath = dirname(__FILE__) . '/../logs/run.log';
31 | if(!file_exists($this->logPath)) {
32 | if(!is_dir(dirname($this->logPath))) {
33 | mkdir(dirname($this->logPath), 0755, true);
34 | }
35 | }
36 | }
37 | }
38 |
39 | //程序退出销毁处理
40 | public function __destruct()
41 | {
42 | //如果设置了清理cookie文件
43 | if($this->removeCookieFileAtDestruct && file_exists($this->getLastCookieFile())) {
44 | unlink($this->getLastCookieFile());
45 | }
46 | }
47 |
48 | /**
49 | * 设置全局请求opt(方便使用代理之类的请求)
50 | * @param $opts
51 | */
52 | public function setGlobalOpts($opts = [])
53 | {
54 | $this->globalOpts += $opts;
55 | return $this;
56 | }
57 |
58 | /**
59 | * 根据curl信息执行并解析结果,核心方法常用方法之一
60 | * @param string $curlContent 利用Firefox浏览器复制cURL命令
61 | * @param boolean $callbackBefore 对curl结果前置处理,如更换用户名、密码等
62 | * @param boolean $callbackAfter 对采集结果后置处理,如解析结果的csrf token等
63 | * @param boolean $storeParams 是否存储最后请求参数供重放使用,默认存储
64 | * @return mixed
65 | */
66 | public function execCurl($curlContent, $callbackBefore = false, $callbackAfter = false, $storeParams = true) {
67 | //存储参数供请求重放使用
68 | if($storeParams) {
69 | $this->lastExecParams = func_get_args();
70 | }
71 | $parseCurlResult = $this->parseCurl($curlContent);
72 | if(is_callable($callbackBefore)) {
73 | $parseCurlResult = $callbackBefore($parseCurlResult);
74 | }
75 | $parseCurlResult['opt'] += $this->globalOpts;
76 | $execCurlResult = $this->_execCurl($parseCurlResult);
77 |
78 | if(is_callable($callbackAfter)) {
79 | $execCurlResult = $callbackAfter($parseCurlResult, $execCurlResult);
80 | }
81 |
82 | return $execCurlResult;
83 | }
84 |
85 | /**
86 | * 携带cookie执行curl命令,核心方法常用方法之一,直接利用curl命令里的header头cookie参数
87 | * @param string $curlContent 利用Firefox浏览器复制cURL命令
88 | * @param boolean $callbackBefore 对curl结果前置处理,如更换用户名、密码等
89 | * @param boolean $callbackAfter 对采集结果后置处理,如解析结果的csrf token等
90 | * @return mixed
91 | */
92 | public function execCurlWithCookie($curlContent, $callbackBefore = false, $callbackAfter = false) {
93 | return $this->execCurl($curlContent, function($parseCurlResult) use ($callbackBefore) {
94 | $parseCurlResult['header'][] = $parseCurlResult['cookie'];
95 | if(is_callable($callbackBefore)) {
96 | $parseCurlResult = $callbackBefore($parseCurlResult);
97 | }
98 | return $parseCurlResult;
99 | }, $callbackAfter);
100 | }
101 |
102 | /**
103 | * 重放请求,依赖登录的场景出现登录失败的情况,重新登录后,调用此方法重试上一次的请求
104 | * @return mixed
105 | */
106 | public function repeatRequest()
107 | {
108 | //最后一次请求参数不为空才重放
109 | if(!empty($this->lastExecParams)) {
110 | list($curlContent, $callbackBefore, $callbackAfter) = array_pad($this->lastExecParams, 3, false);
111 | return $this->execCurl($curlContent, $callbackBefore, $callbackAfter, true);
112 | }
113 | return null;
114 | }
115 |
116 | /**
117 | * 获取最后一次请求参数
118 | * @return array
119 | */
120 | public function getLastExecParams()
121 | {
122 | return $this->lastExecParams;
123 | }
124 |
125 | /**
126 | * 主动销毁最后一次请求参数
127 | * @return $this
128 | */
129 | public function unsetLastExecParams()
130 | {
131 | $this->lastExecParams = [];
132 | return $this;
133 | }
134 |
135 | /**
136 | * 解析curl信息
137 | * @param string $curlContent 利用Firefox浏览器复制cURL命令
138 | * @return bool|array
139 | */
140 | public function parseCurl($curlContent) {
141 | if(!preg_match("#curl '([^']*)'#is", $curlContent, $matchUrl)
142 | && !preg_match("#curl.*'([^']*)'\s*$#is", $curlContent, $matchUrl)
143 | ) {
144 | return false;
145 | }
146 |
147 | //get cookie
148 | if(!preg_match("#-H '(Cookie:[^']*)'#is", $curlContent, $cookieMatch)) {
149 | $cookieData = '';
150 | } else {
151 | $cookieData = $cookieMatch[1];
152 | }
153 |
154 | //兼容 -b 参数
155 | if(empty($cookieData) && preg_match("#-b '([^']*)'#is", $curlContent, $cookieMatch)) {
156 | $cookieData = "Cookie: " . $cookieMatch[1];
157 | }
158 |
159 | //remove cookie data in header
160 | $curlContent = preg_replace("#-H 'Cookie:[^']*'#is", '', $curlContent);
161 |
162 | //get header
163 | if(!preg_match_all("#-H '([^']*)'#is", $curlContent, $headerMatches)) {
164 | $httpHeader = array();
165 | } else {
166 | $httpHeader = $headerMatches[1];
167 | }
168 |
169 | //get data
170 | //单引号
171 | if(!preg_match("#(?:--data\S*|-d) \\$?'([^']*)'#is", $curlContent, $postDataMatch)) {
172 | //双引号
173 | if(!preg_match('#(?:--data\S*|-d) \\$?"([^"]*)"#is', $curlContent, $postDataMatch)) {
174 | $postDataMatch[1] = '';
175 | }
176 | }
177 | $postData = $postDataMatch[1];
178 |
179 | return array(
180 | 'url' => $matchUrl[1],
181 | 'header' => $httpHeader,
182 | 'post' => $postData,
183 | 'opt' => array(), //扩展opt,在callbackBefore里添加
184 | 'cookie' => $cookieData,
185 | );
186 | }
187 |
188 | /**
189 | * 执行curl请求
190 | * @param array $parseCurlResult curl信息的解析结果,包含 url/header/post 三个键值参数
191 | * @return string
192 | */
193 | protected function _execCurl($parseCurlResult) {
194 | if(empty($parseCurlResult['url'])) {
195 | return '';
196 | }
197 |
198 | $ch = curl_init($parseCurlResult['url']);
199 | curl_setopt($ch,CURLOPT_HEADER,0);
200 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回数据不直接输出
201 | curl_setopt($ch, CURLOPT_ENCODING, "gzip"); //指定gzip压缩
202 |
203 | //add header
204 | if(!empty($parseCurlResult['header'])) {
205 | curl_setopt($ch, CURLOPT_HTTPHEADER, $parseCurlResult['header']);
206 | }
207 |
208 | //add ssl support
209 | if(substr($parseCurlResult['url'], 0, 5) == 'https') {
210 | // curl_setopt($ch, CURLOPT_SSLVERSION,1); //error:14077458:SSL routines:SSL23_GET_SERVER_HELLO:reason(1112)
211 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //SSL 报错时使用
212 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //SSL 报错时使用
213 | }
214 |
215 | //add 302 support
216 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
217 |
218 | //add cookie support
219 | $cookieFile = $this->getTempFile();
220 | curl_setopt($ch,CURLOPT_COOKIEJAR,$cookieFile); //存储提交后得到的cookie数据
221 |
222 | //add previous curl cookie
223 | if($this->getLastCookieFile()) {
224 | curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据
225 | }
226 |
227 | //add post data support
228 | if(!empty($parseCurlResult['post'])) {
229 | curl_setopt($ch,CURLOPT_POST, 1);
230 | curl_setopt($ch,CURLOPT_POSTFIELDS, $parseCurlResult['post']);
231 | }
232 |
233 | //extend opt
234 | if(!empty($parseCurlResult['opt'])) {
235 | foreach ($parseCurlResult['opt'] as $key => $value) {
236 | curl_setopt($ch, $key, $value);
237 | }
238 | }
239 |
240 | $content = '';
241 | try {
242 | $content = curl_exec($ch); //执行并存储结果
243 | } catch (\Exception $e) {
244 | $this->_log($e->getMessage());
245 | }
246 |
247 | $curlError = curl_error($ch);
248 | if(!empty($curlError)) {
249 | $this->_log($curlError);
250 | }
251 |
252 | curl_close($ch);
253 |
254 | //update last cookie file
255 | $this->setLastCookieFile($cookieFile);
256 |
257 | return $content;
258 | }
259 |
260 | /**
261 | * 设置日志路径
262 | * @param string $logPath 绝对路径,必须可写
263 | */
264 | public function setLogPath($logPath) {
265 | $this->logPath = $logPath;
266 | return $this;
267 | }
268 |
269 | /**
270 | * 记录日志
271 | * @param [type] $msg [description]
272 | * @return [type] [description]
273 | */
274 | protected function _log($msg) {
275 | try {
276 | $res = file_put_contents($this->logPath, $msg . "\n", FILE_APPEND);
277 | } catch (\Exception $e) {
278 | error_log("CurlAutoLogin 无法写入日志文件 {$this->logPath}: {$msg}");
279 | }
280 | }
281 |
282 | /**
283 | * 获取上一次存储cookie的文件
284 | * @return [type] [description]
285 | */
286 | public function getLastCookieFile() {
287 | return $this->lastCookieFile;
288 | }
289 |
290 | /**
291 | * 获取最后一次存储的cookie内容
292 | * @return string
293 | */
294 | public function getLastCookieContent() {
295 | if($file = $this->getLastCookieFile()) {
296 | if(file_exists($file)) {
297 | return file_get_contents($file);
298 | }
299 | }
300 | return '';
301 | }
302 |
303 | /**
304 | * 手动追加cookie内容到最后一次存储的cookie文件
305 | * @param string $content
306 | * @param bool $init
307 | * @return bool|int
308 | */
309 | public function appendCookieContent($content, $init = true)
310 | {
311 | if(file_exists($file = $this->getLastCookieFile()) || $init) {
312 | //初始cookie文件
313 | if(empty($file)) {
314 | $file = $this->getTempFile();
315 | if(!$file) {
316 | return false;
317 | }
318 | $this->setLastCookieFile($file);
319 | }
320 | return file_put_contents($file, $content . "\n", FILE_APPEND);
321 | }
322 | return false;
323 | }
324 |
325 | /**
326 | * 获取临时文件
327 | * @return false|string
328 | */
329 | public function getTempFile() {
330 | $file = tempnam(dirname($this->logPath), 'autologin_cookie_');
331 | if(!$file) {
332 | $this->_log("tempnam创建临时文件失败,请检查");
333 | return false;
334 | }
335 | return $file;
336 | }
337 |
338 | /**
339 | * 设置上一次存储cookie的文件
340 | * @param [type] $cookieFile [description]
341 | */
342 | public function setLastCookieFile($cookieFile) {
343 | if(!$this->lockedLastCookieFile) {
344 | //移除上一个存储cookie的临时文件
345 | if(file_exists($this->lastCookieFile) && $this->lastCookieFile != $cookieFile) {
346 | unlink($this->lastCookieFile);
347 | }
348 | $this->lastCookieFile = $cookieFile;
349 | }
350 | return $this;
351 | }
352 |
353 | /**
354 | * 清空上次存储的cookie
355 | */
356 | public function removeLastCookie() {
357 | if($file = $this->getLastCookieFile()) {
358 | //文件存在才清空
359 | if(file_exists($file)) {
360 | file_put_contents($file, '');
361 | }
362 | }
363 | return $this;
364 | }
365 |
366 | /**
367 | * 登录成功后,锁定上一次存储cookie的文件,避免覆盖
368 | * @return [type] [description]
369 | */
370 | public function lockLastCookieFile() {
371 | $this->lockedLastCookieFile = true;
372 | return $this;
373 | }
374 |
375 | /**
376 | * 解锁上一次存储cookie的文件
377 | * @return [type] [description]
378 | */
379 | public function unlockLastCookieFile() {
380 | $this->lockedLastCookieFile = false;
381 | return $this;
382 | }
383 |
384 | /**
385 | * 登录成功后,锁定cookie,可以基于get方式获取url信息
386 | * @param [type] $url [description]
387 | * @param boolean $header [description]
388 | * @param array $opts [description]
389 | * @return [type] [description]
390 | */
391 | public function getUrl($url, $header = false, $opts = []) {
392 | $ch = curl_init($url);
393 | curl_setopt($ch,CURLOPT_HEADER,0);
394 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回数据不直接输出
395 | curl_setopt($ch, CURLOPT_ENCODING, "gzip"); //指定gzip压缩
396 |
397 | //add header
398 | if(!empty($header)) {
399 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
400 | }
401 |
402 | //add ssl support
403 | if(substr($url, 0, 5) == 'https') {
404 | // curl_setopt($ch, CURLOPT_SSLVERSION,1);
405 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //SSL 报错时使用
406 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //SSL 报错时使用
407 | }
408 |
409 | //add 302 support
410 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
411 |
412 | curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据
413 |
414 | //extend opt
415 | $opts += $this->globalOpts;
416 | if(!empty($opts)) {
417 | foreach ($opts as $key => $value) {
418 | curl_setopt($ch, $key, $value);
419 | }
420 | }
421 |
422 | $content = '';
423 | try {
424 | $content = curl_exec($ch); //执行并存储结果
425 | } catch (\Exception $e) {
426 | $this->_log($e->getMessage());
427 | }
428 |
429 | $curlError = curl_error($ch);
430 | if(!empty($curlError)) {
431 | $this->_log($curlError);
432 | }
433 |
434 | curl_close($ch);
435 |
436 | return $content;
437 | }
438 |
439 | /**
440 | * 登录成功后,锁定cookie,可以基于post方式获取url信息
441 | * @param [type] $url [description]
442 | * @param boolean $postData [description]
443 | * @param boolean $header [description]
444 | * @param array $opts [description]
445 | * @return [type] [description]
446 | */
447 | public function postUrl($url, $postData = false, $header = false, $opts = []) {
448 | $ch = curl_init($url);
449 | curl_setopt($ch,CURLOPT_HEADER,0);
450 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回数据不直接输出
451 | curl_setopt($ch, CURLOPT_ENCODING, "gzip"); //指定gzip压缩
452 |
453 | //add header
454 | if(!empty($header)) {
455 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
456 | }
457 |
458 | //add ssl support
459 | if(substr($url, 0, 5) == 'https') {
460 | // curl_setopt($ch, CURLOPT_SSLVERSION,1);
461 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //SSL 报错时使用
462 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //SSL 报错时使用
463 | }
464 |
465 | //add 302 support
466 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
467 |
468 | curl_setopt($ch,CURLOPT_COOKIEFILE, $this->getLastCookieFile()); //使用提交后得到的cookie数据
469 |
470 | //add post data support
471 | curl_setopt($ch,CURLOPT_POST, 1);
472 | if(!empty($postData)) {
473 | curl_setopt($ch,CURLOPT_POSTFIELDS, $postData);
474 | }
475 |
476 | //extend opt
477 | $opts += $this->globalOpts;
478 | if(!empty($opts)) {
479 | foreach ($opts as $key => $value) {
480 | curl_setopt($ch, $key, $value);
481 | }
482 | }
483 |
484 | $content = '';
485 | try {
486 | $content = curl_exec($ch); //执行并存储结果
487 | } catch (\Exception $e) {
488 | $this->_log($e->getMessage());
489 | }
490 |
491 | $curlError = curl_error($ch);
492 | if(!empty($curlError)) {
493 | $this->_log($curlError);
494 | }
495 |
496 | curl_close($ch);
497 |
498 | return $content;
499 | }
500 |
501 | /**
502 | * 断言内容中包含某个字符(判断登录信息,如“退出”字眼)
503 | * @param string $content 内容
504 | * @param string $subStr 包含字符串
505 | */
506 | public function assertContainStr($content, $subStr) {
507 | if(false !== stripos($content, $subStr)) {
508 | return true;
509 | }
510 |
511 | return false;
512 | }
513 |
514 | /**
515 | * 获取换行符
516 | */
517 | public function getLineBreak() {
518 | if('cli' == PHP_SAPI) {
519 | $lineBreak = "\n";
520 | } else {
521 | $lineBreak = " ";
522 | }
523 |
524 | return $lineBreak;
525 | }
526 |
527 | /**
528 | * 格式化header头cookie成文件存储格式
529 | * @param string $headerCookie //-H 'Cookie: xxxxx=xxxx;',单引号内容
530 | * @param string $domain //授权域名,如www.baidu.com,则传入.baidu.com,根前面有个点
531 | */
532 | public function formatHeaderCookieToFileContent($headerCookie, $domain) {
533 | $rows = [];
534 | if(preg_match_all("#([^ ;]+)=([^ ;]+)#i", $headerCookie, $matches)) {
535 | foreach($matches[0] as $key => $value) {
536 | $rows[] = sprintf("#HttpOnly_%s\tTRUE\t/\tFALSE\t0\t%s\t%s", $domain, $matches[1][$key], $matches[2][$key]);
537 | }
538 | }
539 | return implode("\n", $rows);
540 | }
541 |
542 | /**
543 | * 从curl内容解析cookie内容并追加保存到cookie文件
544 | * @param $curlContent string
545 | * @param $domain string //授权域名,如www.baidu.com,则传入.baidu.com,根前面有个点
546 | */
547 | public function addCookieFromCurl($curlContent, $domain) {
548 | $parseCurlResult = $this->parseCurl($curlContent); //解析curl内容获取cookie内容
549 | $cookieContent = $this->formatHeaderCookieToFileContent($parseCurlResult["cookie"], $domain); //格式化cookie内容
550 | $this->appendCookieContent($cookieContent); //追加cookie内容到cookie文件
551 | }
552 | }
553 |
--------------------------------------------------------------------------------
/demo/11_cnblogLogin/jsencrypt.min.js:
--------------------------------------------------------------------------------
1 | var JSEncryptExports = {};
2 | (function(exports) {
3 | function BigInteger(a,b,c){null!=a&&("number"==typeof a?this.fromNumber(a,b,c):null==b&&"string"!=typeof a?this.fromString(a,256):this.fromString(a,b))}function nbi(){return new BigInteger(null)}function am1(a,b,c,d,e,f){for(;--f>=0;){var g=b*this[a++]+c[d]+e;e=Math.floor(g/67108864),c[d++]=67108863&g}return e}function am2(a,b,c,d,e,f){for(var g=32767&b,h=b>>15;--f>=0;){var i=32767&this[a],j=this[a++]>>15,k=h*i+j*g;i=g*i+((32767&k)<<15)+c[d]+(1073741823&e),e=(i>>>30)+(k>>>15)+h*j+(e>>>30),c[d++]=1073741823&i}return e}function am3(a,b,c,d,e,f){for(var g=16383&b,h=b>>14;--f>=0;){var i=16383&this[a],j=this[a++]>>14,k=h*i+j*g;i=g*i+((16383&k)<<14)+c[d]+e,e=(i>>28)+(k>>14)+h*j,c[d++]=268435455&i}return e}function int2char(a){return BI_RM.charAt(a)}function intAt(a,b){var c=BI_RC[a.charCodeAt(b)];return null==c?-1:c}function bnpCopyTo(a){for(var b=this.t-1;b>=0;--b)a[b]=this[b];a.t=this.t,a.s=this.s}function bnpFromInt(a){this.t=1,this.s=0>a?-1:0,a>0?this[0]=a:-1>a?this[0]=a+DV:this.t=0}function nbv(a){var b=nbi();return b.fromInt(a),b}function bnpFromString(a,b){var c;if(16==b)c=4;else if(8==b)c=3;else if(256==b)c=8;else if(2==b)c=1;else if(32==b)c=5;else{if(4!=b)return void this.fromRadix(a,b);c=2}this.t=0,this.s=0;for(var d=a.length,e=!1,f=0;--d>=0;){var g=8==c?255&a[d]:intAt(a,d);0>g?"-"==a.charAt(d)&&(e=!0):(e=!1,0==f?this[this.t++]=g:f+c>this.DB?(this[this.t-1]|=(g&(1<>this.DB-f):this[this.t-1]|=g<=this.DB&&(f-=this.DB))}8==c&&0!=(128&a[0])&&(this.s=-1,f>0&&(this[this.t-1]|=(1<0&&this[this.t-1]==a;)--this.t}function bnToString(a){if(this.s<0)return"-"+this.negate().toString(a);var b;if(16==a)b=4;else if(8==a)b=3;else if(2==a)b=1;else if(32==a)b=5;else{if(4!=a)return this.toRadix(a);b=2}var c,d=(1<0)for(h>h)>0&&(e=!0,f=int2char(c));g>=0;)b>h?(c=(this[g]&(1<>(h+=this.DB-b)):(c=this[g]>>(h-=b)&d,0>=h&&(h+=this.DB,--g)),c>0&&(e=!0),e&&(f+=int2char(c));return e?f:"0"}function bnNegate(){var a=nbi();return BigInteger.ZERO.subTo(this,a),a}function bnAbs(){return this.s<0?this.negate():this}function bnCompareTo(a){var b=this.s-a.s;if(0!=b)return b;var c=this.t;if(b=c-a.t,0!=b)return this.s<0?-b:b;for(;--c>=0;)if(0!=(b=this[c]-a[c]))return b;return 0}function nbits(a){var b,c=1;return 0!=(b=a>>>16)&&(a=b,c+=16),0!=(b=a>>8)&&(a=b,c+=8),0!=(b=a>>4)&&(a=b,c+=4),0!=(b=a>>2)&&(a=b,c+=2),0!=(b=a>>1)&&(a=b,c+=1),c}function bnBitLength(){return this.t<=0?0:this.DB*(this.t-1)+nbits(this[this.t-1]^this.s&this.DM)}function bnpDLShiftTo(a,b){var c;for(c=this.t-1;c>=0;--c)b[c+a]=this[c];for(c=a-1;c>=0;--c)b[c]=0;b.t=this.t+a,b.s=this.s}function bnpDRShiftTo(a,b){for(var c=a;c=0;--c)b[c+g+1]=this[c]>>e|h,h=(this[c]&f)<=0;--c)b[c]=0;b[g]=h,b.t=this.t+g+1,b.s=this.s,b.clamp()}function bnpRShiftTo(a,b){b.s=this.s;var c=Math.floor(a/this.DB);if(c>=this.t)return void(b.t=0);var d=a%this.DB,e=this.DB-d,f=(1<>d;for(var g=c+1;g>d;d>0&&(b[this.t-c-1]|=(this.s&f)<c;)d+=this[c]-a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t>=this.DB;d+=this.s}else{for(d+=this.s;c>=this.DB;d-=a.s}b.s=0>d?-1:0,-1>d?b[c++]=this.DV+d:d>0&&(b[c++]=d),b.t=c,b.clamp()}function bnpMultiplyTo(a,b){var c=this.abs(),d=a.abs(),e=c.t;for(b.t=e+d.t;--e>=0;)b[e]=0;for(e=0;e=0;)a[c]=0;for(c=0;c=b.DV&&(a[c+b.t]-=b.DV,a[c+b.t+1]=1)}a.t>0&&(a[a.t-1]+=b.am(c,b[c],a,2*c,0,1)),a.s=0,a.clamp()}function bnpDivRemTo(a,b,c){var d=a.abs();if(!(d.t<=0)){var e=this.abs();if(e.t0?(d.lShiftTo(i,f),e.lShiftTo(i,c)):(d.copyTo(f),e.copyTo(c));var j=f.t,k=f[j-1];if(0!=k){var l=k*(1<1?f[j-2]>>this.F2:0),m=this.FV/l,n=(1<=0&&(c[c.t++]=1,c.subTo(r,c)),BigInteger.ONE.dlShiftTo(j,r),r.subTo(f,f);f.t=0;){var s=c[--p]==k?this.DM:Math.floor(c[p]*m+(c[p-1]+o)*n);if((c[p]+=f.am(0,s,c,q,0,j))0&&c.rShiftTo(i,c),0>g&&BigInteger.ZERO.subTo(c,c)}}}function bnMod(a){var b=nbi();return this.abs().divRemTo(a,null,b),this.s<0&&b.compareTo(BigInteger.ZERO)>0&&a.subTo(b,b),b}function Classic(a){this.m=a}function cConvert(a){return a.s<0||a.compareTo(this.m)>=0?a.mod(this.m):a}function cRevert(a){return a}function cReduce(a){a.divRemTo(this.m,null,a)}function cMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function cSqrTo(a,b){a.squareTo(b),this.reduce(b)}function bnpInvDigit(){if(this.t<1)return 0;var a=this[0];if(0==(1&a))return 0;var b=3&a;return b=b*(2-(15&a)*b)&15,b=b*(2-(255&a)*b)&255,b=b*(2-((65535&a)*b&65535))&65535,b=b*(2-a*b%this.DV)%this.DV,b>0?this.DV-b:-b}function Montgomery(a){this.m=a,this.mp=a.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<0&&this.m.subTo(b,b),b}function montRevert(a){var b=nbi();return a.copyTo(b),this.reduce(b),b}function montReduce(a){for(;a.t<=this.mt2;)a[a.t++]=0;for(var b=0;b>15)*this.mpl&this.um)<<15)&a.DM;for(c=b+this.m.t,a[c]+=this.m.am(0,d,a,b,0,this.m.t);a[c]>=a.DV;)a[c]-=a.DV,a[++c]++}a.clamp(),a.drShiftTo(this.m.t,a),a.compareTo(this.m)>=0&&a.subTo(this.m,a)}function montSqrTo(a,b){a.squareTo(b),this.reduce(b)}function montMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function bnpIsEven(){return 0==(this.t>0?1&this[0]:this.s)}function bnpExp(a,b){if(a>4294967295||1>a)return BigInteger.ONE;var c=nbi(),d=nbi(),e=b.convert(this),f=nbits(a)-1;for(e.copyTo(c);--f>=0;)if(b.sqrTo(c,d),(a&1<0)b.mulTo(d,e,c);else{var g=c;c=d,d=g}return b.revert(c)}function bnModPowInt(a,b){var c;return c=256>a||b.isEven()?new Classic(b):new Montgomery(b),this.exp(a,c)}function bnClone(){var a=nbi();return this.copyTo(a),a}function bnIntValue(){if(this.s<0){if(1==this.t)return this[0]-this.DV;if(0==this.t)return-1}else{if(1==this.t)return this[0];if(0==this.t)return 0}return(this[1]&(1<<32-this.DB)-1)<>24}function bnShortValue(){return 0==this.t?this.s:this[0]<<16>>16}function bnpChunkSize(a){return Math.floor(Math.LN2*this.DB/Math.log(a))}function bnSigNum(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1}function bnpToRadix(a){if(null==a&&(a=10),0==this.signum()||2>a||a>36)return"0";var b=this.chunkSize(a),c=Math.pow(a,b),d=nbv(c),e=nbi(),f=nbi(),g="";for(this.divRemTo(d,e,f);e.signum()>0;)g=(c+f.intValue()).toString(a).substr(1)+g,e.divRemTo(d,e,f);return f.intValue().toString(a)+g}function bnpFromRadix(a,b){this.fromInt(0),null==b&&(b=10);for(var c=this.chunkSize(b),d=Math.pow(b,c),e=!1,f=0,g=0,h=0;hi?"-"==a.charAt(h)&&0==this.signum()&&(e=!0):(g=b*g+i,++f>=c&&(this.dMultiply(d),this.dAddOffset(g,0),f=0,g=0))}f>0&&(this.dMultiply(Math.pow(b,f)),this.dAddOffset(g,0)),e&&BigInteger.ZERO.subTo(this,this)}function bnpFromNumber(a,b,c){if("number"==typeof b)if(2>a)this.fromInt(1);else for(this.fromNumber(a,c),this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);!this.isProbablePrime(b);)this.dAddOffset(2,0),this.bitLength()>a&&this.subTo(BigInteger.ONE.shiftLeft(a-1),this);else{var d=new Array,e=7&a;d.length=(a>>3)+1,b.nextBytes(d),e>0?d[0]&=(1<0)for(d>d)!=(this.s&this.DM)>>d&&(b[e++]=c|this.s<=0;)8>d?(c=(this[a]&(1<>(d+=this.DB-8)):(c=this[a]>>(d-=8)&255,0>=d&&(d+=this.DB,--a)),0!=(128&c)&&(c|=-256),0==e&&(128&this.s)!=(128&c)&&++e,(e>0||c!=this.s)&&(b[e++]=c);return b}function bnEquals(a){return 0==this.compareTo(a)}function bnMin(a){return this.compareTo(a)<0?this:a}function bnMax(a){return this.compareTo(a)>0?this:a}function bnpBitwiseTo(a,b,c){var d,e,f=Math.min(a.t,this.t);for(d=0;f>d;++d)c[d]=b(this[d],a[d]);if(a.ta?this.rShiftTo(-a,b):this.lShiftTo(a,b),b}function bnShiftRight(a){var b=nbi();return 0>a?this.lShiftTo(-a,b):this.rShiftTo(a,b),b}function lbit(a){if(0==a)return-1;var b=0;return 0==(65535&a)&&(a>>=16,b+=16),0==(255&a)&&(a>>=8,b+=8),0==(15&a)&&(a>>=4,b+=4),0==(3&a)&&(a>>=2,b+=2),0==(1&a)&&++b,b}function bnGetLowestSetBit(){for(var a=0;a=this.t?0!=this.s:0!=(this[b]&1<c;)d+=this[c]+a[c],b[c++]=d&this.DM,d>>=this.DB;if(a.t>=this.DB;d+=this.s}else{for(d+=this.s;c>=this.DB;d+=a.s}b.s=0>d?-1:0,d>0?b[c++]=d:-1>d&&(b[c++]=this.DV+d),b.t=c,b.clamp()}function bnAdd(a){var b=nbi();return this.addTo(a,b),b}function bnSubtract(a){var b=nbi();return this.subTo(a,b),b}function bnMultiply(a){var b=nbi();return this.multiplyTo(a,b),b}function bnSquare(){var a=nbi();return this.squareTo(a),a}function bnDivide(a){var b=nbi();return this.divRemTo(a,b,null),b}function bnRemainder(a){var b=nbi();return this.divRemTo(a,null,b),b}function bnDivideAndRemainder(a){var b=nbi(),c=nbi();return this.divRemTo(a,b,c),new Array(b,c)}function bnpDMultiply(a){this[this.t]=this.am(0,a-1,this,0,0,this.t),++this.t,this.clamp()}function bnpDAddOffset(a,b){if(0!=a){for(;this.t<=b;)this[this.t++]=0;for(this[b]+=a;this[b]>=this.DV;)this[b]-=this.DV,++b>=this.t&&(this[this.t++]=0),++this[b]}}function NullExp(){}function nNop(a){return a}function nMulTo(a,b,c){a.multiplyTo(b,c)}function nSqrTo(a,b){a.squareTo(b)}function bnPow(a){return this.exp(a,new NullExp)}function bnpMultiplyLowerTo(a,b,c){var d=Math.min(this.t+a.t,b);for(c.s=0,c.t=d;d>0;)c[--d]=0;var e;for(e=c.t-this.t;e>d;++d)c[d+this.t]=this.am(0,a[d],c,d,0,this.t);for(e=Math.min(a.t,b);e>d;++d)this.am(0,a[d],c,d,0,b-d);c.clamp()}function bnpMultiplyUpperTo(a,b,c){--b;var d=c.t=this.t+a.t-b;for(c.s=0;--d>=0;)c[d]=0;for(d=Math.max(b-this.t,0);d2*this.m.t)return a.mod(this.m);if(a.compareTo(this.m)<0)return a;var b=nbi();return a.copyTo(b),this.reduce(b),b}function barrettRevert(a){return a}function barrettReduce(a){for(a.drShiftTo(this.m.t-1,this.r2),a.t>this.m.t+1&&(a.t=this.m.t+1,a.clamp()),this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3),this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);a.compareTo(this.r2)<0;)a.dAddOffset(1,this.m.t+1);for(a.subTo(this.r2,a);a.compareTo(this.m)>=0;)a.subTo(this.m,a)}function barrettSqrTo(a,b){a.squareTo(b),this.reduce(b)}function barrettMulTo(a,b,c){a.multiplyTo(b,c),this.reduce(c)}function bnModPow(a,b){var c,d,e=a.bitLength(),f=nbv(1);if(0>=e)return f;c=18>e?1:48>e?3:144>e?4:768>e?5:6,d=8>e?new Classic(b):b.isEven()?new Barrett(b):new Montgomery(b);var g=new Array,h=3,i=c-1,j=(1<1){var k=nbi();for(d.sqrTo(g[1],k);j>=h;)g[h]=nbi(),d.mulTo(k,g[h-2],g[h]),h+=2}var l,m,n=a.t-1,o=!0,p=nbi();for(e=nbits(a[n])-1;n>=0;){for(e>=i?l=a[n]>>e-i&j:(l=(a[n]&(1<0&&(l|=a[n-1]>>this.DB+e-i)),h=c;0==(1&l);)l>>=1,--h;if((e-=h)<0&&(e+=this.DB,--n),o)g[l].copyTo(f),o=!1;else{for(;h>1;)d.sqrTo(f,p),d.sqrTo(p,f),h-=2;h>0?d.sqrTo(f,p):(m=f,f=p,p=m),d.mulTo(p,g[l],f)}for(;n>=0&&0==(a[n]&1<f)return b;for(f>e&&(f=e),f>0&&(b.rShiftTo(f,b),c.rShiftTo(f,c));b.signum()>0;)(e=b.getLowestSetBit())>0&&b.rShiftTo(e,b),(e=c.getLowestSetBit())>0&&c.rShiftTo(e,c),b.compareTo(c)>=0?(b.subTo(c,b),b.rShiftTo(1,b)):(c.subTo(b,c),c.rShiftTo(1,c));return f>0&&c.lShiftTo(f,c),c}function bnpModInt(a){if(0>=a)return 0;var b=this.DV%a,c=this.s<0?a-1:0;if(this.t>0)if(0==b)c=this[0]%a;else for(var d=this.t-1;d>=0;--d)c=(b*c+this[d])%a;return c}function bnModInverse(a){var b=a.isEven();if(this.isEven()&&b||0==a.signum())return BigInteger.ZERO;for(var c=a.clone(),d=this.clone(),e=nbv(1),f=nbv(0),g=nbv(0),h=nbv(1);0!=c.signum();){for(;c.isEven();)c.rShiftTo(1,c),b?(e.isEven()&&f.isEven()||(e.addTo(this,e),f.subTo(a,f)),e.rShiftTo(1,e)):f.isEven()||f.subTo(a,f),f.rShiftTo(1,f);for(;d.isEven();)d.rShiftTo(1,d),b?(g.isEven()&&h.isEven()||(g.addTo(this,g),h.subTo(a,h)),g.rShiftTo(1,g)):h.isEven()||h.subTo(a,h),h.rShiftTo(1,h);c.compareTo(d)>=0?(c.subTo(d,c),b&&e.subTo(g,e),f.subTo(h,f)):(d.subTo(c,d),b&&g.subTo(e,g),h.subTo(f,h))}return 0!=d.compareTo(BigInteger.ONE)?BigInteger.ZERO:h.compareTo(a)>=0?h.subtract(a):h.signum()<0?(h.addTo(a,h),h.signum()<0?h.add(a):h):h}function bnIsProbablePrime(a){var b,c=this.abs();if(1==c.t&&c[0]<=lowprimes[lowprimes.length-1]){for(b=0;bd;)d*=lowprimes[e++];for(d=c.modInt(d);e>b;)if(d%lowprimes[b++]==0)return!1}return c.millerRabin(a)}function bnpMillerRabin(a){var b=this.subtract(BigInteger.ONE),c=b.getLowestSetBit();if(0>=c)return!1;var d=b.shiftRight(c);a=a+1>>1,a>lowprimes.length&&(a=lowprimes.length);for(var e=nbi(),f=0;a>f;++f){e.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);var g=e.modPow(d,this);if(0!=g.compareTo(BigInteger.ONE)&&0!=g.compareTo(b)){for(var h=1;h++b;++b)this.S[b]=b;for(c=0,b=0;256>b;++b)c=c+this.S[b]+a[b%a.length]&255,d=this.S[b],this.S[b]=this.S[c],this.S[c]=d;this.i=0,this.j=0}function ARC4next(){var a;return this.i=this.i+1&255,this.j=this.j+this.S[this.i]&255,a=this.S[this.i],this.S[this.i]=this.S[this.j],this.S[this.j]=a,this.S[a+this.S[this.i]&255]}function prng_newstate(){return new Arcfour}function rng_get_byte(){if(null==rng_state){for(rng_state=prng_newstate();rng_psize>rng_pptr;){var a=Math.floor(65536*Math.random());rng_pool[rng_pptr++]=255&a}for(rng_state.init(rng_pool),rng_pptr=0;rng_pptra?"0"+a.toString(16):a.toString(16)}function pkcs1pad2(a,b){if(b=0&&b>0;){var e=a.charCodeAt(d--);128>e?c[--b]=e:e>127&&2048>e?(c[--b]=63&e|128,c[--b]=e>>6|192):(c[--b]=63&e|128,c[--b]=e>>6&63|128,c[--b]=e>>12|224)}c[--b]=0;for(var f=new SecureRandom,g=new Array;b>2;){for(g[0]=0;0==g[0];)f.nextBytes(g);c[--b]=g[0]}return c[--b]=2,c[--b]=0,new BigInteger(c)}function RSAKey(){this.n=null,this.e=0,this.d=null,this.p=null,this.q=null,this.dmp1=null,this.dmq1=null,this.coeff=null}function RSASetPublic(a,b){null!=a&&null!=b&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16)):console.error("Invalid RSA public key")}function RSADoPublic(a){return a.modPowInt(this.e,this.n)}function RSAEncrypt(a){var b=pkcs1pad2(a,this.n.bitLength()+7>>3);if(null==b)return null;var c=this.doPublic(b);if(null==c)return null;var d=c.toString(16);return 0==(1&d.length)?d:"0"+d}function pkcs1unpad2(a,b){for(var c=a.toByteArray(),d=0;d=c.length)return null;for(var e="";++df?e+=String.fromCharCode(f):f>191&&224>f?(e+=String.fromCharCode((31&f)<<6|63&c[d+1]),++d):(e+=String.fromCharCode((15&f)<<12|(63&c[d+1])<<6|63&c[d+2]),d+=2)}return e}function RSASetPrivate(a,b,c){null!=a&&null!=b&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16)):console.error("Invalid RSA private key")}function RSASetPrivateEx(a,b,c,d,e,f,g,h){null!=a&&null!=b&&a.length>0&&b.length>0?(this.n=parseBigInt(a,16),this.e=parseInt(b,16),this.d=parseBigInt(c,16),this.p=parseBigInt(d,16),this.q=parseBigInt(e,16),this.dmp1=parseBigInt(f,16),this.dmq1=parseBigInt(g,16),this.coeff=parseBigInt(h,16)):console.error("Invalid RSA private key")}function RSAGenerate(a,b){var c=new SecureRandom,d=a>>1;this.e=parseInt(b,16);for(var e=new BigInteger(b,16);;){for(;this.p=new BigInteger(a-d,1,c),0!=this.p.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)||!this.p.isProbablePrime(10););for(;this.q=new BigInteger(d,1,c),0!=this.q.subtract(BigInteger.ONE).gcd(e).compareTo(BigInteger.ONE)||!this.q.isProbablePrime(10););if(this.p.compareTo(this.q)<=0){var f=this.p;this.p=this.q,this.q=f}var g=this.p.subtract(BigInteger.ONE),h=this.q.subtract(BigInteger.ONE),i=g.multiply(h);if(0==i.gcd(e).compareTo(BigInteger.ONE)){this.n=this.p.multiply(this.q),this.d=e.modInverse(i),this.dmp1=this.d.mod(g),this.dmq1=this.d.mod(h),this.coeff=this.q.modInverse(this.p);break}}}function RSADoPrivate(a){if(null==this.p||null==this.q)return a.modPow(this.d,this.n);for(var b=a.mod(this.p).modPow(this.dmp1,this.p),c=a.mod(this.q).modPow(this.dmq1,this.q);b.compareTo(c)<0;)b=b.add(this.p);return b.subtract(c).multiply(this.coeff).mod(this.p).multiply(this.q).add(c)}function RSADecrypt(a){var b=parseBigInt(a,16),c=this.doPrivate(b);return null==c?null:pkcs1unpad2(c,this.n.bitLength()+7>>3)}function hex2b64(a){var b,c,d="";for(b=0;b+3<=a.length;b+=3)c=parseInt(a.substring(b,b+3),16),d+=b64map.charAt(c>>6)+b64map.charAt(63&c);for(b+1==a.length?(c=parseInt(a.substring(b,b+1),16),d+=b64map.charAt(c<<2)):b+2==a.length&&(c=parseInt(a.substring(b,b+2),16),d+=b64map.charAt(c>>2)+b64map.charAt((3&c)<<4));(3&d.length)>0;)d+=b64pad;return d}function b64tohex(a){var b,c,d="",e=0;for(b=0;b>2),c=3&v,e=1):1==e?(d+=int2char(c<<2|v>>4),c=15&v,e=2):2==e?(d+=int2char(c),d+=int2char(v>>2),c=3&v,e=3):(d+=int2char(c<<2|v>>4),d+=int2char(15&v),e=0));return 1==e&&(d+=int2char(c<<2)),d}function b64toBA(a){var b,c=b64tohex(a),d=new Array;for(b=0;2*b=vv;++vv)BI_RC[rr++]=vv;for(rr="a".charCodeAt(0),vv=10;36>vv;++vv)BI_RC[rr++]=vv;for(rr="A".charCodeAt(0),vv=10;36>vv;++vv)BI_RC[rr++]=vv;Classic.prototype.convert=cConvert,Classic.prototype.revert=cRevert,Classic.prototype.reduce=cReduce,Classic.prototype.mulTo=cMulTo,Classic.prototype.sqrTo=cSqrTo,Montgomery.prototype.convert=montConvert,Montgomery.prototype.revert=montRevert,Montgomery.prototype.reduce=montReduce,Montgomery.prototype.mulTo=montMulTo,Montgomery.prototype.sqrTo=montSqrTo,BigInteger.prototype.copyTo=bnpCopyTo,BigInteger.prototype.fromInt=bnpFromInt,BigInteger.prototype.fromString=bnpFromString,BigInteger.prototype.clamp=bnpClamp,BigInteger.prototype.dlShiftTo=bnpDLShiftTo,BigInteger.prototype.drShiftTo=bnpDRShiftTo,BigInteger.prototype.lShiftTo=bnpLShiftTo,BigInteger.prototype.rShiftTo=bnpRShiftTo,BigInteger.prototype.subTo=bnpSubTo,BigInteger.prototype.multiplyTo=bnpMultiplyTo,BigInteger.prototype.squareTo=bnpSquareTo,BigInteger.prototype.divRemTo=bnpDivRemTo,BigInteger.prototype.invDigit=bnpInvDigit,BigInteger.prototype.isEven=bnpIsEven,BigInteger.prototype.exp=bnpExp,BigInteger.prototype.toString=bnToString,BigInteger.prototype.negate=bnNegate,BigInteger.prototype.abs=bnAbs,BigInteger.prototype.compareTo=bnCompareTo,BigInteger.prototype.bitLength=bnBitLength,BigInteger.prototype.mod=bnMod,BigInteger.prototype.modPowInt=bnModPowInt,BigInteger.ZERO=nbv(0),BigInteger.ONE=nbv(1),NullExp.prototype.convert=nNop,NullExp.prototype.revert=nNop,NullExp.prototype.mulTo=nMulTo,NullExp.prototype.sqrTo=nSqrTo,Barrett.prototype.convert=barrettConvert,Barrett.prototype.revert=barrettRevert,Barrett.prototype.reduce=barrettReduce,Barrett.prototype.mulTo=barrettMulTo,Barrett.prototype.sqrTo=barrettSqrTo;var lowprimes=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],lplim=(1<<26)/lowprimes[lowprimes.length-1];BigInteger.prototype.chunkSize=bnpChunkSize,BigInteger.prototype.toRadix=bnpToRadix,BigInteger.prototype.fromRadix=bnpFromRadix,BigInteger.prototype.fromNumber=bnpFromNumber,BigInteger.prototype.bitwiseTo=bnpBitwiseTo,BigInteger.prototype.changeBit=bnpChangeBit,BigInteger.prototype.addTo=bnpAddTo,BigInteger.prototype.dMultiply=bnpDMultiply,BigInteger.prototype.dAddOffset=bnpDAddOffset,BigInteger.prototype.multiplyLowerTo=bnpMultiplyLowerTo,BigInteger.prototype.multiplyUpperTo=bnpMultiplyUpperTo,BigInteger.prototype.modInt=bnpModInt,BigInteger.prototype.millerRabin=bnpMillerRabin,BigInteger.prototype.clone=bnClone,BigInteger.prototype.intValue=bnIntValue,BigInteger.prototype.byteValue=bnByteValue,BigInteger.prototype.shortValue=bnShortValue,BigInteger.prototype.signum=bnSigNum,BigInteger.prototype.toByteArray=bnToByteArray,BigInteger.prototype.equals=bnEquals,BigInteger.prototype.min=bnMin,BigInteger.prototype.max=bnMax,BigInteger.prototype.and=bnAnd,BigInteger.prototype.or=bnOr,BigInteger.prototype.xor=bnXor,BigInteger.prototype.andNot=bnAndNot,BigInteger.prototype.not=bnNot,BigInteger.prototype.shiftLeft=bnShiftLeft,BigInteger.prototype.shiftRight=bnShiftRight,BigInteger.prototype.getLowestSetBit=bnGetLowestSetBit,BigInteger.prototype.bitCount=bnBitCount,BigInteger.prototype.testBit=bnTestBit,BigInteger.prototype.setBit=bnSetBit,BigInteger.prototype.clearBit=bnClearBit,BigInteger.prototype.flipBit=bnFlipBit,BigInteger.prototype.add=bnAdd,BigInteger.prototype.subtract=bnSubtract,BigInteger.prototype.multiply=bnMultiply,BigInteger.prototype.divide=bnDivide,BigInteger.prototype.remainder=bnRemainder,BigInteger.prototype.divideAndRemainder=bnDivideAndRemainder,BigInteger.prototype.modPow=bnModPow,BigInteger.prototype.modInverse=bnModInverse,BigInteger.prototype.pow=bnPow,BigInteger.prototype.gcd=bnGCD,BigInteger.prototype.isProbablePrime=bnIsProbablePrime,BigInteger.prototype.square=bnSquare,Arcfour.prototype.init=ARC4init,Arcfour.prototype.next=ARC4next;var rng_psize=256,rng_state,rng_pool,rng_pptr;if(null==rng_pool){rng_pool=new Array,rng_pptr=0;var t;if(window.crypto&&window.crypto.getRandomValues){var z=new Uint32Array(256);for(window.crypto.getRandomValues(z),t=0;t=256||rng_pptr>=rng_psize)return void(window.removeEventListener?window.removeEventListener("mousemove",onMouseMoveListener):window.detachEvent&&window.detachEvent("onmousemove",onMouseMoveListener));this.count+=1;var b=a.x+a.y;rng_pool[rng_pptr++]=255&b};window.addEventListener?window.addEventListener("mousemove",onMouseMoveListener):window.attachEvent&&window.attachEvent("onmousemove",onMouseMoveListener)}SecureRandom.prototype.nextBytes=rng_get_bytes,RSAKey.prototype.doPublic=RSADoPublic,RSAKey.prototype.setPublic=RSASetPublic,RSAKey.prototype.encrypt=RSAEncrypt,RSAKey.prototype.doPrivate=RSADoPrivate,RSAKey.prototype.setPrivate=RSASetPrivate,RSAKey.prototype.setPrivateEx=RSASetPrivateEx,RSAKey.prototype.generate=RSAGenerate,RSAKey.prototype.decrypt=RSADecrypt,function(){var a=function(a,b,c){var d=new SecureRandom,e=a>>1;this.e=parseInt(b,16);var f=new BigInteger(b,16),g=this,h=function(){var b=function(){if(g.p.compareTo(g.q)<=0){var a=g.p;g.p=g.q,g.q=a}var b=g.p.subtract(BigInteger.ONE),d=g.q.subtract(BigInteger.ONE),e=b.multiply(d);0==e.gcd(f).compareTo(BigInteger.ONE)?(g.n=g.p.multiply(g.q),g.d=f.modInverse(e),g.dmp1=g.d.mod(b),g.dmq1=g.d.mod(d),g.coeff=g.q.modInverse(g.p),setTimeout(function(){c()},0)):setTimeout(h,0)},i=function(){g.q=nbi(),g.q.fromNumberAsync(e,1,d,function(){g.q.subtract(BigInteger.ONE).gcda(f,function(a){0==a.compareTo(BigInteger.ONE)&&g.q.isProbablePrime(10)?setTimeout(b,0):setTimeout(i,0)})})},j=function(){g.p=nbi(),g.p.fromNumberAsync(a-e,1,d,function(){g.p.subtract(BigInteger.ONE).gcda(f,function(a){0==a.compareTo(BigInteger.ONE)&&g.p.isProbablePrime(10)?setTimeout(i,0):setTimeout(j,0)})})};setTimeout(j,0)};setTimeout(h,0)};RSAKey.prototype.generateAsync=a;var b=function(a,b){var c=this.s<0?this.negate():this.clone(),d=a.s<0?a.negate():a.clone();if(c.compareTo(d)<0){var e=c;c=d,d=e}var f=c.getLowestSetBit(),g=d.getLowestSetBit();if(0>g)return void b(c);g>f&&(g=f),g>0&&(c.rShiftTo(g,c),d.rShiftTo(g,d));var h=function(){(f=c.getLowestSetBit())>0&&c.rShiftTo(f,c),(f=d.getLowestSetBit())>0&&d.rShiftTo(f,d),c.compareTo(d)>=0?(c.subTo(d,c),c.rShiftTo(1,c)):(d.subTo(c,d),d.rShiftTo(1,d)),c.signum()>0?setTimeout(h,0):(g>0&&d.lShiftTo(g,d),setTimeout(function(){b(d)},0))};setTimeout(h,10)};BigInteger.prototype.gcda=b;var c=function(a,b,c,d){if("number"==typeof b)if(2>a)this.fromInt(1);else{this.fromNumber(a,c),this.testBit(a-1)||this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this),this.isEven()&&this.dAddOffset(1,0);var e=this,f=function(){e.dAddOffset(2,0),e.bitLength()>a&&e.subTo(BigInteger.ONE.shiftLeft(a-1),e),e.isProbablePrime(b)?setTimeout(function(){d()},0):setTimeout(f,0)};setTimeout(f,0)}else{var g=new Array,h=7&a;g.length=(a>>3)+1,b.nextBytes(g),h>0?g[0]&=(1<f;f++)e+="f";var g=new BigInteger(e,16),h=g.xor(a).add(BigInteger.ONE);b=h.toString(16).replace(/^-/,"")}return b},this.getPEMStringFromHex=function(a,b){var c=CryptoJS.enc.Hex.parse(a),d=CryptoJS.enc.Base64.stringify(c),e=d.replace(/(.{64})/g,"$1\r\n");return e=e.replace(/\r\n$/,""),"-----BEGIN "+b+"-----\r\n"+e+"\r\n-----END "+b+"-----\r\n"}},KJUR.asn1.ASN1Object=function(){var a="";this.getLengthHexFromValue=function(){if("undefined"==typeof this.hV||null==this.hV)throw"this.hV is null or undefined.";if(this.hV.length%2==1)throw"value hex must be even length: n="+a.length+",v="+this.hV;var b=this.hV.length/2,c=b.toString(16);if(c.length%2==1&&(c="0"+c),128>b)return c;var d=c.length/2;if(d>15)throw"ASN.1 length too long to represent by 8x: n = "+b.toString(16);var e=128+d;return e.toString(16)+c},this.getEncodedHex=function(){return(null==this.hTLV||this.isModified)&&(this.hV=this.getFreshValueHex(),this.hL=this.getLengthHexFromValue(),this.hTLV=this.hT+this.hL+this.hV,this.isModified=!1),this.hTLV},this.getValueHex=function(){return this.getEncodedHex(),this.hV},this.getFreshValueHex=function(){return""}},KJUR.asn1.DERAbstractString=function(a){KJUR.asn1.DERAbstractString.superclass.constructor.call(this);this.getString=function(){return this.s},this.setString=function(a){this.hTLV=null,this.isModified=!0,this.s=a,this.hV=stohex(this.s)},this.setStringHex=function(a){this.hTLV=null,this.isModified=!0,this.s=null,this.hV=a},this.getFreshValueHex=function(){return this.hV},"undefined"!=typeof a&&("undefined"!=typeof a.str?this.setString(a.str):"undefined"!=typeof a.hex&&this.setStringHex(a.hex))},JSX.extend(KJUR.asn1.DERAbstractString,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractTime=function(){KJUR.asn1.DERAbstractTime.superclass.constructor.call(this);this.localDateToUTC=function(a){utc=a.getTime()+6e4*a.getTimezoneOffset();var b=new Date(utc);return b},this.formatDate=function(a,b){var c=this.zeroPadding,d=this.localDateToUTC(a),e=String(d.getFullYear());"utc"==b&&(e=e.substr(2,2));var f=c(String(d.getMonth()+1),2),g=c(String(d.getDate()),2),h=c(String(d.getHours()),2),i=c(String(d.getMinutes()),2),j=c(String(d.getSeconds()),2);return e+f+g+h+i+j+"Z"},this.zeroPadding=function(a,b){return a.length>=b?a:new Array(b-a.length+1).join("0")+a},this.getString=function(){return this.s},this.setString=function(a){this.hTLV=null,this.isModified=!0,this.s=a,this.hV=stohex(this.s)},this.setByDateValue=function(a,b,c,d,e,f){var g=new Date(Date.UTC(a,b-1,c,d,e,f,0));this.setByDate(g)},this.getFreshValueHex=function(){return this.hV}},JSX.extend(KJUR.asn1.DERAbstractTime,KJUR.asn1.ASN1Object),KJUR.asn1.DERAbstractStructured=function(a){KJUR.asn1.DERAbstractString.superclass.constructor.call(this);this.setByASN1ObjectArray=function(a){this.hTLV=null,this.isModified=!0,this.asn1Array=a},this.appendASN1Object=function(a){this.hTLV=null,this.isModified=!0,this.asn1Array.push(a)},this.asn1Array=new Array,"undefined"!=typeof a&&"undefined"!=typeof a.array&&(this.asn1Array=a.array)},JSX.extend(KJUR.asn1.DERAbstractStructured,KJUR.asn1.ASN1Object),KJUR.asn1.DERBoolean=function(){KJUR.asn1.DERBoolean.superclass.constructor.call(this),this.hT="01",this.hTLV="0101ff"},JSX.extend(KJUR.asn1.DERBoolean,KJUR.asn1.ASN1Object),KJUR.asn1.DERInteger=function(a){KJUR.asn1.DERInteger.superclass.constructor.call(this),this.hT="02",this.setByBigInteger=function(a){this.hTLV=null,this.isModified=!0,this.hV=KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex(a)},this.setByInteger=function(a){var b=new BigInteger(String(a),10);this.setByBigInteger(b)},this.setValueHex=function(a){this.hV=a},this.getFreshValueHex=function(){return this.hV},"undefined"!=typeof a&&("undefined"!=typeof a.bigint?this.setByBigInteger(a.bigint):"undefined"!=typeof a["int"]?this.setByInteger(a["int"]):"undefined"!=typeof a.hex&&this.setValueHex(a.hex))},JSX.extend(KJUR.asn1.DERInteger,KJUR.asn1.ASN1Object),KJUR.asn1.DERBitString=function(a){KJUR.asn1.DERBitString.superclass.constructor.call(this),this.hT="03",this.setHexValueIncludingUnusedBits=function(a){this.hTLV=null,this.isModified=!0,this.hV=a},this.setUnusedBitsAndHexValue=function(a,b){if(0>a||a>7)throw"unused bits shall be from 0 to 7: u = "+a;var c="0"+a;this.hTLV=null,this.isModified=!0,this.hV=c+b},this.setByBinaryString=function(a){a=a.replace(/0+$/,"");var b=8-a.length%8;8==b&&(b=0);for(var c=0;b>=c;c++)a+="0";for(var d="",c=0;cc;c++)b[c]=!1;return b},this.getFreshValueHex=function(){return this.hV},"undefined"!=typeof a&&("undefined"!=typeof a.hex?this.setHexValueIncludingUnusedBits(a.hex):"undefined"!=typeof a.bin?this.setByBinaryString(a.bin):"undefined"!=typeof a.array&&this.setByBooleanArray(a.array))},JSX.extend(KJUR.asn1.DERBitString,KJUR.asn1.ASN1Object),KJUR.asn1.DEROctetString=function(a){KJUR.asn1.DEROctetString.superclass.constructor.call(this,a),this.hT="04"},JSX.extend(KJUR.asn1.DEROctetString,KJUR.asn1.DERAbstractString),KJUR.asn1.DERNull=function(){KJUR.asn1.DERNull.superclass.constructor.call(this),this.hT="05",this.hTLV="0500"},JSX.extend(KJUR.asn1.DERNull,KJUR.asn1.ASN1Object),KJUR.asn1.DERObjectIdentifier=function(a){var b=function(a){var b=a.toString(16);return 1==b.length&&(b="0"+b),b},c=function(a){var c="",d=new BigInteger(a,10),e=d.toString(2),f=7-e.length%7;7==f&&(f=0);for(var g="",h=0;f>h;h++)g+="0";e=g+e;for(var h=0;hd;++d)b[e.charAt(d)]=d;for(e=e.toLowerCase(),d=10;16>d;++d)b[e.charAt(d)]=d;for(d=0;d=2?(g[g.length]=h,h=0,i=0):h<<=4}}if(i)throw"Hex encoding incomplete: 4 bits missing";return g},window.Hex=c}(),function(a){"use strict";var b,c={};c.decode=function(c){var d;if(b===a){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",f="= \f\n\r \u2028\u2029";for(b=[],d=0;64>d;++d)b[e.charAt(d)]=d;for(d=0;d=4?(g[g.length]=h>>16,g[g.length]=h>>8&255,g[g.length]=255&h,h=0,i=0):h<<=6}}switch(i){case 1:throw"Base64 encoding incomplete: at least 2 bits missing";case 2:g[g.length]=h>>10;break;case 3:g[g.length]=h>>16,g[g.length]=h>>8&255}return g},c.re=/-----BEGIN [^-]+-----([A-Za-z0-9+\/=\s]+)-----END [^-]+-----|begin-base64[^\n]+\n([A-Za-z0-9+\/=\s]+)====/,c.unarmor=function(a){var b=c.re.exec(a);if(b)if(b[1])a=b[1];else{if(!b[2])throw"RegExp out of sync";a=b[2]}return c.decode(a)},window.Base64=c}(),function(a){"use strict";function b(a,c){a instanceof b?(this.enc=a.enc,this.pos=a.pos):(this.enc=a,this.pos=c)}function c(a,b,c,d,e){this.stream=a,this.header=b,this.length=c,this.tag=d,this.sub=e}var d=100,e="…",f={tag:function(a,b){var c=document.createElement(a);return c.className=b,c},text:function(a){return document.createTextNode(a)}};b.prototype.get=function(b){if(b===a&&(b=this.pos++),b>=this.enc.length)throw"Requesting byte offset "+b+" on a stream of length "+this.enc.length;return this.enc[b]},b.prototype.hexDigits="0123456789ABCDEF",b.prototype.hexByte=function(a){return this.hexDigits.charAt(a>>4&15)+this.hexDigits.charAt(15&a)},b.prototype.hexDump=function(a,b,c){for(var d="",e=a;b>e;++e)if(d+=this.hexByte(this.get(e)),c!==!0)switch(15&e){case 7:d+=" ";break;case 15:d+="\n";break;default:d+=" "}return d},b.prototype.parseStringISO=function(a,b){for(var c="",d=a;b>d;++d)c+=String.fromCharCode(this.get(d));return c},b.prototype.parseStringUTF=function(a,b){for(var c="",d=a;b>d;){var e=this.get(d++);c+=String.fromCharCode(128>e?e:e>191&&224>e?(31&e)<<6|63&this.get(d++):(15&e)<<12|(63&this.get(d++))<<6|63&this.get(d++))}return c},b.prototype.parseStringBMP=function(a,b){for(var c="",d=a;b>d;d+=2){var e=this.get(d),f=this.get(d+1);c+=String.fromCharCode((e<<8)+f)}return c},b.prototype.reTime=/^((?:1[89]|2\d)?\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/,b.prototype.parseTime=function(a,b){var c=this.parseStringISO(a,b),d=this.reTime.exec(c);return d?(c=d[1]+"-"+d[2]+"-"+d[3]+" "+d[4],d[5]&&(c+=":"+d[5],d[6]&&(c+=":"+d[6],d[7]&&(c+="."+d[7]))),d[8]&&(c+=" UTC","Z"!=d[8]&&(c+=d[8],d[9]&&(c+=":"+d[9]))),c):"Unrecognized time: "+c},b.prototype.parseInteger=function(a,b){var c=b-a;if(c>4){c<<=3;var d=this.get(a);if(0===d)c-=8;else for(;128>d;)d<<=1,--c;return"("+c+" bit)"}for(var e=0,f=a;b>f;++f)e=e<<8|this.get(f);return e},b.prototype.parseBitString=function(a,b){var c=this.get(a),d=(b-a-1<<3)-c,e="("+d+" bit)";if(20>=d){var f=c;e+=" ";for(var g=b-1;g>a;--g){for(var h=this.get(g),i=f;8>i;++i)e+=h>>i&1?"1":"0";f=0}}return e},b.prototype.parseOctetString=function(a,b){var c=b-a,f="("+c+" byte) ";c>d&&(b=a+d);for(var g=a;b>g;++g)f+=this.hexByte(this.get(g));return c>d&&(f+=e),f},b.prototype.parseOID=function(a,b){for(var c="",d=0,e=0,f=a;b>f;++f){var g=this.get(f);if(d=d<<7|127&g,e+=7,!(128&g)){if(""===c){var h=80>d?40>d?0:1:2;c=h+"."+(d-40*h)}else c+="."+(e>=31?"bigint":d);d=e=0}}return c},c.prototype.typeName=function(){if(this.tag===a)return"unknown";var b=this.tag>>6,c=(this.tag>>5&1,31&this.tag);switch(b){case 0:switch(c){case 0:return"EOC";case 1:return"BOOLEAN";case 2:return"INTEGER";case 3:return"BIT_STRING";case 4:return"OCTET_STRING";case 5:return"NULL";case 6:return"OBJECT_IDENTIFIER";case 7:return"ObjectDescriptor";case 8:return"EXTERNAL";case 9:return"REAL";case 10:return"ENUMERATED";case 11:return"EMBEDDED_PDV";case 12:return"UTF8String";case 16:return"SEQUENCE";case 17:return"SET";case 18:return"NumericString";case 19:return"PrintableString";case 20:return"TeletexString";case 21:return"VideotexString";case 22:return"IA5String";case 23:return"UTCTime";case 24:return"GeneralizedTime";case 25:return"GraphicString";case 26:return"VisibleString";case 27:return"GeneralString";case 28:return"UniversalString";case 30:return"BMPString";default:return"Universal_"+c.toString(16)}case 1:return"Application_"+c.toString(16);case 2:return"["+c+"]";case 3:return"Private_"+c.toString(16)}},c.prototype.reSeemsASCII=/^[ -~]+$/,c.prototype.content=function(){if(this.tag===a)return null;var b=this.tag>>6,c=31&this.tag,f=this.posContent(),g=Math.abs(this.length);if(0!==b){if(null!==this.sub)return"("+this.sub.length+" elem)";var h=this.stream.parseStringISO(f,f+Math.min(g,d));return this.reSeemsASCII.test(h)?h.substring(0,2*d)+(h.length>2*d?e:""):this.stream.parseOctetString(f,f+g)}switch(c){case 1:return 0===this.stream.get(f)?"false":"true";case 2:return this.stream.parseInteger(f,f+g);case 3:return this.sub?"("+this.sub.length+" elem)":this.stream.parseBitString(f,f+g);case 4:return this.sub?"("+this.sub.length+" elem)":this.stream.parseOctetString(f,f+g);case 6:return this.stream.parseOID(f,f+g);case 16:case 17:return"("+this.sub.length+" elem)";case 12:return this.stream.parseStringUTF(f,f+g);case 18:case 19:case 20:case 21:case 22:case 26:return this.stream.parseStringISO(f,f+g);case 30:return this.stream.parseStringBMP(f,f+g);case 23:case 24:return this.stream.parseTime(f,f+g)}return null},c.prototype.toString=function(){return this.typeName()+"@"+this.stream.pos+"[header:"+this.header+",length:"+this.length+",sub:"+(null===this.sub?"null":this.sub.length)+"]"},c.prototype.print=function(b){if(b===a&&(b=""),document.writeln(b+this),null!==this.sub){b+=" ";for(var c=0,d=this.sub.length;d>c;++c)this.sub[c].print(b)}},c.prototype.toPrettyString=function(b){b===a&&(b="");var c=b+this.typeName()+" @"+this.stream.pos;if(this.length>=0&&(c+="+"),c+=this.length,32&this.tag?c+=" (constructed)":3!=this.tag&&4!=this.tag||null===this.sub||(c+=" (encapsulates)"),c+="\n",null!==this.sub){b+=" ";for(var d=0,e=this.sub.length;e>d;++d)c+=this.sub[d].toPrettyString(b)}return c},c.prototype.toDOM=function(){var a=f.tag("div","node");a.asn1=this;var b=f.tag("div","head"),c=this.typeName().replace(/_/g," ");b.innerHTML=c;var d=this.content();if(null!==d){d=String(d).replace(/",c+="Length: "+this.header+"+",c+=this.length>=0?this.length:-this.length+" (undefined)",32&this.tag?c+=" (constructed)":3!=this.tag&&4!=this.tag||null===this.sub||(c+=" (encapsulates)"),null!==d&&(c+=" Value: "+d+"","object"==typeof oids&&6==this.tag)){var h=oids[d];h&&(h.d&&(c+=" "+h.d),h.c&&(c+=" "+h.c),h.w&&(c+=" (warning!)"))}g.innerHTML=c,a.appendChild(g);var i=f.tag("div","sub");if(null!==this.sub)for(var j=0,k=this.sub.length;k>j;++j)i.appendChild(this.sub[j].toDOM());return a.appendChild(i),b.onclick=function(){a.className="node collapsed"==a.className?"node":"node collapsed"},a},c.prototype.posStart=function(){return this.stream.pos},c.prototype.posContent=function(){return this.stream.pos+this.header},c.prototype.posEnd=function(){return this.stream.pos+this.header+Math.abs(this.length)},c.prototype.fakeHover=function(a){this.node.className+=" hover",a&&(this.head.className+=" hover")},c.prototype.fakeOut=function(a){var b=/ ?hover/;this.node.className=this.node.className.replace(b,""),a&&(this.head.className=this.head.className.replace(b,""))},c.prototype.toHexDOM_sub=function(a,b,c,d,e){if(!(d>=e)){var g=f.tag("span",b);g.appendChild(f.text(c.hexDump(d,e))),a.appendChild(g)}},c.prototype.toHexDOM=function(b){var c=f.tag("span","hex");if(b===a&&(b=c),this.head.hexNode=c,this.head.onmouseover=function(){this.hexNode.className="hexCurrent"},this.head.onmouseout=function(){this.hexNode.className="hex"},c.asn1=this,c.onmouseover=function(){var a=!b.selected;a&&(b.selected=this.asn1,this.className="hexCurrent"),this.asn1.fakeHover(a)},c.onmouseout=function(){var a=b.selected==this.asn1;this.asn1.fakeOut(a),a&&(b.selected=null,this.className="hex")},this.toHexDOM_sub(c,"tag",this.stream,this.posStart(),this.posStart()+1),this.toHexDOM_sub(c,this.length>=0?"dlen":"ulen",this.stream,this.posStart()+1,this.posContent()),null===this.sub)c.appendChild(f.text(this.stream.hexDump(this.posContent(),this.posEnd())));else if(this.sub.length>0){var d=this.sub[0],e=this.sub[this.sub.length-1];this.toHexDOM_sub(c,"intro",this.stream,this.posContent(),d.posStart());for(var g=0,h=this.sub.length;h>g;++g)c.appendChild(this.sub[g].toHexDOM(b));this.toHexDOM_sub(c,"outro",this.stream,e.posEnd(),this.posEnd())}return c},c.prototype.toHexString=function(){return this.stream.hexDump(this.posStart(),this.posEnd(),!0)},c.decodeLength=function(a){var b=a.get(),c=127&b;if(c==b)return c;if(c>3)throw"Length over 24 bits not supported at position "+(a.pos-1);if(0===c)return-1;b=0;for(var d=0;c>d;++d)b=b<<8|a.get();return b},c.hasContent=function(a,d,e){if(32&a)return!0;if(3>a||a>4)return!1;var f=new b(e);3==a&&f.get();var g=f.get();if(g>>6&1)return!1;try{var h=c.decodeLength(f);return f.pos-e.pos+h==d}catch(i){return!1}},c.decode=function(a){a instanceof b||(a=new b(a,0));var d=new b(a),e=a.get(),f=c.decodeLength(a),g=a.pos-d.pos,h=null;if(c.hasContent(e,f,a)){var i=a.pos;if(3==e&&a.get(),h=[],f>=0){for(var j=i+f;a.posd;++d){var f=new b(a[d].value,0),g=c.decodeLength(f);g!=a[d].expected&&document.write("In test["+d+"] expected "+a[d].expected+" got "+g+"\n")}},window.ASN1=c}(),ASN1.prototype.getHexStringValue=function(){var a=this.toHexString(),b=2*this.header,c=2*this.length;return a.substr(b,c)},RSAKey.prototype.parseKey=function(a){try{var b=0,c=0,d=/^\s*(?:[0-9A-Fa-f][0-9A-Fa-f]\s*)+$/,e=d.test(a)?Hex.decode(a):Base64.unarmor(a),f=ASN1.decode(e);if(3===f.sub.length&&(f=f.sub[2].sub[0]),9===f.sub.length){b=f.sub[1].getHexStringValue(),this.n=parseBigInt(b,16),c=f.sub[2].getHexStringValue(),this.e=parseInt(c,16);var g=f.sub[3].getHexStringValue();this.d=parseBigInt(g,16);var h=f.sub[4].getHexStringValue();this.p=parseBigInt(h,16);var i=f.sub[5].getHexStringValue();this.q=parseBigInt(i,16);var j=f.sub[6].getHexStringValue();this.dmp1=parseBigInt(j,16);var k=f.sub[7].getHexStringValue();this.dmq1=parseBigInt(k,16);var l=f.sub[8].getHexStringValue();this.coeff=parseBigInt(l,16)}else{if(2!==f.sub.length)return!1;var m=f.sub[1],n=m.sub[0];b=n.sub[0].getHexStringValue(),this.n=parseBigInt(b,16),c=n.sub[1].getHexStringValue(),this.e=parseInt(c,16)}return!0}catch(o){return!1}},RSAKey.prototype.getPrivateBaseKey=function(){var a={array:[new KJUR.asn1.DERInteger({"int":0}),new KJUR.asn1.DERInteger({bigint:this.n}),new KJUR.asn1.DERInteger({"int":this.e}),new KJUR.asn1.DERInteger({bigint:this.d}),new KJUR.asn1.DERInteger({bigint:this.p}),new KJUR.asn1.DERInteger({bigint:this.q}),new KJUR.asn1.DERInteger({bigint:this.dmp1}),new KJUR.asn1.DERInteger({bigint:this.dmq1}),new KJUR.asn1.DERInteger({bigint:this.coeff})]},b=new KJUR.asn1.DERSequence(a);return b.getEncodedHex()},RSAKey.prototype.getPrivateBaseKeyB64=function(){return hex2b64(this.getPrivateBaseKey())},RSAKey.prototype.getPublicBaseKey=function(){var a={array:[new KJUR.asn1.DERObjectIdentifier({oid:"1.2.840.113549.1.1.1"}),new KJUR.asn1.DERNull]},b=new KJUR.asn1.DERSequence(a);a={array:[new KJUR.asn1.DERInteger({bigint:this.n}),new KJUR.asn1.DERInteger({"int":this.e})]};var c=new KJUR.asn1.DERSequence(a);a={hex:"00"+c.getEncodedHex()};var d=new KJUR.asn1.DERBitString(a);a={array:[b,d]};var e=new KJUR.asn1.DERSequence(a);return e.getEncodedHex()},RSAKey.prototype.getPublicBaseKeyB64=function(){return hex2b64(this.getPublicBaseKey())},RSAKey.prototype.wordwrap=function(a,b){if(b=b||64,!a)return a;var c="(.{1,"+b+"})( +|$\n?)|(.{1,"+b+"})";return a.match(RegExp(c,"g")).join("\n")},RSAKey.prototype.getPrivateKey=function(){var a="-----BEGIN RSA PRIVATE KEY-----\n";return a+=this.wordwrap(this.getPrivateBaseKeyB64())+"\n",a+="-----END RSA PRIVATE KEY-----"},RSAKey.prototype.getPublicKey=function(){var a="-----BEGIN PUBLIC KEY-----\n";return a+=this.wordwrap(this.getPublicBaseKeyB64())+"\n",a+="-----END PUBLIC KEY-----"},RSAKey.prototype.hasPublicKeyProperty=function(a){return a=a||{},a.hasOwnProperty("n")&&a.hasOwnProperty("e")},RSAKey.prototype.hasPrivateKeyProperty=function(a){return a=a||{},a.hasOwnProperty("n")&&a.hasOwnProperty("e")&&a.hasOwnProperty("d")&&a.hasOwnProperty("p")&&a.hasOwnProperty("q")&&a.hasOwnProperty("dmp1")&&a.hasOwnProperty("dmq1")&&a.hasOwnProperty("coeff")},RSAKey.prototype.parsePropertiesFrom=function(a){this.n=a.n,this.e=a.e,a.hasOwnProperty("d")&&(this.d=a.d,this.p=a.p,this.q=a.q,this.dmp1=a.dmp1,this.dmq1=a.dmq1,this.coeff=a.coeff)};var JSEncryptRSAKey=function(a){RSAKey.call(this),a&&("string"==typeof a?this.parseKey(a):(this.hasPrivateKeyProperty(a)||this.hasPublicKeyProperty(a))&&this.parsePropertiesFrom(a))};JSEncryptRSAKey.prototype=new RSAKey,JSEncryptRSAKey.prototype.constructor=JSEncryptRSAKey;var JSEncrypt=function(a){a=a||{},this.default_key_size=parseInt(a.default_key_size)||1024,this.default_public_exponent=a.default_public_exponent||"010001",this.log=a.log||!1,this.key=null};JSEncrypt.prototype.setKey=function(a){this.log&&this.key&&console.warn("A key was already set, overriding existing."),this.key=new JSEncryptRSAKey(a)},JSEncrypt.prototype.setPrivateKey=function(a){this.setKey(a)},JSEncrypt.prototype.setPublicKey=function(a){this.setKey(a)},JSEncrypt.prototype.decrypt=function(a){try{return this.getKey().decrypt(b64tohex(a))}catch(b){return!1}},JSEncrypt.prototype.encrypt=function(a){try{return hex2b64(this.getKey().encrypt(a))}catch(b){return!1}},JSEncrypt.prototype.getKey=function(a){if(!this.key){if(this.key=new JSEncryptRSAKey,a&&"[object Function]"==={}.toString.call(a))return void this.key.generateAsync(this.default_key_size,this.default_public_exponent,a);this.key.generate(this.default_key_size,this.default_public_exponent)}return this.key},JSEncrypt.prototype.getPrivateKey=function(){return this.getKey().getPrivateKey()},JSEncrypt.prototype.getPrivateKeyB64=function(){return this.getKey().getPrivateBaseKeyB64()},JSEncrypt.prototype.getPublicKey=function(){return this.getKey().getPublicKey()},JSEncrypt.prototype.getPublicKeyB64=function(){return this.getKey().getPublicBaseKeyB64()};exports.JSEncrypt = JSEncrypt;
5 | })(JSEncryptExports);
6 | var JSEncrypt = JSEncryptExports.JSEncrypt;
7 |
--------------------------------------------------------------------------------
|