This commit is contained in:
make
2025-04-21 17:49:17 +08:00
parent 7ef217c1b9
commit 2337ab4f7d
942 changed files with 209166 additions and 0 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 909 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,155 @@
import CctvsJs from '../class/cctv.js';
const Cctvs = new CctvsJs();
import ConfigsJs from '../class/config.js';
const Configs = new ConfigsJs();
let arrConfigs = Configs.getAll()
// 公共广告
const CommonCctv = {
init(){
if(document.querySelector(".j-cctv-list-page")){
this.initVideoList()
}
// this.initBannerBottomPiao()
this.initPlBannerBottomPiao()
Cctvs.addEvent() //切勿多次调用监听事件
},
/**
* 视频列表
*/
initVideoList(arrPageId=[300,302]) {
let CctvBannerBottomPiaoList = Cctvs.getDataByWhere(105, 209, arrPageId);
//列表页-猜你喜欢
if (CctvBannerBottomPiaoList.length > 0) {
//列表页-1
$(".j-cctv-list-page .j-cctv-list-ul").children().eq(0).remove()
$(".j-cctv-list-page .j-cctv-list-ul").children().eq(0).before(this.CreatListCctv(CctvBannerBottomPiaoList[0]))
}
if (CctvBannerBottomPiaoList.length > 1) {
//列表页-2
$(".j-cctv-list-page .j-cctv-list-ul").children().eq(5).remove()
$(".j-cctv-list-page .j-cctv-list-ul").children().eq(5).before(this.CreatListCctv(CctvBannerBottomPiaoList[1]))
}
if (CctvBannerBottomPiaoList.length > 2) {
//列表页-2
$(".j-cctv-list-page .j-cctv-list-ul").children().eq(8).remove()
$(".j-cctv-list-page .j-cctv-list-ul").children().eq(8).before(this.CreatListCctv(CctvBannerBottomPiaoList[2]))
}
},
/**
* 底飘初始化
* --随机生成
*/
initBannerBottomPiao() {
return
let CctvBannerBottomPiaoList = Cctvs.getDataByWhere(101, 217, [300, 303]);
let CctvBannerBottomPiaoListDom = '';
let intRandNum = Math.floor(Math.random() * CctvBannerBottomPiaoList.length) //生成随机开屏广告
let intFindActioveIndex = CctvBannerBottomPiaoList.findIndex((item, index) => index == intRandNum)
if (intFindActioveIndex != -1) {
CctvBannerBottomPiaoListDom = this.CreateCctvBottomDomList(CctvBannerBottomPiaoList[intFindActioveIndex], intFindActioveIndex, '底瓢');
}
if (CctvBannerBottomPiaoList.length > 0) {
$(".foot-dp-fix").html(CctvBannerBottomPiaoListDom);
} else {
$(".foot-dp-fix").addClass('yc')
}
},
/**
* 跑量页面-底飘初始化
* --随机生成
*/
initPlBannerBottomPiao() {
let CctvBannerBottomPiaoPlList = Cctvs.getDataByWhere(101, 217, [305]);
let CctvBannerBottomPiaoPlListDom = '';
let intRandNum = Math.floor(Math.random() * CctvBannerBottomPiaoPlList.length) //生成随机开屏广告
let intFindActioveIndex = CctvBannerBottomPiaoPlList.findIndex((item, index) => index == intRandNum)
if (intFindActioveIndex != -1) {
CctvBannerBottomPiaoPlListDom = this.CreateCctvBottomDomPlList(CctvBannerBottomPiaoPlListDom[intFindActioveIndex], intFindActioveIndex, '底瓢');
}
if (CctvBannerBottomPiaoPlList.length > 0) {
$(".foot-fix").html(CctvBannerBottomPiaoPlListDom);
}
},
/**
*
* 创建底瓢 -- 随机生成
**/
CreateCctvBottomDomList(data, index, page) {
if (data) {
return `
<div class="app-content">
<a class="j-cctv-click-dp" data-href="${data.href}" data-id="${data.id}" data-onsite-or-offsite="${data.onsite_or_offsite}"
rel="nofollow">
<img class="logo-img" src="${data.cover}" alt="${data.title}">
<span class="dp-cctv-title" >${data.title}</span>
<span class="dp-lj-into" >立即进入 </span>
</a>
</div>
`
}
},
/**
*
* 创建底瓢 -- 随机生成 -- 跑量页
**/
CreateCctvBottomDomPlList(data, index, page) {
if (data) {
return `
<div class="app-content">
<a class="j-cctv-click" data-href="${data.href}" data-id="${data.id}" data-onsite-or-offsite="${data.onsite_or_offsite}" rel="nofollow">
<img class="logo-img" class="logo-img" src="${data.cover}" alt="${data.title}">
<span class="dp-cctv-title" >${data.title}</span>
</a>
<i class="close-img icon iconfont icon-shanchu1" id="close-di-but"></i>
</div>
`
}
},
/**
*
* 视频列表dom
*
***/
CreatListCctv(list,arrConfigs=[]) {
var cctvListStr = "";
if (list) {
cctvListStr += `
<li class="video_li swiper-slide">
<a class="j-cctv-click" data-href="${list.href}" data-id="${list.id}" data-onsite-or-offsite="${list.onsite_or_offsite}" rel="nofollow">
<div class="cover_dv">
<img class="lazyLoad videoCover jqlazyload"
alt="${list.title}"
src="${arrConfigs['STATIC_SOURCE_DOMAIN']}/siteConfig/img/video.webp" data-wh=0.69
data-original="${list.cover}"/>
</div>
<h3>${list.title}</h3>
</a>
</li>
`;
return cctvListStr;
}
},
}
export default CommonCctv;

View File

@@ -0,0 +1,257 @@
import { parseInt } from 'lodash';
import CctvsJs from '../class/cctv';
import ConfigsJs from '../class/config';
import { downloadImage,outPutLog,layerPopup } from '../public/commonFun.js';
const Configs = new ConfigsJs();
// 首页弹窗
const IndexCctv = {
intPopUpsIndex: 0,
init() {
const Cctvs = new CctvsJs();
let CctvTipIndex = Cctvs.getDataByWhere(106, 211, [301]);
console.log(CctvTipIndex)
let CctvTipIndexDom = `
<!--首页弹窗遮挡层-->
<div class="index-center-tc-zdc j-close-occlusion-layer"></div>
`
//首页弹窗广告数量
if (document.querySelector(".index-center-tc-num") ) {
document.querySelector(".index-center-tc-num").innerText = (CctvTipIndex.length-1)
}
/**
* 首页弹窗
*
*/
CctvTipIndex.forEach((item, index) => {
if (item) {
if (item.title == '域名弹窗' && index == 0) {
CctvTipIndexDom += this.CreateCctvTipIndexPupopDomainFun(item, index)
}else{
CctvTipIndexDom += this.CreateCctvTipIndexFun(item, index);
}
}
})
//首页弹窗广告
if (!this.isFirstLoadHomeDomanFun() && CctvTipIndex.length>0 ) {
$("body.home-web").append(CctvTipIndexDom)
}
this.addEvent()
},
/**
* 绑定点击事件-初始化
*/
addEvent(){
// 保存相册
$(".j-genimg").on('click', function () {
if (!window.HTMLCanvasElement) {
layerPopup("请截图保存!", 3)
return;
}
const layerIndexTc = layerPopup("拼命保存中。。");
html2canvas(document.querySelector(".index-center-tc"), {
useCORS: true, // 启用跨域配置
logging: true, // 启用日志记录以进行调试
backgroundColor: null // 保持透明背景(如果需要)
}).then(canvas => {
var clipImgBase64 = canvas.toDataURL();
// 生成图片
var clipImg = new Image();
clipImg.src = clipImgBase64;
downloadImage(clipImgBase64);
layer.close(layerIndexTc);
}).catch(err => {
console.error("html2canvas 出错:", err);
layer.close(layerIndexTc);
layerPopup("请手动截图保存!", 3)
});
});
// 关闭弹窗
$(".j-close-index-pop-ups").on('click', (event) => {
let intPopUpsIndex = $(event.currentTarget).attr('data-index')
this.closeIndexTcfun(intPopUpsIndex)
})
// 关闭遮挡层
$(".j-close-occlusion-layer").on('click', () => {
console.log(this.intPopUpsIndex)
this.closeIndexTcfun(this.intPopUpsIndex)
})
},
/**
*
* 创建首页弹窗广告
* h5
**/
CreateCctvTipIndexPupopDomainFun(data, index) {
if (typeof data == 'object') {
if (data.title == '域名弹窗' && index == 0) {
return `
<div class="index-center-tc index-center-tc-index${index} df-index-center-tc df-index-center-tc" >
<div style="width:300px">
<i class="index-center-tc-close icon iconfont icon-shanchu1 j-close-index-pop-ups" data-index="${index}" ></i>
<a>
<img class="index-center-tc-bjimg jqlazyload" src="${data.cover}" data-original="${data.cover}" />
</a>
<div class="index-center-tc-op-domain df-top-domain j-share" data-sharedom=".index-center-tc-op-domain-text" >
<p class="index-center-tc-op-domain-text">${Configs.get('STANDBY_URL')}</p>
</div>
<!--
<div class="index-center-tc-yj-domain tc-domain j-share" data-sharedom=".index-center-tc-yj-domain-text" >
<p class="index-center-tc-yj-domain-text">${Configs.get('VIP_DOMAIN_1')}</p>
</div>
-->
<div class="index-center-tc-vip1-domain tc-domain j-share" data-sharedom=".index-center-tc-vip1-domain-text" >
<p class="index-center-tc-vip1-domain-text">${Configs.get('VIP_DOMAIN_1')}</p>
</div>
<div class="index-center-tc-vip2-domain tc-domain j-share" data-sharedom=".index-center-tc-vip2-domain-text" >
<p class="index-center-tc-vip2-domain-text">${Configs.get('VIP_DOMAIN_2')}</p>
</div>
<div class="index-center-tc-vip3-domain tc-domain j-share" data-sharedom=".index-center-tc-vip3-domain-text" >
<p class="index-center-tc-vip3-domain-text">${Configs.get('VIP_DOMAIN_3')}</p>
</div>
<a class="index-center-tc-fs1-domain tc-domain" href="${Configs.get('TG_URL', null)}" target="_blank">
<p class="index-center-tc-fs1-domain-text" >${Configs.get('TG_URL', null)}</p>
</a>
<a class="index-center-tc-fs2-ios tc-domain" href="https://f5d3.xyz" target="_blank">
<p ><!--点击查看解决苹果手机无法加入和查看群内容--></p>
</a>
<div class="index-center-tc-new-mail tc-domain j-share" data-sharedom=".index-center-tc-new-mail-text">
<p class="index-center-tc-new-mail-text">${Configs.get('NEW_EMAIL')}</p>
</div>
<div class="index-center-tc-btn">
<div class="index-center-tc-btn-left j-genimg" ></div>
<div class="index-center-tc-btn-right j-share" data-sharedom=".yjfz-nr-dv" ></div>
</div>
<div class="yjfz-nr-dv">
官方永久域名:<br>
${Configs.get('VIP_DOMAIN_1')}<br>
你的VIP专属域名<br>
${Configs.get('VIP_DOMAIN_1')}<br>
${Configs.get('VIP_DOMAIN_2')}<br>
${Configs.get('VIP_DOMAIN_3')}<br>
官方万人粉丝群:<br>
${Configs.get('TG_URL')}<br>
官方自动回复最新邮箱地址:<br>
${Configs.get('NEW_EMAIL')}<br>
</div>
</div>
</div>
`
}
}
},
/**
*
* 创建首页弹窗广告
* h5
**/
CreateCctvTipIndexFun(data, index) {
if (typeof data == 'object') {
//index++
//data.href = framt_cctv_url(data.href,secretUrl)
let strStyle = `style="display: none;"`
if(index == 0){
strStyle = `style="display: block;"`
}
return `
<div class="index-center-tc index-center-tc-index${index}" ${strStyle}>
<div style="width:300px">
<i class="index-center-tc-close icon iconfont icon-shanchu1 j-close-index-pop-ups" data-index="${index}"></i>
<a rel="nofollow" class="j-cctv-click" data-href="${data.href}" data-id="${data.id}" data-onsite-or-offsite="${data.onsite_or_offsite}" >
<img class="index-center-tc-bjimg jqlazyload" src="${data.cover}" data-original="${data.cover}" alt="" />
</a>
</div>
</div>
`
}
},
/*
* 检测是否n分钟内是否访问过访问首页
* intMinute 分钟
*/
isFirstLoadHomeDomanFun(intMinute = Configs.get('HOMEPAGE_LOAD_POPUPS_NUM')) {
let currentDomain = document.domain
let isFirstLoadHome = localStorage.getItem("isFirstLoadHome");
let isFirstLoadHomeTime = localStorage.getItem("isFirstLoadHomeTime") ? localStorage.getItem("isFirstLoadHomeTime") : 0;
isFirstLoadHomeTime = Number(isFirstLoadHomeTime)
let timestamp = new Date().getTime();
let timeLeft = timestamp - isFirstLoadHomeTime
outPutLog(currentDomain)
outPutLog(isFirstLoadHome)
outPutLog(isFirstLoadHomeTime)
outPutLog(timestamp)
outPutLog(timeLeft + '===' + intMinute * 60 * 1000)
if (isFirstLoadHome == currentDomain && timeLeft <= intMinute * 60 * 1000) {
outPutLog('非首次访问')
return true
} else {
outPutLog('首次访问')
localStorage.setItem("isFirstLoadHome", currentDomain);
localStorage.setItem("isFirstLoadHomeTime", timestamp);
return false
}
},
//点击 关闭按钮
closeIndexTcfun(intIndex) {
let intPopusTotal = document.querySelector(".index-center-tc-num").innerText //一共几个弹窗
intIndex = parseInt(intIndex)
intPopusTotal = parseInt(intPopusTotal)
console.log(intPopusTotal)
console.log(intIndex)
if (intIndex >= intPopusTotal) {
//最后一个弹窗才关闭遮挡层
let DomOcclusionLayer = document.querySelector(".index-center-tc-zdc")
DomOcclusionLayer.setAttribute("style", "display:none!important");
//关闭最后一个弹窗
let strClassName = ".index-center-tc-index" + intIndex
let DomPupous = document.querySelector(strClassName)
DomPupous.setAttribute("style", "display:none!important");
} else {
//关当前弹窗
let strCurrentClassName = ".index-center-tc-index" + intIndex
let DomCurrentPupous = document.querySelector(strCurrentClassName)
DomCurrentPupous.setAttribute("style", "display:none!important");
//展示下一个弹窗
let strNextClassName = ".index-center-tc-index" + (intIndex += 1)
let DomNextPupous = document.querySelector(strNextClassName)
DomNextPupous.setAttribute("style", "display:block");
}
this.intPopUpsIndex = intIndex++
}
}
export default IndexCctv;

View File

@@ -0,0 +1,47 @@
import CctvsJs from '../class/cctv';
const Cctvs = new CctvsJs();
import {
getRandomElements
} from '../public/commonFun.js';
// cctv
const InfoCctv = {
strPalaceGridHtml: '',
init(strLoadImg) {
if($(".BodyClass365dh")){
this.genCctvHtml(strLoadImg)
$(".j-cctv-info-palace-grid").html(this.strPalaceGridHtml);
}
},
/**
* 随机宫格宫格 5个
* @returns {string}
*/
genCctvHtml(strLoadImg, arrPageId = [300, 304]) {
let arrRandCctvPalaceGrid = Cctvs.getDataByWhere(102, 214, arrPageId);
if (arrRandCctvPalaceGrid.length > 0) {
arrRandCctvPalaceGrid = getRandomElements(arrRandCctvPalaceGrid,5)
arrRandCctvPalaceGrid.forEach(item => {
this.strPalaceGridHtml +=
`
<div class="list-item ${item.equipment_class} j-cctv-click"
data-href="${item.href}" data-id="${item.id}"
data-onsite-or-offsite="${item.onsite_or_offsite}">
<p class="app-logo">
<img class=" jqlazyload jqlazyload" style="width: 100%;height:100%;"
src="${strLoadImg}"
data-original="${item.cover}">
</p>
<p class="app-name">${item.title}</p>
</div>
`
});
}
return this.strBannerHtml;
},
}
export default InfoCctv;

View File

@@ -0,0 +1,36 @@
import CctvsJs from '../class/cctv';
const Cctvs = new CctvsJs();
// cctv
const TransCctv = {
strBannerHtml : '' ,
init(arrConfigs){
this.genCctvHtml(arrConfigs)
$(".j-head-banner-A2").html(this.strBannerHtml);
},
/**
* 横幅
* @returns {string}
*/
genCctvHtml(arrConfigs,arrPageId=[300,304]){
let CctvCenterBanner = Cctvs.getDataByWhere(101, 210, arrPageId);
if(CctvCenterBanner.length>0){
CctvCenterBanner.forEach(item => {
this.strBannerHtml +=
`
<a class="swiper-slide ${ item.equipment_class } j-cctv-click"
data-href="${ item.href }" data-id="${ item.id }" data-onsite-or-offsite="${ item.onsite_or_offsite }"
rel="nofollow">
<img class="lazyLoad videoCover jqlazyload relate-img" src="${arrConfigs['LAZY_LOADING_OF_BANNER_IMAGES']}" data-wh=0.1 data-original="${ item.cover}" />
</a>
`
});
}
return this.strBannerHtml ;
},
}
export default TransCctv;

View File

@@ -0,0 +1,8 @@
export class Base64Url {
encode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
function toSolidBytes(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
}

View File

@@ -0,0 +1,97 @@
import { apiGetVideoInfo } from '../public/api/index.js';
import { fetchApi,onError} from '../public/api/fetch.js';
class VideoPlayer {
constructor(intPayStatus, intVideoId, CctvOpening, strVideoPlayUrl, strDownUrl) {
this.intPayStatus = intPayStatus;
this.intVideoId = intVideoId;
this.CctvOpening = CctvOpening;
this.strVideoPlayUrl = strVideoPlayUrl;
this.strDownUrl = strDownUrl;
}
init() {
this.intDplay();
}
intDplay() {
if (this.intPayStatus !== 1 && checkIsMemberFn()) {
this.fetchVideoInfo();
return;
}
if (this.shouldShowCctvOpening()) {
this.setupCctvOpening();
} else {
this.startMainVideo();
}
}
fetchVideoInfo() {
let strApiUrl = apiGetVideoInfo + '?vid=' + this.intVideoId;
fetchApi(strApiUrl, null,successFn, onError)
function successFn(res) {
if (res.code == '000') {
videoInfoJs.setDownUrl(res.data.downurl);
videoInfoJs.setPlayUrl(res.data.playurl);
}
}
}
shouldShowCctvOpening() {
const disallowedDevices = ['UCBrowser', 'QuarkBrowser', 'VIVODevice'];
return this.CctvOpening.length > 0 &&
!checkIsMemberStatus() &&
!disallowedDevices.includes(detectBrowserOrDevice());
}
setupCctvOpening() {
this.strCctvHref = this.CctvOpening[0].href;
this.strCctvUrl = this.CctvOpening[0].cover;
this.strCctvUrl.indexOf(".m3u8") > 0 ? this.showCctvVideo() : this.showCctvImg();
this.bindCctvClickEvent();
}
showCctvVideo() {
this.boolIsShowCctvVideo = true;
this.intCountDownTimes = this.intCctvOpeningTimes;
$(".isShow_cctv_video").show();
this.beforePlay(this.strCctvUrl, true);
}
showCctvImg() {
this.boolIsShowCctvImg = true;
this.intCountDownTimes = this.intCctvOpeningTimes;
$(".isShow_cctv_img img").attr('src', this.strCctvUrl);
$(".isShow_cctv_img").show();
}
bindCctvClickEvent() {
if (this.cctvEventBound) return;
$(".isShow_cctv_video").on('click', () => {
if (this.intCountDownTimes === this.intCctvOpeningTimes) {
this.beforePlay(this.strCctvUrl);
return;
}
if (checkIsLoginFn()) {
$(".isShow_cctv_img, .isShow_cctv_video").hide();
this.intCountDownTimes = 0;
clearInterval(this.CctvInterval);
this.setPlayUrl(this.strVideoPlayUrl);
}
});
this.cctvEventBound = true;
}
startMainVideo() {
this.intCountDownTimes = 0;
this.setPlayUrl(this.strVideoPlayUrl);
this.setDownUrl(this.strDownUrl);
}
// ... Any other methods or helpers you might need can be added here.
}
// 使用方式:
// const player = new VideoPlayer(intPayStatus, intVideoId, CctvOpening, strVideoPlayUrl, strDownUrl);
// player.init();

View File

@@ -0,0 +1,130 @@
import EncAndDec from '../public/enc.js'
import {Equipment,clickEvent} from '../public/commonFun.js';
/**
* 广告
*/
class Cctvs {
constructor() {
// 初始化数据
this.arrCctvs = this.getAll();
this.currentEquipmentData = this.getCurrentEquipmentData();
}
/**
* 绑定点击事件
* 所有广告点击
* class="j-cctv-click" data-href="${data.href}" data-id="${data.id}" data-onsite-or-offsite="${data.onsite_or_offsite}"
*/
addEvent() {
$(document).on("click", ".j-cctv-click", function(event) {
event.stopPropagation(); // 阻止事件冒泡
event.preventDefault(); // 阻止默认行为
let strHref = $(this).attr('data-href') ?? '';
let intId = $(this).attr('data-id') ?? '';
let strOnsiteOrOffsite = $(this).attr('data-onsite-or-offsite') ?? '';
console.log(strHref)
clickEvent(strHref, intId, 5, strOnsiteOrOffsite)
})
$(document).on("click", ".j-cctv-click-dp", function(event) {
let strHref = $(this).attr('data-href') ?? '';
let intId = $(this).attr('data-id') ?? '';
let strOnsiteOrOffsite = $(this).attr('data-onsite-or-offsite') ?? '';
clickEvent(strHref, intId, 5, strOnsiteOrOffsite)
})
$(".j-close-float-pupous").on("click", () => {
$("#coupletLeft").addClass("yc")
$("#coupletRight").addClass("yc")
})
}
/**
* 读取所有广告数据
* @returns array
*/
getAll() {
return
let strCtvEncoded = EncAndDec.decryptData(cctvEncodedData, configDecData.MIAO_API_ENCRYPT_KEY);
let CtvEncoded = JSON.parse(strCtvEncoded)
return CtvEncoded.data;
}
/**
* 获取当前设备的数据
* @returns array
*/
getCurrentEquipmentData() {
let currentEquipmentData = []
return
this.arrCctvs.forEach(function (item) {
if (item.status == 1) { // 启用
if (Equipment().isAndroid) {
// 所有设备 + H5(安卓+IOS) + 安卓+ PC+安卓)
if (item.equipment == 400 || item.equipment == 402 || item.equipment == 403 || item.equipment == 405) {
currentEquipmentData.push(item)
}
} else if (Equipment().isPhone) {
// 所有设备 + H5(安卓+IOS) + IOS+ PC+IOS
if (item.equipment == 400 || item.equipment == 402 || item.equipment == 404 || item.equipment == 406) {
currentEquipmentData.push(item)
}
} else {
// 所有设备 + PC + PC+安卓) + PC+ios
if (item.equipment == 400 || item.equipment == 401 || item.equipment == 405 || item.equipment == 406) {
currentEquipmentData.push(item)
}
}
}
})
return currentEquipmentData;
}
/**
* 根据条件读取广告数据
* @param {int} intType
* @param {int} intLocation
* @param {array} arrPageId
* @returns array
*/
getDataByWhere(intType, intLocation, arrPageId) {
return
let arrCctv = []
this.currentEquipmentData.forEach(Cctv => {
if (Cctv.type == intType && Cctv.location == intLocation) {
arrPageId.forEach(intPageId => {
if(Cctv.page_id == intPageId){
arrCctv.push(Cctv)
}
})
}
});
return arrCctv;
}
/**
* 创建横幅 dom
* @param {array} arrCctv
* @param {string} strTip
*/
createBananerDom(arrCctv, strTip = null) {
let DomCctv = ''
arrCctv.forEach((item, index) => {
if (item) {
DomCctv += this.CreateCctvBannerTopDom(item, index, strTip);
}
})
return DomCctv;
}
}
export default Cctvs

View File

@@ -0,0 +1,49 @@
import EncAndDec from '../public/enc.js'
/**
* 后台-网站配置数据
*/
class Configs {
constructor() {
// 初始化配置数据
this.arrConfigs = this.getAll();
}
// 添加或更新配置项
set(key, value) {
this.arrConfigs[key] = value;
}
/**
* 获取配置项
* @param {string} strKey
* @param {string} strType
* @returns string | int | null
*/
get(strKey,strType=null) {
return
let intIndex = this.arrConfigs.findIndex((item) => strKey == item.conf_code)
let strVal = intIndex != -1 ? this.arrConfigs[intIndex].conf_val : null;
if(strType == 'int' && strVal != null)[
strVal = parseInt(strVal)
]
return strVal;
}
// 读取所有配置数据
getAll() {
return
let configEncoded = EncAndDec.decryptData(configEncodedData, configDecData.MIAO_API_ENCRYPT_KEY);
configEncoded = JSON.parse(configEncoded)
return configEncoded.data;
}
}
export default Configs ;
// 使用示例
// var configs = new Configs();
// console.log(Configs.get('PLAY_CCTV_OPENING_TIME','int'));
// console.log(configs.get('PLAY_CCTV_OPENING_TIME','int')); // 输出特定配置blue

View File

@@ -0,0 +1,73 @@
import { asyncFunction} from '../public/api/fetch.js';
import ConfigsJs from './config.js';
const Configs = new ConfigsJs();
/*
* 调用
* 引入 LazyLoading.js
* img 绑定类名 jqlazyload
* img 绑定属性 data-wh=0.69 值根据实质需求定因为如果图片不设置高度offsettop 获取的值不准确
* img dat-original="真实地址"
* img src="懒加载图片"
* import LazyLoadingJs from '../class/lozyLoading';
* const LazyLoading = new LazyLoadingJs();
* LazyLoading.int()
*/
class LazyLoading {
constructor() {
// 初始化配置数据
this.arrImgDom = document.querySelectorAll('.jqlazyload');
}
int() {
var config = {
rootMargin: '0px',
threshold: 0,
}
let observer = new IntersectionObserver((entries, self) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let domImg = entry.target
let strImgSrc = domImg.dataset.original
if (strImgSrc) {
if (strImgSrc.indexOf('encry') >= 0) {
asyncFunction(strImgSrc + '?v=' + Configs.get('COVER_VERSION'))
.then(result => {
// 异步操作成功时的回调
let base64Content = `data:image/png;base64,${result}`;
domImg.src = base64Content
this.setImgHeightFun(domImg)
})
.catch(error => {
// 异步操作失败时的回调
console.error(error);
});
} else {
domImg.src = strImgSrc
domImg.classList.remove("jqlazyload");
this.setImgHeightFun(domImg)
}
}
// 解除观察
self.unobserve(entry.target)
}
})
}, config)
this.arrImgDom.forEach((image) => {
observer.observe(image)
})
}
setImgHeightFun(element) {
let imgDataWh = element.getAttribute('data-wh')
if (imgDataWh) {
let $height = element.getBoundingClientRect().width * Number(imgDataWh)
element.style.height = $height + 'px';
}
element.classList.remove('jqlazyload');
}
}
export default LazyLoading;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
import { fetchApi,onError} from '../public/api/fetch.js';
import { getLoginStatus }from '../public/localstorage.js';
import { getValFromBrowserAddress ,pageJumpFn,layerPopup} from '../public/commonFun.js';
import { apiFundsTransactionsList } from '../public/api/index.js';
document.addEventListener('DOMContentLoaded', function () {
// 登录状态
if (getLoginStatus()) {
//getUserInfo()
}else{
location.href="/login.html"
}
const BillJs = function () {
//支付订单列表
var page = 1
var allpage = 1
$('.load-morn').text('暂无')
getOrderList(page)
function getOrderList(page) {
let apiUrl = apiFundsTransactionsList + '?limit=10' + '&page=' + page
fetchApi(apiUrl, null,successFn, onError)
function successFn(res) {
if (res.code == '000') {
allpage = res.data.total_page
var data = res.data.item
if (page >= res.data.total_page) {
$('.load-morn').text('没有了')
if(data.length ==0 ){
$('.load-morn').text('暂无')
}
} else {
$('.load-morn').text('加载更多 ↓')
}
data.forEach((item) => {
if (item.vo_status == 1) {
item['vp_name'] = '已支付'
} else if (item.vo_status == 1) {
item['vp_name'] = '未支付'
}else {
item['vp_name'] = '已过期'
}
})
if (page == 1) {
data = data
} else {
data = data.concat(data)
}
var $list = $(".detail-list");
setLunDate(data)
// let data2 = [
// {vo_success_at:'2021-06888',created_at:'2021-06',vp_name:'VIP购买',vo_order_no:'171882135426094995HU',vo_price:'¥50.00'},
// {vo_success_at:'2021-07',created_at:'2021-08',vp_name:'VIP购买',vo_order_no:'171882135426094995HU',vo_price:'¥150.00'},
// {vo_success_at:'2021-08',created_at:'2021-09',vp_name:'VIP购买',vo_order_no:'171882135426094995HU',vo_price:'¥250.00'},
// {vo_success_at:'2021-07',created_at:'2021-10',vp_name:'VIP购买',vo_order_no:'171882135426094995HU',vo_price:'¥350.00'}
// ]
// setLunDate(data2)
function setLunDate(data) {
data.forEach((item) => {
var html = ''
html += `
<div class="f48f2ef5_yh">
<div class="f48f2ef5ec">${item.vo_success_at}</div>
<div class="ef9739b7e6 _7d85f9f50c _2e9da47136">
<div>
<div>${item.created_at}</div>
<div>${item.vo_order_no}</div>
</div>
<div>${item.vo_price}</div>
<div class="_4af47fba7d">${item.vp_name}</div>
</div>
</div>
`
$list.append(html);
// 这是jquery的拼接
$list.append($list);
});
}
} else {
layerPopup(res.msg, 3)
console.log(res)
}
}
}
//加载更多
$('.load-morn').click(function () {
if (page >= allpage) {
$('.load-morn').text('没有了')
} else {
page++
getOrderList(page)
}
})
}()
})

View File

@@ -0,0 +1,121 @@
import { apiBindPhone,apiSmsCode } from '../public/api/index.js';
import { fetchApi,onError} from '../public/api/fetch.js';
import { getLoginStatus }from '../public/localstorage.js';
$(document).ready(function() {
// 登录状态
if (getLoginStatus()) {
//getUserInfo()
}else{
location.href="/login.html"
}
const PHONE_LENGTH = 0;
const PASSWORD_MIN_LENGTH = 6;
const PASSWORD_MAX_LENGTH = 20;
let intChangIndex = 0;
const $getCodeButton = $('.get-v-code');
// 去空格
const getValueAndTrim = (selector) => $(selector).length > 0 ? $(selector).val().replace(/\s*/g, "") : "";
// 手机号验证
const isValidPhone = (phone) => {
if (phone.length !== 11 ) {
$(".sc-public-popup").show()
$(".sc-public-popup .sc-trends-text").text(`请填写正确的手机号码`);
return false;
}
return true;
};
//验证码验证
const isValidCode = (code) => {
if (code.length !== 6 ) {
$(".sc-public-popup").show()
$(".sc-public-popup .sc-trends-text").text(`短信验证码必须是6位数字`);
return false;
}
return true;
};
// 提交表单逻辑
const submitForm = async (isLogin) => {
const strPhoneVal = getValueAndTrim(".sc-phone");
const strCodeVal = getValueAndTrim(".sc-code");
if (isLogin ==1) {
//绑定手机号码
if (isValidPhone(strPhoneVal) && isValidCode(strCodeVal)) {
await handleSubmit(strPhoneVal,strCodeVal);
}
}
};
const handleSubmit = async (strPhone,strVCode,) => {
$(".sc-public-popup").show()
$(".sc-public-popup .sc-trends-text").text(`绑定成功`);
let postData = {
'phone':strPhone,
'vcode':strVCode,
}
fetchApi(apiBindPhone, postData,successFun, onError,false)
function successFun(res) {
if (res.code == '000') {
$("#code").val('')
pageJumpFn({ 'url': '/member/info.html?free_vip_data=' + res.data.free_vip_data, 'url_type': 1 })
localStorage.setItem(storageObj.isBingPhoneReturn, true)
} else if (res.code == '2001') {
layerPopup(res.msg, 3)
} else {
layerPopup(res.msg, 3)
}
}
};
//绑定号码
$('.sc-binding-btn').on('click', function() {
submitForm(1);
});
/**
* 发送验证码
*/
const sendMsg = () => {
$(".yzm-btn").on('click', function () {
const intPhone = getValueAndTrim(".sc-phone");
if (isValidPhone(intPhone)) {
getSmsCode(intPhone);
}else{
$(".sc-public-popup").show()
$(".sc-public-popup .sc-trends-text").text(`请填写正确的手机号码`);
}
});
function getSmsCode(strPhone) {
let postData = {
'phone':strPhone,
'type':'reg',
}
fetchApi(apiSmsCode, postData,successFun, onError)
function successFun(res){
if (res.code == '000') {
$(".sc-public-popup").show()
$(".sc-public-popup .sc-trends-text").text(`发送成功,请注意查收`);
}else{
$(".sc-public-popup").show()
$(".sc-public-popup .sc-trends-text").text(`短信已在1分钟内发出请耐心等待`);
}
}
}
}
$(function () {
sendMsg()
//弹窗关闭公共方法2
$(".btn_sty_close").on('click', function () {
$(".sc-prompt-popup").hide()
});
});
});

View File

@@ -0,0 +1,65 @@
import { memberCountDown } from '../public/commonFun.js';
import { fetchApi,onError} from '../public/api/fetch.js';
import { layerPopup} from '../public/commonFun.js';
import { apiPayPackage } from '../public/api/index.js';
import { getLoginStatus }from '../public/localstorage.js';
$(document).ready(function() {
// 登录状态
if (getLoginStatus()) {
//getUserInfo()
}else{
location.href="/login.html"
}
//限时优惠倒计时 无限循环
memberCountDown()
getOrderList()
function getOrderList() {
fetchApi(apiPayPackage, null,successFn, onError)
function successFn(res) {
if (res.code == '000') {
if (res.data.item.length != 0) {
res.data.item.forEach((card) => {
if (card.vp_id == 4) {
var $list = $(".yh-tc-yjvip");
var html = '';
html += `
<a class="relative" href="/chongzhi?id=${card.vp_id}&val=${card.vp_real_price}">
<div style="height:9rem;background: #f4dfc2;margin-bottom:5px;border-radius: 5px;"></div>
<div class="abs _25f0b6f3cd _25ccbe5ac8 _69aa9a34e8">
<div class="_71ab71e6f0 cd69248791">终身VIP限时优惠</div>
<div class="_71ab71e6f0 cd69248791 djs_time" id="sc-countdown-time">21:39:46</div>
<div class="_584c0e0412">限时特价<span>${card.vp_real_price}</span>元 <span class="text_line">原价 ${card.vp_tag_price}</span></div>
</div>
</a>
`;
$list.append(html);
}
// Render all cards, including those with card.vp_id == 4
const cardElement = document.createElement("a");
cardElement.href = `/chongzhi?id=${card.vp_id}&val=${card.vp_real_price}`;
cardElement.className = "d_none point";
cardElement.innerHTML = `
<div class="_5618db95dc _1016bcbbbd grid align_center">
<div class="grid align_center h100 gap5">
<div class="fl align_center gap10">
<div class="a9c1886f50">${card.vp_name}</div>
${card.vp_best_describe ? `<span class="c3b7fd6d8e">${card.vp_best_describe}</span>` : ''}
</div>
<div class="d83e478929">原价 ${card.vp_tag_price}</div>
</div>
<div><span class="_2b48c581b1">${card.vp_real_price}</span><span>元</span></div>
</div>
`;
document.querySelector(".cardContainer").appendChild(cardElement);
});
}
} else {
layerPopup(res.msg, 3);
}
}
}
})

View File

@@ -0,0 +1,196 @@
import { getValFromBrowserAddress, checkIsLoginFn, getPublictUserInfo ,layerPopup} from '../public/commonFun.js';
import { apiPayChannele,apiPayOrderCreate } from '../public/api/index.js';
import { fetchApi,onError,strSite} from '../public/api/fetch.js';
import { getLoginStatus }from '../public/localstorage.js';
$(document).ready(function() {
// 登录状态
if (getLoginStatus()) {
//getUserInfo()
}else{
location.href="/login.html"
}
let intVpId = getValFromBrowserAddress('id')
let intActiveCgId = null
//支付金额
$('.sc-payment-amount').text('¥'+getValFromBrowserAddress('val'))
getChannelList()
let paymentData = [
// {
// method: { id: 'alipay', name: '支付宝88', img: '/assets/huiyuan/images/zhifubao.png' },
// channels: [
// {id: '1', name: '支付宝1', img: '/assets/huiyuan/images/zhifubao.png'},
// {id: '2', name: '支付宝2', img: '/assets/huiyuan/images/zhifubao.png'},
// {id: '3', name: '支付宝3', img: 'v/images/zhifubao.png'},
// ]
// },
// {
// method: { id: 'wechat', name: '微信88', img: '/assets/huiyuan/images/wechat.png' },
// channels: [
// {id: '11', name: '微信1', img: '/assets/huiyuan/images/zhifubao.png'},
// {id: '12', name: '微信2', img: '/assets/huiyuan/images/zhifubao.png'},
// {id: '13', name: '微信3', img: '/assets/huiyuan/images/zhifubao.png'},
// ]
// },
// {
// method: { id: 'test', name: '测试', img: '/assets/huiyuan/images/wechat.png' },
// channels: [
// {id: '21', name: '测试1', img: '/assets/huiyuan/images/zhifubao.png'},
// {id: '22', name: '测试2', img: '/assets/huiyuan/images/zhifubao.png'},
// {id: '23', name: '测试3', img: '/assets/huiyuan/images/zhifubao.png'},
// ]
// }
];
const paymentMethodsContainer = document.getElementById('payment-methods-container');
const paymentChannelsContainer = document.getElementById('payment-channels-container');
function renderPaymentMethods() {
let html = `<div class="fl"><div>支付方式</div></div><div class="mt10"><div class="fl gap5 align_center fl_wrap">`;
paymentData.forEach((data, index) => {
const method = data.method;
html += `
<div id="${method.id}" class="e21f3fa97e point relative ${index === 0 ? 'selected _71a3d26126' : ''}" onclick="selectPaymentMethod(${index})">
<img sizes="100vh" class="point fill undefined" height="33" width="33" alt="${method.name}" src="${method.icon}">
<div class="mt3 ${index === 0 ? 'c63892b6d2' : ''}">${method.name}</div>
<div class="abs eb2a18721c" style="display:${index === 0 ? 'block' : 'none'};"><img sizes="100vh" class="point fill undefined" height="25" width="25" alt="" src="/assets/huiyuan/images/user-center/charge/h.png"></div>
</div>`;
});
html += `</div></div>`;
paymentMethodsContainer.innerHTML = html;
}
function renderPaymentChannels(index) {
const channels = paymentData[index].channels;
intActiveCgId = paymentData[index].channels[0].id
let html = `<div class="fl"><div>渠道选择</div></div><div class="mt10"><div class="fl gap5 align_center fl_wrap">`;
channels.forEach((channel, idx) => {
html += `
<div id="channel-${idx}" class="e21f3fa97e point relative ${idx === 0 ? 'selected _71a3d26126' : ''}" style="height: 25px; display: flex; align-items: center; justify-content: center;" onclick="selectPaymentChannel(${idx}, ${index})">
<div class="mt3 ${idx === 0 ? 'c63892b6d2' : ''} b36fec8841">${channel.name}</div>
<div class="abs eb2a18721c" style="display:${idx === 0 ? 'block' : 'none'};"><img sizes="100vh" class="point fill undefined" height="25" width="25" alt="" src="/assets/huiyuan/images/user-center/charge/h.png"></div>
</div>`;
});
html += `</div></div>`;
paymentChannelsContainer.innerHTML = html;
}
window.selectPaymentMethod = function(index) {
document.querySelectorAll('#payment-methods-container .e21f3fa97e').forEach(el => {
el.classList.remove('selected', '_71a3d26126');
el.querySelector('.mt3').classList.remove('c63892b6d2');
});
paymentData.forEach((data) => {
document.querySelector(`#${data.method.id} .eb2a18721c`).style.display = 'none';
});
const selectedMethod = document.getElementById(paymentData[index].method.id);
intActiveCgId = paymentData[index].channels[0].id
selectedMethod.classList.add('selected', '_71a3d26126');
selectedMethod.querySelector('.mt3').classList.add('c63892b6d2');
selectedMethod.querySelector('.eb2a18721c').style.display = 'block';
renderPaymentChannels(index);
}
window.selectPaymentChannel = function(channelIdx, methodIdx) {
document.querySelectorAll('#payment-channels-container .e21f3fa97e').forEach(el => {
el.classList.remove('selected', '_71a3d26126');
el.querySelector('.mt3').classList.remove('c63892b6d2');
});
paymentData[methodIdx].channels.forEach((channel, idx) => {
document.querySelector(`#channel-${idx} .eb2a18721c`).style.display = 'none';
});
const selectedChannel = document.getElementById(`channel-${channelIdx}`);
selectedChannel.classList.add('selected', '_71a3d26126');
selectedChannel.querySelector('.mt3').classList.add('c63892b6d2');
selectedChannel.querySelector('.eb2a18721c').style.display = 'block';
// 获取点击渠道的 id
intActiveCgId = paymentData[methodIdx].channels[channelIdx].id;
}
/**
* 获取支付通道
*/
function getChannelList() {
let strApiUrl = apiPayChannele + "?vp_id="+intVpId
fetchApi(strApiUrl, null,successFn, onError,'拼命加载中。。。')
function successFn(res) {
if (res.code == '000') {
let arrPayChannel = res.data.item
if(arrPayChannel.length <=0){
layerPopup('暂无支付渠道,请稍后再试!', 3)
return false
}
arrPayChannel.forEach((item)=>{
item.id = item.cg_id
item.name = item.pg_channel_name
if(item.pg_channel_code == 'ZFB'){
item.icon = '/assets/huiyuan/images/zhifubao.png'
}else if(item.pg_channel_code == 'WX'){
item.icon = '/assets/huiyuan/images/wechat.png'
}
})
// 提取 pg_channel_name 和 pg_product_code 到新数组
const extractedData = arrPayChannel.map(PayChannel => {
const filteredElements = arrPayChannel.filter(item => item.pg_channel_code === PayChannel.pg_channel_code);
return {
method:{
name: PayChannel.pg_channel_name,
id: PayChannel.pg_channel_code,
pg_channel_code: PayChannel.pg_channel_code,
icon: PayChannel.icon,
},
channels:filteredElements
};
});
paymentData = extractedData
renderPaymentMethods();
renderPaymentChannels(0); // Show channels for the first payment method by default
} else {
layerPopup(res.msg, 3)
}
}
}
// 确认支付
$(".sc-pay-btn").on('click', function () {
getCreateV(intVpId, intActiveCgId)
});
/**
* 创建支付订单
* @param {number} vp_id // 套餐id
* @param {number} intCgId // 通道id
*/
function getCreateV(intVpId, intCgId) {
let postData = {
'vp_id':intVpId,
'cg_id':intCgId,
'si_id':strSite,
}
if(postData.cg_id == null || postData.cg_id.length ==0 ){
layerPopup('暂无支付渠道,请稍后再试!', 3)
return false
}
fetchApi(apiPayOrderCreate, postData,successFun, onError)
function successFun(res) {
if (res.code == '000') {
let time = setTimeout(()=>{
$(".sc-pay-jump-popup").show()
clearTimeout(time)
},3000)
}
}
}
//立即跳转
$(".sc-Jump-immediately-btn").on('click', function () {
$(".sc-pay-jump-popup").hide()
window.open('https://render.alipay.com/p/yuyan/180020040001212700/?cid=wap_dc', '_blank');
});
})

View File

@@ -0,0 +1,93 @@
import { getValFromBrowserAddress,layerPopup} from '../public/commonFun.js';
import {storageObj ,getLoginStatus }from '../public/localstorage.js';
import { apiLoGout ,apiGetUserInfo} from '../public/api/index.js';
import { fetchApi,onError,strSite} from '../public/api/fetch.js';
if (document.querySelector(".infojs")) {
$(function () {
// 从绑定手机页面返回到个人中心
if (getValFromBrowserAddress('free_vip_data') && localStorage.getItem(storageObj.isBingPhoneReturn)) {
$(".free_vip_data_tip").removeClass("yc")
$(".tip_zdc_body").removeClass("yc")
$(".free_vip_data_num").text(getValFromBrowserAddress('free_vip_data'))
}
//退出点击
$('.logout-url').click(function () {
getLogout()
})
})
// 登录状态
if (getLoginStatus()) {
getUserInfo()
}else{
location.href="/login.html"
}
//退出登录
function getLogout() {
let postData = {}
fetchApi(apiLoGout, postData,successFun, onError, false)
function successFun(res) {
if (res.code == '000') {
$('.mm_id').text('')
$('.mm_name').text('')
$('.another_level_vip').hide()
$('.another_level_vip1').hide()
localStorage.setItem(storageObj.loginStatus, false)
localStorage.setItem(storageObj.isMember, false)
localStorage.setItem(storageObj.tokenKey, '')
localStorage.setItem(storageObj.userInfo, '')
layerPopup('退出成功', 3)
location.href="/"
} else {
layerPopup(res.msg, 3)
}
}
}
//用户详情
function getUserInfo() {
let apiUrl = apiGetUserInfo + `?si_id=${strSite}`
fetchApi(apiUrl, null,successFn, onError)
function successFn(res) {
if (res.code == '000') {
var data = res.data
$("._40cfe6e5fe").text(data.mu_nickname)
$(".user_id").text(data.mu_id)
if(data.mu_email_verified == 0){
$(".j-email-verify").show()
$(".user_email").text(data.mu_email)
}
// if(data.mu_auth_phone == 0){
// $(".j-phone-verify").show()
// }
localStorage.setItem(storageObj.userInfo, JSON.stringify(data))
if (data.mu_is_vip) {
// 会员
localStorage.setItem(storageObj.isMember, true)
$('.user_is_type').text("VIP会员")
$(".mu_vip_expired").show()
$(".user_vip_day").text(data.expire_vip_day + '天')
} else {
// 不是会员
localStorage.setItem(storageObj.isMember, false)
}
}
}
}
}
if (document.querySelector(".settingjs")) {
getSetInfo()
//用户详情
function getSetInfo() {
var data = localStorage.getItem(storageObj.userInfo)
data = JSON.parse(data)
$('.user-phone').text(data.mu_phone)
}
}

View File

@@ -0,0 +1,380 @@
import { layerPopup } from '../public/commonFun-news.js';
import { fetchApi,onError,strSite} from '../public/api/fetch.js';
import { storageObj } from '../public/localstorage.js';
// import { checkoutHuiyuanTip } from '/assets/js/html.js?';
import { apiGetUserInfo,apiLoginByPhone ,apiLoginByEmail,apiReGist} from '../public/api/index.js';
$(document).ready(function() {
const PHONE_LENGTH = 11;
const PASSWORD_MIN_LENGTH = 6;
const PASSWORD_MAX_LENGTH = 20;
let intChangIndex = 0;
const $getCodeButton = $('.get-v-code');
// 去空格
const getValueAndTrim = (selector) => $(selector).length > 0 ? $(selector).val().replace(/\s*/g, "") : "";
// 用户名验证
const isValidUsername = (username) => {
if (username.length < PASSWORD_MIN_LENGTH || username.length > PASSWORD_MAX_LENGTH) {
$('.sc-username-error').text(`必须由${PASSWORD_MIN_LENGTH}-${PASSWORD_MAX_LENGTH}位数字或者字母组成`);
return false;
}
return true;
};
const validateEmail = (strAccount) => {
let regex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
if (strAccount.length < PASSWORD_MIN_LENGTH ) {
$('.sc-username-error').text(`请输入大于六位数的正确邮箱!`);
return false;
}else{
if (regex.test(strAccount) || !strAccount) {
return true;
} else {
$('.sc-username-error').text(`账号格式输入不正确,请重新输入`);
return false;
}
}
}
// 手机号验证
const isValidPhone = (phone) => {
if (phone.length < PHONE_LENGTH ) {
$('.sc-phone-error').text(`请填写正确的手机号码`);
return false;
}
return true;
};
//验证码验证
const isValidCode = (code) => {
if (code.length !== 6 ) {
$('.sc-code-error').text(`短信验证码必须是6位数字`);
return false;
}
return true;
};
// 密码验证
const isValidPassword = (password, confirmPass = null) => {
if (password.length < PASSWORD_MIN_LENGTH || password.length > PASSWORD_MAX_LENGTH) {
$('.sc-password-error').text(`密码必须由${PASSWORD_MIN_LENGTH}-${PASSWORD_MAX_LENGTH}位数字或者字母组成`);
return false;
}
if (confirmPass !== null && password !== confirmPass) {
$('.sc-confirm-password-error').text(`两次密码不匹配,请确认后重新输入`);
return false;
}
return true;
};
// 输入框监听事件
const setupInputValidation = (selector, errorSelector, validationFunc,type) => {
$(selector).bind('input propertychange', function(e) {
const value = e.target.value.replace(/\s*/g, "");
const strPasswordVal2 = getValueAndTrim(".sc-password");
const strConfirmPasswordval2 = getValueAndTrim(".sc-confirm-password");
if (!validationFunc(value)) {
if(type == 0){
$(errorSelector).text(value.length === 0 ? `请输入邮箱` : $(errorSelector).text());
}else if (type == 2){
$(errorSelector).text(value.length === 0 ? `请填写正确的手机号码` : $(errorSelector).text());
}else if (type == 1){
$(errorSelector).text(value.length === 0 ? `请输入密码` : $(errorSelector).text());
}else{
$(errorSelector).text(value.length === 0 ? `短信验证码必须是6位数字` : $(errorSelector).text());
}
if(type == 1){
// 检查确认密码是否匹配
if (strConfirmPasswordval2.length > 0 && strConfirmPasswordval2 !== strPasswordVal2) {
$('.sc-confirm-password-error').text(`两次密码不匹配,请确认后重新输入`);
} else {
$('.sc-confirm-password-error').text(``);
}
}
} else {
$(errorSelector).text('');
if(type == 1){
// 检查确认密码是否匹配
if (strConfirmPasswordval2.length > 0 && strConfirmPasswordval2 !== strPasswordVal2) {
$('.sc-confirm-password-error').text(`两次密码不匹配,请确认后重新输入`);
} else {
$('.sc-confirm-password-error').text(``);
}
}
}
});
};
// 0代表用户名 1密码 2手机号 1确认密码 3验证码
setupInputValidation(".sc-username", ".sc-username-error", isValidUsername,0);
setupInputValidation(".sc-code", ".sc-code-error", isValidCode,3);
setupInputValidation(".sc-phone", ".sc-phone-error", isValidPhone,2);
setupInputValidation(".sc-password", ".sc-password-error", (val) => isValidPassword(val),1);
setupInputValidation(".sc-confirm-password", ".sc-confirm-password-error", (val) => isValidPassword($('.sc-password').val(), val),1);
// 提交表单逻辑
const submitForm = async (isLogin) => {
const strUsernameVal = getValueAndTrim(".sc-username");
const strPhoneVal = getValueAndTrim(".sc-phone");
const strCodeVal = getValueAndTrim(".sc-code");
const strPasswordVal = getValueAndTrim(".sc-password");
const strConfirmPasswordval = getValueAndTrim(".sc-confirm-password");
if (isLogin ==1) {
//登录
if (intChangIndex === 0) {
if (isValidUsername(strUsernameVal) && isValidPassword(strPasswordVal)) {
await handleSubmit(strUsernameVal, strPasswordVal,isLogin);
}
} else {
if (isValidPhone(strPhoneVal) && isValidPassword(strPasswordVal)) {
await handleSubmit(strPhoneVal, strPasswordVal,isLogin);
}
}
} else if (isLogin ==2) {
//注册
if (validateEmail(strUsernameVal) && isValidPassword(strPasswordVal, strConfirmPasswordval)) {
await handleSubmit(strUsernameVal, strPasswordVal,isLogin,strConfirmPasswordval);
}
}else if (isLogin ==3){
//忘记密码
if (isValidPhone(strPhoneVal) && isValidCode(strCodeVal) && isValidPassword(strPasswordVal, strConfirmPasswordval)) {
await handleSubmit(strPhoneVal,strPasswordVal,isLogin,strConfirmPasswordval,strCodeVal);
}
}
};
const handleSubmit = async (username, password,isLogin,confirmpassword,code,) => {
if(isLogin == 1){
if(intChangIndex == 0){
userLogin(username, password)
}else{
phoneLogin(username, password)
}
}else if(isLogin == 2){
userRegister(username, password)
}else if(isLogin == 3){
forgetPassWord(username, password,code)
}
};
/*
mu_email string Y 用户邮箱
mu_pwd string Y 用户密码
si_id int Y 站点 ID
*/
//用户名登录
function userLogin(username, password) {
let postData = {
'mu_email':username,
'mu_pwd':password,
'si_id':strSite,
}
fetchApi(apiLoginByEmail, postData,successFun, onError)
function successFun(res){
if (res.code == '000') {
layerPopup(res.message, 3)
localStorage.setItem(storageObj.tokenKey, res.data.token)
localStorage.setItem(storageObj.loginStatus, true)
localStorage.setItem(storageObj.isMember, res.data.mu_is_vip)
localStorage.setItem(storageObj.userInfo, res.data)
history.go(-1)
// getInfo()
} else if (res.code == '014') {
// 需要重置密码
strSetPwdKey = res.data.key
localStorage.setItem(storageObj.loginStatus, true)
layerPopup(res.message, 3)
} else {
layerPopup('出错啦!请重试', 3)
}
}
}
//手机登录
function phoneLogin(username, password) {
let postData = {
'phone':username,
'password':password,
'si_id':strSite,
}
fetchApi(apiLoginByPhone, postData,successFun, onError)
function successFun(res){
if (res.code == '000') {
layerPopup(res.message, 3)
localStorage.setItem(storageObj.tokenKey, res.data.token)
localStorage.setItem(storageObj.loginStatus, true)
localStorage.setItem(storageObj.isMember, res.data.mu_is_vip)
localStorage.setItem(storageObj.userInfo, res.data)
// history.go(-1)
// getInfo()
}else if (res.code == '014') {
// 需要重置密码
strSetPwdKey = res.data.key
localStorage.setItem(storageObj.loginStatus, true)
layerPopup(res.message, 3)
} else {
layerPopup('出错啦!请重试', 3)
}
}
}
//用户注册
function userRegister(username, password) {
let postData = {
'mu_email':username,
'mu_pwd':password,
'si_id':strSite,
mu_channel_code: localStorage.getItem(EncAndDec.encryptData('dlfx_channelcode')) || '',
mu_channel_domain: localStorage.getItem(EncAndDec.encryptData('dlfx_sourceDomain')) || '',
mu_referrer_id: localStorage.getItem(EncAndDec.encryptData('dlfx_muReferrerId')) || ''
}
fetchApi(apiReGist, postData,successFun, onError)
function successFun(res){
if (res.code == '000') {
//$(".sc-public-popup").show()
layerPopup('注册成功!' ,3)
let time = setTimeout(()=>{
clearTimeout(time)
history.go(-1)
},1500)
}else{
layerPopup('请求超时,请稍后再试', 3)
}
}
}
//忘记密码
function forgetPassWord(username, password,code) {
let postData = {
'phone':username,
'password':password,
'code':code,
}
fetchApi(apiLoginByPhone, postData,successFun, onError)
function successFun(res){
console.log(res.message)
layerPopup(res.message, 3)
console.log(res)
}
}
//用户详情
function getInfo() {
fetchApi(apiGetUserInfo, null,successFn, onError)
function successFn(res){
if (res.code == '000') {
var data = res.data
localStorage.setItem(storageObj.userInfo, JSON.stringify(data))
let timestamp = Date.parse(new Date());
if (data.mu_vip_expired != null) {
localStorage.setItem(storageObj.isMember, true)
let vip_timesStamp = new Date(data.mu_vip_expired).getTime()
let seconds = 2 * 24 * 60 * 60 * 1000
if (vip_timesStamp - timestamp > seconds) {
console.log('大于2天')
history.go(-1)
} else {
console.log('小于2天')
if (vip_timesStamp < timestamp) {
localStorage.setItem(storageObj.isMember, false)
$('.charge-dialog').show()
} else {
$('.vip-dialog').show()
$('.tip-date').text('你的会员即将过期,请及时续费,续费会员,纵想激情')
}
}
} else {
// $(".sc-vip_modal").show()
// $('.yh-expire').show()
localStorage.setItem(storageObj.isMember, false)
}
} else {
layerPopup(res.msg, 3)
}
}
}
//登录
$('.sc-login-btn').on('click', function() {
submitForm(1);
});
//注册
$('.sc-register-btn').on('click', function() {
submitForm(2);
});
//忘记密码
$('.sc-forget-btn').on('click', function() {
submitForm(3);
});
// 登录页 用户登录/手机登录切换
var a = $(".grid .login_item");
var c = $(".grid .input-pu-lic")
for (var i = 0; i < a.length; i++) {
a[i].index = i;
a[i].setAttribute("index", i);
a[i].onclick = function () {
for (var i = 0; i < a.length; i++) {
a[i].className = 'undefined point login_item'
c[i].className = 'align_center gap10 input-pu-lic ee58ce4adf';
}
this.className = '_2a4b899e3f point login_item';
var index = this.getAttribute("index");
intChangIndex = index
c[index].className = 'fl align_center gap10 _53fc7f89df _17d18e62bf input-pu-lic';
$(".sc-username").val('')
$(".sc-password").val('')
$(".sc-phone").val('');
$('.sc-username-error').text(`请输入邮箱`);
$('.sc-password-error').text(`请输入密码`);
$('.sc-phone-error').text(`请填写正确的手机号码`);
}
}
/**
* 发送验证码
*/
const sendMsg = () => {
$(".yzm-btn").on('click', function () {
const intPhone = getValueAndTrim(".sc-phone");
if (isValidPhone(intPhone)) {
getSmsCode(intPhone);
}else{
// $(".sc-public-popup").show()
// $(".sc-public-popup .sc-trends-text").text(`请填写正确的手机号码`);
}
});
function getSmsCode(strPhone) {
let postData = {
'phone':strPhone,
'type':'reg',
}
let timerCount = 60;
let timerCctvQiDon = setInterval(() => {
if (timerCount <= 0) {
$getCodeButton.text('获取验证码');
clearInterval(timerCctvQiDon);
} else {
timerCount--;
$getCodeButton.text(`${timerCount} s`);
}
}, 1000);
}
}
$(".sc-junp-vip-buy").on('click', function () {
window.open('/taochang');
});
$(function () {
sendMsg()
});
});

View File

@@ -0,0 +1,147 @@
import { layerPopup } from '../public/commonFun.js';
import { resetPasswordByKey, setPasswd } from '../public/api/index.js';
import { fetchApi,onError} from '../public/api/fetch.js';
import { getLoginStatus }from '../public/localstorage.js';
// 登录状态
if (getLoginStatus()) {
//getUserInfo()
}else{
location.href="/login.html"
}
/**
* 展示和隐藏密码
*/
export const showHidePwd = function () {
const inputElements = ['user_old_password', 'user_password', 'user_password2'];
const visibleElements = ['user_old_password_visible_img', 'user_password_visible_img', 'user_password2_visible_img'];
const isVisibleData = [false, false, false];
$('.j-closeEye').on('click', function () {
let index = $(this).data('index')
isVisibleData[index] = !isVisibleData[index];
if (isVisibleData[index]) {
$(`#${inputElements[index]}`).attr('type', 'text');
$(`#${visibleElements[index]}`).removeClass('icon-closeEye');
$(`#${visibleElements[index]}`).addClass('icon-eye1');
} else {
$(`#${inputElements[index]}`).attr('type', 'password');
$(`#${visibleElements[index]}`).addClass('icon-closeEye');
$(`#${visibleElements[index]}`).removeClass('icon-eye1');
}
})
}
/**
* 验证密码格式
* @returns obj
*/
export const verifyPwd = function () {
var strOldPassword = $("#user_old_password").val().replace(/\s*/g, "");
var strNewsPassword = $("#user_password").val().replace(/\s*/g, "");
var strConfirmPassword = $("#user_password2").val().replace(/\s*/g, "");
if (strOldPassword.length < 6) {
layerPopup('当前密码必须由6-20位的数字或者字母组成', 3)
return false;
}
if (strNewsPassword.length < 6) {
layerPopup('新密码必须由6-20位的数字或者字母组成', 3)
return false;
}
if (strConfirmPassword.length < 6) {
layerPopup('确认密码必须由6-20位的数字或者字母组成', 3)
return false;
} else {
if (strConfirmPassword !== strNewsPassword) {
layerPopup('两次密码不匹配,请确认后重新输入', 3)
return false;
}
}
return { 'strOldPassword': strOldPassword, 'strNewsPassword': strNewsPassword }
}
/**
* 修改密码-登录
*/
export const SetPasswdFun = function (strOldPassword, strEwsPassword, strSetPwdKey,Callback) {
let postData = {
'mu_old_password':strOldPassword,
'mu_new_password':strEwsPassword,
'key':strSetPwdKey,
}
fetchApi(resetPasswordByKey, postData,successFun, onError)
function successFun(res){
CallbackFun(res,Callback)
}
}
/**
* 修改密码-个人中心3
*/
export const setPasswdFun2 = function (strOldPassword, strEwsPassword,Callback=null) {
let postData = {
'oldpassword':strOldPassword,
'password':strEwsPassword,
}
fetchApi(setPasswd, postData,successFun, onError)
function successFun(res){
CallbackFun(res,Callback)
}
}
/**
* 处理回调
* @param {*} res
* @param {*} Callback
*/
const CallbackFun = function(res,Callback) {
if(Callback) Callback(res)
if (res.code == '000') {
$("#user_old_password").val('')
$("#user_password").val('')
$("#user_password2").val('');
$('.msg-dialog2').show();
$('.tip-hy').text('修改成功')
} else if (res.code == '2001') {
$('.msg-dialog').show();
$('.tip-hy').text(res.msg)
} else {
$('.msg-dialog').show();
$('.tip-hy').text(res.msg)
}
}
/**
* 邮箱找回密码-登录页入口
*/
export const resetPwdByEmail = function () {
$('.j-reset-pwd-btn').on('click', function () {
layerPopup('重置密码已经发送到你的邮箱,请按邮件里的密码重新登录!',5)
setTimeout(()=>{
location.href="/member/login.html"
},5000)
})
}
/**
* 验证邮箱-个人中心页入口
*/
export const verifyEmail = function () {
$('.j-verify-email-btn').on('click', function () {
layerPopup('重置密码已经发送到你的邮箱,请按邮件里的密码重新登录!',5)
setTimeout(()=>{
location.href="/member/login.html"
},5000)
})
}

View File

@@ -0,0 +1,112 @@
import { apiUserInfoSave } from '../public/api/index.js';
import { fetchApi,onError,strSite} from '../public/api/fetch.js';
import { layerPopup } from '../public/commonFun-news.js';
import { getLoginStatus }from '../public/localstorage.js';
$(document).ready(function() {
// 登录状态
if (getLoginStatus()) {
//getUserInfo()
}else{
location.href="/login.html"
}
const PASSWORD_MIN_LENGTH = 6;
const PASSWORD_MAX_LENGTH = 20;
// 去空格
const getValueAndTrim = (selector) => $(selector).length > 0 ? $(selector).val().replace(/\s*/g, "") : "";
// 当前密码验证
const isValidCurrentPassword = (password) => {
if (password.length < PASSWORD_MIN_LENGTH ) {
$('.sc-current-password-error').text(`请输入密码`);
return false;
}
return true;
};
// 密码验证
const isValidPassword = (password, confirmPass = null) => {
if (password.length < PASSWORD_MIN_LENGTH || password.length > PASSWORD_MAX_LENGTH) {
$('.sc-password-error').text(`密码必须由${PASSWORD_MIN_LENGTH}-${PASSWORD_MAX_LENGTH}位数字或者字母组成`);
return false;
}
if (confirmPass !== null && password !== confirmPass) {
$('.sc-confirm-password-error').text(`两次密码不匹配,请确认后重新输入`);
return false;
}
return true;
};
// 输入框监听事件
const setupInputValidation = (selector, errorSelector, validationFunc,type) => {
$(selector).bind('input propertychange', function(e) {
const value = e.target.value.replace(/\s*/g, "");
const strPasswordVal = getValueAndTrim(".sc-password");
const strConfirmPasswordval = getValueAndTrim(".sc-confirm-password");
if (!validationFunc(value)) {
$(errorSelector).text(value.length === 0 ? `请输入密码` : $(errorSelector).text());
if(type == 1){
// 检查确认密码是否匹配
if (strConfirmPasswordval.length > 0 && strConfirmPasswordval !== strPasswordVal) {
$('.sc-confirm-password-error').text(`两次密码不匹配,请确认后重新输入`);
} else {
$('.sc-confirm-password-error').text(``);
}
}
} else {
$(errorSelector).text('');
if(type == 1){
// 检查确认密码是否匹配
if (strConfirmPasswordval.length > 0 && strConfirmPasswordval !== strPasswordVal) {
$('.sc-confirm-password-error').text(`两次密码不匹配,请确认后重新输入`);
} else {
$('.sc-confirm-password-error').text(``);
}
}
}
});
};
// 0代表用户名 1密码 2手机号 1确认密码 3验证码
setupInputValidation(".sc-current-password", ".sc-current-password-error", isValidCurrentPassword,0);
setupInputValidation(".sc-password", ".sc-password-error", (val) => isValidPassword(val),1);
setupInputValidation(".sc-confirm-password", ".sc-confirm-password-error", (val) => isValidPassword($('.sc-password').val(), val),1);
// 提交表单逻辑
const submitForm = async (isLogin) => {
const strCurrentPasswordVal = getValueAndTrim(".sc-current-password");
const strPasswordVal = getValueAndTrim(".sc-password");
const strConfirmPasswordval = getValueAndTrim(".sc-confirm-password");
if (isLogin ==1) {
//修改密码
if (isValidCurrentPassword(strCurrentPasswordVal) && isValidPassword(strPasswordVal, strConfirmPasswordval)) {
await handleSubmit(strCurrentPasswordVal, strPasswordVal,strConfirmPasswordval);
}
}
};
const handleSubmit = async (strCurrentPasswordVal, strPasswordVal) => {
let postData = {
'old_mu_pwd':strCurrentPasswordVal,
'mu_pwd':strPasswordVal,
'si_id':strSite,
}
fetchApi(apiUserInfoSave, postData,successFun, onError)
function successFun(res){
if(res.code == '000'){
layerPopup('修改成功', 3)
let time = setTimeout(()=>{
clearTimeout(time)
history.go(-1)
},1500)
// $(".sc-public-popup").show()
// $('.sc-trends-text').text(`修改成功`);
}
}
};
//修改密码
$('.sc-modify-btn').on('click', function() {
submitForm(1);
});
});

View File

@@ -0,0 +1,149 @@
// 首页弹窗隐藏
function setupHideOnClick(elementId) {
// 获取元素
var element = document.querySelector(elementId);
// 如果元素不存在,退出函数
if (!element) {
return;
}
// 获取当前日期字符串 a2bb38a3fa
var today = new Date().toISOString().slice(0, 10);
// 检查本地存储中的日期是否与今天匹配
if (localStorage.getItem('hideDate_' + elementId) === today) {
// 如果匹配,则隐藏元素
element.style.display = 'none';
} else {
// 如果不匹配,则显示元素并添加点击事件监听器
element.style.display = 'block';
element.addEventListener('click', function() {
// 隐藏元素
element.style.display = 'none';
// 更新本地存储,保存当前日期
localStorage.setItem('hideDate_' + elementId, today);
});
}
}
// 懒加载
function initLazyLoad() {
let lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));
if ("IntersectionObserver" in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.getAttribute("data-src");
lazyImage.classList.remove("lazy");
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
} else {
// Fallback for older browsers
let lazyLoad = function() {
let active = false;
if (active === false) {
active = true;
setTimeout(function() {
lazyImages.forEach(function(lazyImage) {
if ((lazyImage.getBoundingClientRect().top <= window.innerHeight && lazyImage.getBoundingClientRect().bottom >= 0) && getComputedStyle(lazyImage).display !== "none") {
lazyImage.src = lazyImage.getAttribute("data - src");
lazyImage.classList.remove("lazy");
lazyImages = lazyImages.filter(function(image) {
return image !== lazyImage;
});
if (lazyImages.length === 0) {
document.removeEventListener("scroll", lazyLoad);
window.removeEventListener("resize", lazyLoad);
window.removeEventListener("orientationchange", lazyLoad);
}
}
});
active = false;
}, 200);
}
};
document.addEventListener("scroll", lazyLoad);
window.addEventListener("resize", lazyLoad);
window.addEventListener("orientationchange", lazyLoad);
}
}
function showOverlay(message, duration = 2000) {
const overlay = document.createElement('div');
overlay.id = "overlay";
overlay.className = "overlay";
overlay.style.display = "flex"; // 显示遮罩层
const overlayContent = document.createElement('div');
overlayContent.className = "overlay-content";
overlayContent.textContent = message;
overlay.appendChild(overlayContent);
document.body.appendChild(overlay);
// 设置定时器隐藏遮罩层并移除它
setTimeout(function() {
document.body.removeChild(overlay);
}, duration); // 默认2秒后隐藏
}
// 复制粘贴
function copyTextToClipboard(text) {
const copyText = document.createElement('input');
copyText.type = 'text';
copyText.value = text;
copyText.style.position = 'absolute';
copyText.style.left = '-9999px';
document.body.appendChild(copyText);
// 复制功能
copyText.select();
copyText.setSelectionRange(0, 99999); // For mobile devices
document.execCommand("copy");
document.body.removeChild(copyText); // 移除输入框
}
function handleCopyButtonClick() {
const textToCopy = location.href;
copyTextToClipboard(textToCopy);
showOverlay("您已成功复制链接,快分享给好友吧~");
}
// 确保在 DOM 加载完成后执行脚本
document.addEventListener('DOMContentLoaded', function() {
// 设置首页弹窗
setupHideOnClick('._31bb2383c4');
initLazyLoad(); // 调用方法初始化懒加载
// 分享
if(document.querySelector("#ShareButton")){
}
// const GuideButton = document.querySelector("#ShareButton");
// GuideButton.addEventListener("click", handleCopyButtonClick);
});

View File

@@ -0,0 +1,92 @@
$(document).ready(function() {
//专题 btn_gray
$(".btn_gray").on('click', function () {
$(".sc-gray-jump-popup").show()
});
// $(".btn_gray").on('click', function () {
// $(".sc-jc-pd-img").show()
// });
//精彩片段
const imagesArray = [
"/static/images/default/loading/750x422.jpg",
"https://i.imgtg.com/2023/01/16/QRBHS.jpg",
"/static/images/default/loading/750x422.jpg",
"/static/images/default/loading/750x422.jpg",
"/static/images/default/loading/750x422.jpg",
];
const imageContainer = document.getElementById("imageContainer");
let strHtml = ''; // Define html before using it
imagesArray.forEach(img => {
strHtml += `
<div class="_64cc81278a" onclick="openPopup('${img}')">
<img sizes="100vh" class="point fill undefined" height="30" width="0" alt="" src="${img}">
<div style="position: relative; float: inline-start;">
<img sizes="100vh" class="point fill undefined" height="20" width="20" alt="" src="/static/images/zoom.png" style="position: absolute; top: 0px; right: 0px;">
<img sizes="100vh" class="point fill lazy" height="0" width="0" alt="" src="${img}" style="object-fit: contain; width: 100%; height: 100%;">
</div>
</div>`
});
imageContainer.innerHTML = strHtml;
window.openPopup = function(imgSrc) {
$(".sc-jc-pd-img img").attr("src", imgSrc);
$(".sc-jc-pd-img").show()
}
const dataArray = [
{
title: '[樱空桃桃] 樱空桃桃-免费观看片段 1',
badge: '免费试看',
image: '/static/images/default/loading/750x422.jpg',
duration: '0:02:58',
date: '10 天前',
description: '此内容为免费观看资源,若需要观看完整版内容请开通捆版包'
},
{
title: '[樱空桃桃] 樱空桃桃-免费观看片段 1',
badge: '免费试看',
image: '/static/images/default/loading/750x422.jpg',
duration: '0:02:58',
date: '10 天前',
description: '此内容为免费观看资源,若需要观看完整版内容请开通捆版包'
},
// Add more objects as needed
];
const container = document.getElementById('dynamicContentContainer');
container.innerHTML = ''; // Clear existing content
dataArray.forEach((item, index) => {
const content = `
<div class="_045eeff507 b13cd7bde3">
<div class="_8e389b3ada to" style="height: auto; max-height: 43px; line-height: 1.3rem; padding-bottom: 8px; font-size: 16px;">
${index + 1}. <span class="pink_badge" style="margin-right: 3px;">${item.badge}</span>${item.title}
</div>
<div class="b29b1e3a20 _1ba75a9421 b8795542a0">
<div class="_5adb102473 _508f1080bd relative">
<img class="point fill i_cvr" height="0" width="0" alt="" src="${item.image}">
<img class="point fill lazy" height="0" width="0" alt="" src="${item.image}" style="object-fit: contain; width: 100%; height: 100%;">
<div class="_45774389f4">
<div>${item.duration}</div>
</div>
<div class="_293abc39de _0a85a12109">
<div>${item.date}</div>
</div>
</div>
<div class="_65325a7a69 acf5ea3bd3">
<div style="white-space: pre-wrap;">${item.description}</div>
</div>
</div>
<div class="_7d13122783 a661c212c5"></div>
<div></div>
</div>
`;
container.innerHTML += content; // Append the new content
});
});

View File

@@ -0,0 +1,127 @@
import {downloadImageFromUrl,copyFun,init} from '../public/commonFun.js';
$(document).ready(function() {
init();
//视频片段-视频下载-立即分享点击切换
const menuItems = document.querySelectorAll('._0b92e5c73f');
const tabContents = document.querySelectorAll('.sc-tab-info');
// Function to reset all highlights and hide all contents
function resetHighlights() {
menuItems.forEach(item => item.classList.remove('_732b697cd0'));
tabContents.forEach(content => content.classList.add('ee58ce4adf'));
}
// Highlight the first item and show the first tab content by default
if(menuItems.length > 0) {
menuItems[0].classList.add('_732b697cd0');
if(tabContents.length > 0) {
tabContents[0].classList.remove('ee58ce4adf');
}
}
// Add click event to each menu item
menuItems.forEach((item, index) => {
item.addEventListener('click', () => {
resetHighlights();
item.classList.add('_732b697cd0');
if(tabContents[index]) {
tabContents[index].classList.remove('ee58ce4adf');
}
});
});
//迅雷下载
$(".sc-thunder").text(`thunder://QUFodHRwczovL3d3dy5tbXh6eGwxLmNvbS9jb21tb24vbWFvbWkvbWFvbWkvLzg5NjEwZmQ4MTIwNzM2NjgyZDc0YTkyZTk4X18yMTE5NDkvODk2MTBmZDgxMjA3MzY2ODJkNzRhOTJlOThfXzIxMTk0OS5tcDRaWg==`)
$(".sc-down-thunder-btn").on('click', function(event) {
const thunderText = $(".sc-thunder").text();
window.open(thunderText, '_blank');
});
//fdm下载
$(".sc-fdm").text(`https://www.mmxzxl1.com/common/maomi/maomi//89610fd8120736682d74a92e98__211949/89610fd8120736682d74a92e98__211949.mp4`)
$(".sc-down-fdm-btn").on('click', function(event) {
const fdmText = $(".sc-fdm").text();
window.open(fdmText, '_blank');
});
//保存二维码
$(".sc-download-btn").on('click', function () {
const imageUrl = 'https://mj.pki.net.cn/build1//images/help/fdm/Mac.jpg'; // 替换为你要下载的图片URL
downloadImageFromUrl(imageUrl)
});
//桃子app
$(".sc-tz-app").on('click', function () {
const textUrl = 'https://oy1gp3100i6r.xyz/?code=nn'; // 替换为你要下载的图片URL
window.open(textUrl, '_blank');
});
// 绑定复制点击事件
$(".data-cp-val").text('b3e8k.com668')
$(".j-copy-select").trigger("click");
// 定义播放线路数据
const playLines = [
{ name: "默认线路2", url: "https://example.com/default.mp4",index:0 },
{ name: "线路13", url: "https://example.com/line1.mp4",index:1 },
{ name: "线路24", url: "https://example.com/line2.mp4" ,index:2}
];
// 获取线路容器
const playlineContainer = document.getElementById("playline-container");
// 动态创建线路按钮并添加到容器中
playLines.forEach((line, index) => {
const lineBtn = document.createElement("div");
lineBtn.className = "faee9a7c48 point PlayLineBtn";
lineBtn.setAttribute("data-playline", line.url);
lineBtn.setAttribute("data-index", index); // 添加索引属性
lineBtn.textContent = line.name;
playlineContainer.appendChild(lineBtn);
});
// 获取视频元素
const videoPlayer = document.getElementById("video-player");
// 设置默认播放线路第二条线路index为1
const defaultPlayLine = playLines[0]; // 第二条线路
videoPlayer.src = defaultPlayLine.url;
videoPlayer.playsinline = true;
videoPlayer.setAttribute("playsinline", defaultPlayLine.index);
videoPlayer.load();
// 绑定点击事件处理程序
playlineContainer.addEventListener("click", function(e) {
if (e.target.classList.contains("PlayLineBtn")) {
const playLineUrl = e.target.getAttribute("data-playline");
const index = e.target.getAttribute("data-index"); // 获取索引
// 更改视频的 src 属性
videoPlayer.src = playLineUrl;
videoPlayer.load();
// 设置 playsinline 属性(根据需要进行处理)
videoPlayer.playsinline = true;
videoPlayer.setAttribute("playsinline", index);
// 根据索引进行不同操作
switch (index) {
case '0':
console.log("播放默认线路2");
break;
case '1':
console.log("播放线路13");
break;
case '2':
console.log("播放线路24");
break;
default:
console.log("播放未知线路");
}
}
});
})

View File

@@ -0,0 +1,7 @@
/**
* Minified by jsDelivr using Terser v5.7.1.
* Original file: /npm/js-base64@3.7.2/base64.js
*
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
*/
!function(t,n){var r,e;"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(r=t.Base64,(e=n()).noConflict=function(){return t.Base64=r,e},t.Meteor&&(Base64=e),t.Base64=e)}("undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:this,(function(){"use strict";var t,n="3.7.2",r="function"==typeof atob,e="function"==typeof btoa,o="function"==typeof Buffer,u="function"==typeof TextDecoder?new TextDecoder:void 0,i="function"==typeof TextEncoder?new TextEncoder:void 0,f=Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="),c=(t={},f.forEach((function(n,r){return t[n]=r})),t),a=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,d=String.fromCharCode.bind(String),s="function"==typeof Uint8Array.from?Uint8Array.from.bind(Uint8Array):function(t,n){return void 0===n&&(n=function(t){return t}),new Uint8Array(Array.prototype.slice.call(t,0).map(n))},l=function(t){return t.replace(/=/g,"").replace(/[+\/]/g,(function(t){return"+"==t?"-":"_"}))},h=function(t){return t.replace(/[^A-Za-z0-9\+\/]/g,"")},p=function(t){for(var n,r,e,o,u="",i=t.length%3,c=0;c<t.length;){if((r=t.charCodeAt(c++))>255||(e=t.charCodeAt(c++))>255||(o=t.charCodeAt(c++))>255)throw new TypeError("invalid character found");u+=f[(n=r<<16|e<<8|o)>>18&63]+f[n>>12&63]+f[n>>6&63]+f[63&n]}return i?u.slice(0,i-3)+"===".substring(i):u},y=e?function(t){return btoa(t)}:o?function(t){return Buffer.from(t,"binary").toString("base64")}:p,A=o?function(t){return Buffer.from(t).toString("base64")}:function(t){for(var n=[],r=0,e=t.length;r<e;r+=4096)n.push(d.apply(null,t.subarray(r,r+4096)));return y(n.join(""))},b=function(t,n){return void 0===n&&(n=!1),n?l(A(t)):A(t)},g=function(t){if(t.length<2)return(n=t.charCodeAt(0))<128?t:n<2048?d(192|n>>>6)+d(128|63&n):d(224|n>>>12&15)+d(128|n>>>6&63)+d(128|63&n);var n=65536+1024*(t.charCodeAt(0)-55296)+(t.charCodeAt(1)-56320);return d(240|n>>>18&7)+d(128|n>>>12&63)+d(128|n>>>6&63)+d(128|63&n)},B=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,x=function(t){return t.replace(B,g)},C=o?function(t){return Buffer.from(t,"utf8").toString("base64")}:i?function(t){return A(i.encode(t))}:function(t){return y(x(t))},m=function(t,n){return void 0===n&&(n=!1),n?l(C(t)):C(t)},v=function(t){return m(t,!0)},U=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,F=function(t){switch(t.length){case 4:var n=((7&t.charCodeAt(0))<<18|(63&t.charCodeAt(1))<<12|(63&t.charCodeAt(2))<<6|63&t.charCodeAt(3))-65536;return d(55296+(n>>>10))+d(56320+(1023&n));case 3:return d((15&t.charCodeAt(0))<<12|(63&t.charCodeAt(1))<<6|63&t.charCodeAt(2));default:return d((31&t.charCodeAt(0))<<6|63&t.charCodeAt(1))}},w=function(t){return t.replace(U,F)},S=function(t){if(t=t.replace(/\s+/g,""),!a.test(t))throw new TypeError("malformed base64.");t+="==".slice(2-(3&t.length));for(var n,r,e,o="",u=0;u<t.length;)n=c[t.charAt(u++)]<<18|c[t.charAt(u++)]<<12|(r=c[t.charAt(u++)])<<6|(e=c[t.charAt(u++)]),o+=64===r?d(n>>16&255):64===e?d(n>>16&255,n>>8&255):d(n>>16&255,n>>8&255,255&n);return o},E=r?function(t){return atob(h(t))}:o?function(t){return Buffer.from(t,"base64").toString("binary")}:S,D=o?function(t){return s(Buffer.from(t,"base64"))}:function(t){return s(E(t),(function(t){return t.charCodeAt(0)}))},R=function(t){return D(T(t))},z=o?function(t){return Buffer.from(t,"base64").toString("utf8")}:u?function(t){return u.decode(D(t))}:function(t){return w(E(t))},T=function(t){return h(t.replace(/[-_]/g,(function(t){return"-"==t?"+":"/"})))},Z=function(t){return z(T(t))},j=function(t){return{value:t,enumerable:!1,writable:!0,configurable:!0}},I=function(){var t=function(t,n){return Object.defineProperty(String.prototype,t,j(n))};t("fromBase64",(function(){return Z(this)})),t("toBase64",(function(t){return m(this,t)})),t("toBase64URI",(function(){return m(this,!0)})),t("toBase64URL",(function(){return m(this,!0)})),t("toUint8Array",(function(){return R(this)}))},O=function(){var t=function(t,n){return Object.defineProperty(Uint8Array.prototype,t,j(n))};t("toBase64",(function(t){return b(this,t)})),t("toBase64URI",(function(){return b(this,!0)})),t("toBase64URL",(function(){return b(this,!0)}))},P={version:n,VERSION:"3.7.2",atob:E,atobPolyfill:S,btoa:y,btoaPolyfill:p,fromBase64:Z,toBase64:m,encode:m,encodeURI:v,encodeURL:v,utob:x,btou:w,decode:Z,isValid:function(t){if("string"!=typeof t)return!1;var n=t.replace(/\s+/g,"").replace(/={0,2}$/,"");return!/[^\s0-9a-zA-Z\+/]/.test(n)||!/[^\s0-9a-zA-Z\-_]/.test(n)},fromUint8Array:b,toUint8Array:R,extendString:I,extendUint8Array:O,extendBuiltins:function(){I(),O()},Base64:{}};return Object.keys(P).forEach((function(t){return P.Base64[t]=P[t]})),P}));

View File

@@ -0,0 +1,28 @@
# Contribution
# Git Flow
The crypto-js project uses [git flow](https://github.com/nvie/gitflow) to manage branches.
Do your changes on the `develop` or even better on a `feature/*` branch. Don't do any changes on the `master` branch.
# Pull request
Target your pull request on `develop` branch. Other pull request won't be accepted.
# How to build
1. Clone
2. Run
```sh
npm install
```
3. Run
```sh
npm run build
```
4. Check `build` folder

View File

@@ -0,0 +1,24 @@
# License
[The MIT License (MIT)](http://opensource.org/licenses/MIT)
Copyright (c) 2009-2013 Jeff Mott
Copyright (c) 2013-2016 Evan Vosberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,261 @@
# crypto-js [![Build Status](https://travis-ci.org/brix/crypto-js.svg?branch=develop)](https://travis-ci.org/brix/crypto-js)
JavaScript library of crypto standards.
## Node.js (Install)
Requirements:
- Node.js
- npm (Node.js package manager)
```bash
npm install crypto-js
```
### Usage
ES6 import for typical API call signing use case:
```javascript
import sha256 from 'crypto-js/sha256';
import hmacSHA512 from 'crypto-js/hmac-sha512';
import Base64 from 'crypto-js/enc-base64';
const message, nonce, path, privateKey; // ...
const hashDigest = sha256(nonce + message);
const hmacDigest = Base64.stringify(hmacSHA512(path + hashDigest, privateKey));
```
Modular include:
```javascript
var AES = require("crypto-js/aes");
var SHA256 = require("crypto-js/sha256");
...
console.log(SHA256("Message"));
```
Including all libraries, for access to extra methods:
```javascript
var CryptoJS = require("crypto-js");
console.log(CryptoJS.HmacSHA1("Message", "Key"));
```
## Client (browser)
Requirements:
- Node.js
- Bower (package manager for frontend)
```bash
bower install crypto-js
```
### Usage
Modular include:
```javascript
require.config({
packages: [
{
name: 'crypto-js',
location: 'path-to/bower_components/crypto-js',
main: 'index'
}
]
});
require(["crypto-js/aes", "crypto-js/sha256"], function (AES, SHA256) {
console.log(SHA256("Message"));
});
```
Including all libraries, for access to extra methods:
```javascript
// Above-mentioned will work or use this simple form
require.config({
paths: {
'crypto-js': 'path-to/bower_components/crypto-js/crypto-js'
}
});
require(["crypto-js"], function (CryptoJS) {
console.log(CryptoJS.HmacSHA1("Message", "Key"));
});
```
### Usage without RequireJS
```html
<script type="text/javascript" src="path-to/bower_components/crypto-js/crypto-js.js"></script>
<script type="text/javascript">
var encrypted = CryptoJS.AES(...);
var encrypted = CryptoJS.SHA256(...);
</script>
```
## API
See: https://cryptojs.gitbook.io/docs/
### AES Encryption
#### Plain text encryption
```javascript
var CryptoJS = require("crypto-js");
// Encrypt
var ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();
// Decrypt
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
var originalText = bytes.toString(CryptoJS.enc.Utf8);
console.log(originalText); // 'my message'
```
#### Object encryption
```javascript
var CryptoJS = require("crypto-js");
var data = [{id: 1}, {id: 2}]
// Encrypt
var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123').toString();
// Decrypt
var bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
console.log(decryptedData); // [{id: 1}, {id: 2}]
```
### List of modules
- ```crypto-js/core```
- ```crypto-js/x64-core```
- ```crypto-js/lib-typedarrays```
---
- ```crypto-js/md5```
- ```crypto-js/sha1```
- ```crypto-js/sha256```
- ```crypto-js/sha224```
- ```crypto-js/sha512```
- ```crypto-js/sha384```
- ```crypto-js/sha3```
- ```crypto-js/ripemd160```
---
- ```crypto-js/hmac-md5```
- ```crypto-js/hmac-sha1```
- ```crypto-js/hmac-sha256```
- ```crypto-js/hmac-sha224```
- ```crypto-js/hmac-sha512```
- ```crypto-js/hmac-sha384```
- ```crypto-js/hmac-sha3```
- ```crypto-js/hmac-ripemd160```
---
- ```crypto-js/pbkdf2```
---
- ```crypto-js/aes```
- ```crypto-js/tripledes```
- ```crypto-js/rc4```
- ```crypto-js/rabbit```
- ```crypto-js/rabbit-legacy```
- ```crypto-js/evpkdf```
---
- ```crypto-js/format-openssl```
- ```crypto-js/format-hex```
---
- ```crypto-js/enc-latin1```
- ```crypto-js/enc-utf8```
- ```crypto-js/enc-hex```
- ```crypto-js/enc-utf16```
- ```crypto-js/enc-base64```
---
- ```crypto-js/mode-cfb```
- ```crypto-js/mode-ctr```
- ```crypto-js/mode-ctr-gladman```
- ```crypto-js/mode-ofb```
- ```crypto-js/mode-ecb```
---
- ```crypto-js/pad-pkcs7```
- ```crypto-js/pad-ansix923```
- ```crypto-js/pad-iso10126```
- ```crypto-js/pad-iso97971```
- ```crypto-js/pad-zeropadding```
- ```crypto-js/pad-nopadding```
## Release notes
### 4.1.1
Fix module order in bundled release.
Include the browser field in the released package.json.
### 4.1.0
Added url safe variant of base64 encoding. [357](https://github.com/brix/crypto-js/pull/357)
Avoid webpack to add crypto-browser package. [364](https://github.com/brix/crypto-js/pull/364)
### 4.0.0
This is an update including breaking changes for some environments.
In this version `Math.random()` has been replaced by the random methods of the native crypto module.
For this reason CryptoJS might not run in some JavaScript environments without native crypto module. Such as IE 10 or before or React Native.
### 3.3.0
Rollback, `3.3.0` is the same as `3.1.9-1`.
The move of using native secure crypto module will be shifted to a new `4.x.x` version. As it is a breaking change the impact is too big for a minor release.
### 3.2.1
The usage of the native crypto module has been fixed. The import and access of the native crypto module has been improved.
### 3.2.0
In this version `Math.random()` has been replaced by the random methods of the native crypto module.
For this reason CryptoJS might does not run in some JavaScript environments without native crypto module. Such as IE 10 or before.
If it's absolute required to run CryptoJS in such an environment, stay with `3.1.x` version. Encrypting and decrypting stays compatible. But keep in mind `3.1.x` versions still use `Math.random()` which is cryptographically not secure, as it's not random enough.
This version came along with `CRITICAL` `BUG`.
DO NOT USE THIS VERSION! Please, go for a newer version!
### 3.1.x
The `3.1.x` are based on the original CryptoJS, wrapped in CommonJS modules.

View File

@@ -0,0 +1,234 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var BlockCipher = C_lib.BlockCipher;
var C_algo = C.algo;
// Lookup tables
var SBOX = [];
var INV_SBOX = [];
var SUB_MIX_0 = [];
var SUB_MIX_1 = [];
var SUB_MIX_2 = [];
var SUB_MIX_3 = [];
var INV_SUB_MIX_0 = [];
var INV_SUB_MIX_1 = [];
var INV_SUB_MIX_2 = [];
var INV_SUB_MIX_3 = [];
// Compute lookup tables
(function () {
// Compute double table
var d = [];
for (var i = 0; i < 256; i++) {
if (i < 128) {
d[i] = i << 1;
} else {
d[i] = (i << 1) ^ 0x11b;
}
}
// Walk GF(2^8)
var x = 0;
var xi = 0;
for (var i = 0; i < 256; i++) {
// Compute sbox
var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);
sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;
SBOX[x] = sx;
INV_SBOX[sx] = x;
// Compute multiplication
var x2 = d[x];
var x4 = d[x2];
var x8 = d[x4];
// Compute sub bytes, mix columns tables
var t = (d[sx] * 0x101) ^ (sx * 0x1010100);
SUB_MIX_0[x] = (t << 24) | (t >>> 8);
SUB_MIX_1[x] = (t << 16) | (t >>> 16);
SUB_MIX_2[x] = (t << 8) | (t >>> 24);
SUB_MIX_3[x] = t;
// Compute inv sub bytes, inv mix columns tables
var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);
INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);
INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);
INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24);
INV_SUB_MIX_3[sx] = t;
// Compute next counter
if (!x) {
x = xi = 1;
} else {
x = x2 ^ d[d[d[x8 ^ x2]]];
xi ^= d[d[xi]];
}
}
}());
// Precomputed Rcon lookup
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
/**
* AES block cipher algorithm.
*/
var AES = C_algo.AES = BlockCipher.extend({
_doReset: function () {
var t;
// Skip reset of nRounds has been set before and key did not change
if (this._nRounds && this._keyPriorReset === this._key) {
return;
}
// Shortcuts
var key = this._keyPriorReset = this._key;
var keyWords = key.words;
var keySize = key.sigBytes / 4;
// Compute number of rounds
var nRounds = this._nRounds = keySize + 6;
// Compute number of key schedule rows
var ksRows = (nRounds + 1) * 4;
// Compute key schedule
var keySchedule = this._keySchedule = [];
for (var ksRow = 0; ksRow < ksRows; ksRow++) {
if (ksRow < keySize) {
keySchedule[ksRow] = keyWords[ksRow];
} else {
t = keySchedule[ksRow - 1];
if (!(ksRow % keySize)) {
// Rot word
t = (t << 8) | (t >>> 24);
// Sub word
t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
// Mix Rcon
t ^= RCON[(ksRow / keySize) | 0] << 24;
} else if (keySize > 6 && ksRow % keySize == 4) {
// Sub word
t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];
}
keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;
}
}
// Compute inv key schedule
var invKeySchedule = this._invKeySchedule = [];
for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {
var ksRow = ksRows - invKsRow;
if (invKsRow % 4) {
var t = keySchedule[ksRow];
} else {
var t = keySchedule[ksRow - 4];
}
if (invKsRow < 4 || ksRow <= 4) {
invKeySchedule[invKsRow] = t;
} else {
invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^
INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];
}
}
},
encryptBlock: function (M, offset) {
this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);
},
decryptBlock: function (M, offset) {
// Swap 2nd and 4th rows
var t = M[offset + 1];
M[offset + 1] = M[offset + 3];
M[offset + 3] = t;
this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);
// Inv swap 2nd and 4th rows
var t = M[offset + 1];
M[offset + 1] = M[offset + 3];
M[offset + 3] = t;
},
_doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {
// Shortcut
var nRounds = this._nRounds;
// Get input, add round key
var s0 = M[offset] ^ keySchedule[0];
var s1 = M[offset + 1] ^ keySchedule[1];
var s2 = M[offset + 2] ^ keySchedule[2];
var s3 = M[offset + 3] ^ keySchedule[3];
// Key schedule row counter
var ksRow = 4;
// Rounds
for (var round = 1; round < nRounds; round++) {
// Shift rows, sub bytes, mix columns, add round key
var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++];
var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++];
var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++];
var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++];
// Update state
s0 = t0;
s1 = t1;
s2 = t2;
s3 = t3;
}
// Shift rows, sub bytes, add round key
var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];
var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];
var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];
var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];
// Set output
M[offset] = t0;
M[offset + 1] = t1;
M[offset + 2] = t2;
M[offset + 3] = t3;
},
keySize: 256/32
});
/**
* Shortcut functions to the cipher's object interface.
*
* @example
*
* var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);
* var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg);
*/
C.AES = BlockCipher._createHelper(AES);
}());
return CryptoJS.AES;
}));

View File

@@ -0,0 +1,39 @@
{
"name": "crypto-js",
"version": "4.1.1",
"description": "JavaScript library of crypto standards.",
"license": "MIT",
"homepage": "http://github.com/brix/crypto-js",
"repository": {
"type": "git",
"url": "http://github.com/brix/crypto-js.git"
},
"keywords": [
"security",
"crypto",
"Hash",
"MD5",
"SHA1",
"SHA-1",
"SHA256",
"SHA-256",
"RC4",
"Rabbit",
"AES",
"DES",
"PBKDF2",
"HMAC",
"OFB",
"CFB",
"CTR",
"CBC",
"Base64",
"Base64url"
],
"main": "index.js",
"dependencies": {},
"browser": {
"crypto": false
},
"ignore": []
}

View File

@@ -0,0 +1,890 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./evpkdf"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./evpkdf"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
/**
* Cipher core components.
*/
CryptoJS.lib.Cipher || (function (undefined) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var Base = C_lib.Base;
var WordArray = C_lib.WordArray;
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm;
var C_enc = C.enc;
var Utf8 = C_enc.Utf8;
var Base64 = C_enc.Base64;
var C_algo = C.algo;
var EvpKDF = C_algo.EvpKDF;
/**
* Abstract base cipher template.
*
* @property {number} keySize This cipher's key size. Default: 4 (128 bits)
* @property {number} ivSize This cipher's IV size. Default: 4 (128 bits)
* @property {number} _ENC_XFORM_MODE A constant representing encryption mode.
* @property {number} _DEC_XFORM_MODE A constant representing decryption mode.
*/
var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({
/**
* Configuration options.
*
* @property {WordArray} iv The IV to use for this operation.
*/
cfg: Base.extend(),
/**
* Creates this cipher in encryption mode.
*
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {Cipher} A cipher instance.
*
* @static
*
* @example
*
* var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray });
*/
createEncryptor: function (key, cfg) {
return this.create(this._ENC_XFORM_MODE, key, cfg);
},
/**
* Creates this cipher in decryption mode.
*
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {Cipher} A cipher instance.
*
* @static
*
* @example
*
* var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray });
*/
createDecryptor: function (key, cfg) {
return this.create(this._DEC_XFORM_MODE, key, cfg);
},
/**
* Initializes a newly created cipher.
*
* @param {number} xformMode Either the encryption or decryption transormation mode constant.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @example
*
* var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray });
*/
init: function (xformMode, key, cfg) {
// Apply config defaults
this.cfg = this.cfg.extend(cfg);
// Store transform mode and key
this._xformMode = xformMode;
this._key = key;
// Set initial values
this.reset();
},
/**
* Resets this cipher to its initial state.
*
* @example
*
* cipher.reset();
*/
reset: function () {
// Reset data buffer
BufferedBlockAlgorithm.reset.call(this);
// Perform concrete-cipher logic
this._doReset();
},
/**
* Adds data to be encrypted or decrypted.
*
* @param {WordArray|string} dataUpdate The data to encrypt or decrypt.
*
* @return {WordArray} The data after processing.
*
* @example
*
* var encrypted = cipher.process('data');
* var encrypted = cipher.process(wordArray);
*/
process: function (dataUpdate) {
// Append
this._append(dataUpdate);
// Process available blocks
return this._process();
},
/**
* Finalizes the encryption or decryption process.
* Note that the finalize operation is effectively a destructive, read-once operation.
*
* @param {WordArray|string} dataUpdate The final data to encrypt or decrypt.
*
* @return {WordArray} The data after final processing.
*
* @example
*
* var encrypted = cipher.finalize();
* var encrypted = cipher.finalize('data');
* var encrypted = cipher.finalize(wordArray);
*/
finalize: function (dataUpdate) {
// Final data update
if (dataUpdate) {
this._append(dataUpdate);
}
// Perform concrete-cipher logic
var finalProcessedData = this._doFinalize();
return finalProcessedData;
},
keySize: 128/32,
ivSize: 128/32,
_ENC_XFORM_MODE: 1,
_DEC_XFORM_MODE: 2,
/**
* Creates shortcut functions to a cipher's object interface.
*
* @param {Cipher} cipher The cipher to create a helper for.
*
* @return {Object} An object with encrypt and decrypt shortcut functions.
*
* @static
*
* @example
*
* var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES);
*/
_createHelper: (function () {
function selectCipherStrategy(key) {
if (typeof key == 'string') {
return PasswordBasedCipher;
} else {
return SerializableCipher;
}
}
return function (cipher) {
return {
encrypt: function (message, key, cfg) {
return selectCipherStrategy(key).encrypt(cipher, message, key, cfg);
},
decrypt: function (ciphertext, key, cfg) {
return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg);
}
};
};
}())
});
/**
* Abstract base stream cipher template.
*
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits)
*/
var StreamCipher = C_lib.StreamCipher = Cipher.extend({
_doFinalize: function () {
// Process partial blocks
var finalProcessedBlocks = this._process(!!'flush');
return finalProcessedBlocks;
},
blockSize: 1
});
/**
* Mode namespace.
*/
var C_mode = C.mode = {};
/**
* Abstract base block cipher mode template.
*/
var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({
/**
* Creates this mode for encryption.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @static
*
* @example
*
* var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words);
*/
createEncryptor: function (cipher, iv) {
return this.Encryptor.create(cipher, iv);
},
/**
* Creates this mode for decryption.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @static
*
* @example
*
* var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words);
*/
createDecryptor: function (cipher, iv) {
return this.Decryptor.create(cipher, iv);
},
/**
* Initializes a newly created mode.
*
* @param {Cipher} cipher A block cipher instance.
* @param {Array} iv The IV words.
*
* @example
*
* var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words);
*/
init: function (cipher, iv) {
this._cipher = cipher;
this._iv = iv;
}
});
/**
* Cipher Block Chaining mode.
*/
var CBC = C_mode.CBC = (function () {
/**
* Abstract base CBC mode.
*/
var CBC = BlockCipherMode.extend();
/**
* CBC encryptor.
*/
CBC.Encryptor = CBC.extend({
/**
* Processes the data block at offset.
*
* @param {Array} words The data words to operate on.
* @param {number} offset The offset where the block starts.
*
* @example
*
* mode.processBlock(data.words, offset);
*/
processBlock: function (words, offset) {
// Shortcuts
var cipher = this._cipher;
var blockSize = cipher.blockSize;
// XOR and encrypt
xorBlock.call(this, words, offset, blockSize);
cipher.encryptBlock(words, offset);
// Remember this block to use with next block
this._prevBlock = words.slice(offset, offset + blockSize);
}
});
/**
* CBC decryptor.
*/
CBC.Decryptor = CBC.extend({
/**
* Processes the data block at offset.
*
* @param {Array} words The data words to operate on.
* @param {number} offset The offset where the block starts.
*
* @example
*
* mode.processBlock(data.words, offset);
*/
processBlock: function (words, offset) {
// Shortcuts
var cipher = this._cipher;
var blockSize = cipher.blockSize;
// Remember this block to use with next block
var thisBlock = words.slice(offset, offset + blockSize);
// Decrypt and XOR
cipher.decryptBlock(words, offset);
xorBlock.call(this, words, offset, blockSize);
// This block becomes the previous block
this._prevBlock = thisBlock;
}
});
function xorBlock(words, offset, blockSize) {
var block;
// Shortcut
var iv = this._iv;
// Choose mixing block
if (iv) {
block = iv;
// Remove IV for subsequent blocks
this._iv = undefined;
} else {
block = this._prevBlock;
}
// XOR blocks
for (var i = 0; i < blockSize; i++) {
words[offset + i] ^= block[i];
}
}
return CBC;
}());
/**
* Padding namespace.
*/
var C_pad = C.pad = {};
/**
* PKCS #5/7 padding strategy.
*/
var Pkcs7 = C_pad.Pkcs7 = {
/**
* Pads data using the algorithm defined in PKCS #5/7.
*
* @param {WordArray} data The data to pad.
* @param {number} blockSize The multiple that the data should be padded to.
*
* @static
*
* @example
*
* CryptoJS.pad.Pkcs7.pad(wordArray, 4);
*/
pad: function (data, blockSize) {
// Shortcut
var blockSizeBytes = blockSize * 4;
// Count padding bytes
var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes;
// Create padding word
var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes;
// Create padding
var paddingWords = [];
for (var i = 0; i < nPaddingBytes; i += 4) {
paddingWords.push(paddingWord);
}
var padding = WordArray.create(paddingWords, nPaddingBytes);
// Add padding
data.concat(padding);
},
/**
* Unpads data that had been padded using the algorithm defined in PKCS #5/7.
*
* @param {WordArray} data The data to unpad.
*
* @static
*
* @example
*
* CryptoJS.pad.Pkcs7.unpad(wordArray);
*/
unpad: function (data) {
// Get number of padding bytes from last byte
var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;
// Remove padding
data.sigBytes -= nPaddingBytes;
}
};
/**
* Abstract base block cipher template.
*
* @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits)
*/
var BlockCipher = C_lib.BlockCipher = Cipher.extend({
/**
* Configuration options.
*
* @property {Mode} mode The block mode to use. Default: CBC
* @property {Padding} padding The padding strategy to use. Default: Pkcs7
*/
cfg: Cipher.cfg.extend({
mode: CBC,
padding: Pkcs7
}),
reset: function () {
var modeCreator;
// Reset cipher
Cipher.reset.call(this);
// Shortcuts
var cfg = this.cfg;
var iv = cfg.iv;
var mode = cfg.mode;
// Reset block mode
if (this._xformMode == this._ENC_XFORM_MODE) {
modeCreator = mode.createEncryptor;
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
modeCreator = mode.createDecryptor;
// Keep at least one block in the buffer for unpadding
this._minBufferSize = 1;
}
if (this._mode && this._mode.__creator == modeCreator) {
this._mode.init(this, iv && iv.words);
} else {
this._mode = modeCreator.call(mode, this, iv && iv.words);
this._mode.__creator = modeCreator;
}
},
_doProcessBlock: function (words, offset) {
this._mode.processBlock(words, offset);
},
_doFinalize: function () {
var finalProcessedBlocks;
// Shortcut
var padding = this.cfg.padding;
// Finalize
if (this._xformMode == this._ENC_XFORM_MODE) {
// Pad data
padding.pad(this._data, this.blockSize);
// Process final blocks
finalProcessedBlocks = this._process(!!'flush');
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
// Process final blocks
finalProcessedBlocks = this._process(!!'flush');
// Unpad data
padding.unpad(finalProcessedBlocks);
}
return finalProcessedBlocks;
},
blockSize: 128/32
});
/**
* A collection of cipher parameters.
*
* @property {WordArray} ciphertext The raw ciphertext.
* @property {WordArray} key The key to this ciphertext.
* @property {WordArray} iv The IV used in the ciphering operation.
* @property {WordArray} salt The salt used with a key derivation function.
* @property {Cipher} algorithm The cipher algorithm.
* @property {Mode} mode The block mode used in the ciphering operation.
* @property {Padding} padding The padding scheme used in the ciphering operation.
* @property {number} blockSize The block size of the cipher.
* @property {Format} formatter The default formatting strategy to convert this cipher params object to a string.
*/
var CipherParams = C_lib.CipherParams = Base.extend({
/**
* Initializes a newly created cipher params object.
*
* @param {Object} cipherParams An object with any of the possible cipher parameters.
*
* @example
*
* var cipherParams = CryptoJS.lib.CipherParams.create({
* ciphertext: ciphertextWordArray,
* key: keyWordArray,
* iv: ivWordArray,
* salt: saltWordArray,
* algorithm: CryptoJS.algo.AES,
* mode: CryptoJS.mode.CBC,
* padding: CryptoJS.pad.PKCS7,
* blockSize: 4,
* formatter: CryptoJS.format.OpenSSL
* });
*/
init: function (cipherParams) {
this.mixIn(cipherParams);
},
/**
* Converts this cipher params object to a string.
*
* @param {Format} formatter (Optional) The formatting strategy to use.
*
* @return {string} The stringified cipher params.
*
* @throws Error If neither the formatter nor the default formatter is set.
*
* @example
*
* var string = cipherParams + '';
* var string = cipherParams.toString();
* var string = cipherParams.toString(CryptoJS.format.OpenSSL);
*/
toString: function (formatter) {
return (formatter || this.formatter).stringify(this);
}
});
/**
* Format namespace.
*/
var C_format = C.format = {};
/**
* OpenSSL formatting strategy.
*/
var OpenSSLFormatter = C_format.OpenSSL = {
/**
* Converts a cipher params object to an OpenSSL-compatible string.
*
* @param {CipherParams} cipherParams The cipher params object.
*
* @return {string} The OpenSSL-compatible string.
*
* @static
*
* @example
*
* var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams);
*/
stringify: function (cipherParams) {
var wordArray;
// Shortcuts
var ciphertext = cipherParams.ciphertext;
var salt = cipherParams.salt;
// Format
if (salt) {
wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext);
} else {
wordArray = ciphertext;
}
return wordArray.toString(Base64);
},
/**
* Converts an OpenSSL-compatible string to a cipher params object.
*
* @param {string} openSSLStr The OpenSSL-compatible string.
*
* @return {CipherParams} The cipher params object.
*
* @static
*
* @example
*
* var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString);
*/
parse: function (openSSLStr) {
var salt;
// Parse base64
var ciphertext = Base64.parse(openSSLStr);
// Shortcut
var ciphertextWords = ciphertext.words;
// Test for salt
if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) {
// Extract salt
salt = WordArray.create(ciphertextWords.slice(2, 4));
// Remove salt from ciphertext
ciphertextWords.splice(0, 4);
ciphertext.sigBytes -= 16;
}
return CipherParams.create({ ciphertext: ciphertext, salt: salt });
}
};
/**
* A cipher wrapper that returns ciphertext as a serializable cipher params object.
*/
var SerializableCipher = C_lib.SerializableCipher = Base.extend({
/**
* Configuration options.
*
* @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL
*/
cfg: Base.extend({
format: OpenSSLFormatter
}),
/**
* Encrypts a message.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {WordArray|string} message The message to encrypt.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {CipherParams} A cipher params object.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key);
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv });
* var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL });
*/
encrypt: function (cipher, message, key, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Encrypt
var encryptor = cipher.createEncryptor(key, cfg);
var ciphertext = encryptor.finalize(message);
// Shortcut
var cipherCfg = encryptor.cfg;
// Create and return serializable cipher params
return CipherParams.create({
ciphertext: ciphertext,
key: key,
iv: cipherCfg.iv,
algorithm: cipher,
mode: cipherCfg.mode,
padding: cipherCfg.padding,
blockSize: cipher.blockSize,
formatter: cfg.format
});
},
/**
* Decrypts serialized ciphertext.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
* @param {WordArray} key The key.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {WordArray} The plaintext.
*
* @static
*
* @example
*
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL });
* var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL });
*/
decrypt: function (cipher, ciphertext, key, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Convert string to CipherParams
ciphertext = this._parse(ciphertext, cfg.format);
// Decrypt
var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext);
return plaintext;
},
/**
* Converts serialized ciphertext to CipherParams,
* else assumed CipherParams already and returns ciphertext unchanged.
*
* @param {CipherParams|string} ciphertext The ciphertext.
* @param {Formatter} format The formatting strategy to use to parse serialized ciphertext.
*
* @return {CipherParams} The unserialized ciphertext.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format);
*/
_parse: function (ciphertext, format) {
if (typeof ciphertext == 'string') {
return format.parse(ciphertext, this);
} else {
return ciphertext;
}
}
});
/**
* Key derivation function namespace.
*/
var C_kdf = C.kdf = {};
/**
* OpenSSL key derivation function.
*/
var OpenSSLKdf = C_kdf.OpenSSL = {
/**
* Derives a key and IV from a password.
*
* @param {string} password The password to derive from.
* @param {number} keySize The size in words of the key to generate.
* @param {number} ivSize The size in words of the IV to generate.
* @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
*
* @return {CipherParams} A cipher params object with the key, IV, and salt.
*
* @static
*
* @example
*
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32);
* var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt');
*/
execute: function (password, keySize, ivSize, salt) {
// Generate random salt
if (!salt) {
salt = WordArray.random(64/8);
}
// Derive key and IV
var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt);
// Separate key and IV
var iv = WordArray.create(key.words.slice(keySize), ivSize * 4);
key.sigBytes = keySize * 4;
// Return params
return CipherParams.create({ key: key, iv: iv, salt: salt });
}
};
/**
* A serializable cipher wrapper that derives the key from a password,
* and returns ciphertext as a serializable cipher params object.
*/
var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({
/**
* Configuration options.
*
* @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL
*/
cfg: SerializableCipher.cfg.extend({
kdf: OpenSSLKdf
}),
/**
* Encrypts a message using a password.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {WordArray|string} message The message to encrypt.
* @param {string} password The password.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {CipherParams} A cipher params object.
*
* @static
*
* @example
*
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password');
* var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL });
*/
encrypt: function (cipher, message, password, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Derive key and other params
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize);
// Add IV to config
cfg.iv = derivedParams.iv;
// Encrypt
var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg);
// Mix in derived params
ciphertext.mixIn(derivedParams);
return ciphertext;
},
/**
* Decrypts serialized ciphertext using a password.
*
* @param {Cipher} cipher The cipher algorithm to use.
* @param {CipherParams|string} ciphertext The ciphertext to decrypt.
* @param {string} password The password.
* @param {Object} cfg (Optional) The configuration options to use for this operation.
*
* @return {WordArray} The plaintext.
*
* @static
*
* @example
*
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL });
* var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL });
*/
decrypt: function (cipher, ciphertext, password, cfg) {
// Apply config defaults
cfg = this.cfg.extend(cfg);
// Convert string to CipherParams
ciphertext = this._parse(ciphertext, cfg.format);
// Derive key and other params
var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt);
// Add IV to config
cfg.iv = derivedParams.iv;
// Decrypt
var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg);
return plaintext;
}
});
}());
}));

View File

@@ -0,0 +1,807 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory();
}
else if (typeof define === "function" && define.amd) {
// AMD
define([], factory);
}
else {
// Global (browser)
root.CryptoJS = factory();
}
}(this, function () {
/*globals window, global, require*/
/**
* CryptoJS core components.
*/
var CryptoJS = CryptoJS || (function (Math, undefined) {
var crypto;
// Native crypto from window (Browser)
if (typeof window !== 'undefined' && window.crypto) {
crypto = window.crypto;
}
// Native crypto in web worker (Browser)
if (typeof self !== 'undefined' && self.crypto) {
crypto = self.crypto;
}
// Native crypto from worker
if (typeof globalThis !== 'undefined' && globalThis.crypto) {
crypto = globalThis.crypto;
}
// Native (experimental IE 11) crypto from window (Browser)
if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
crypto = window.msCrypto;
}
// Native crypto from global (NodeJS)
if (!crypto && typeof global !== 'undefined' && global.crypto) {
crypto = global.crypto;
}
// Native crypto import via require (NodeJS)
if (!crypto && typeof require === 'function') {
try {
crypto = require('crypto');
} catch (err) {}
}
/*
* Cryptographically secure pseudorandom number generator
*
* As Math.random() is cryptographically not safe to use
*/
var cryptoSecureRandomInt = function () {
if (crypto) {
// Use getRandomValues method (Browser)
if (typeof crypto.getRandomValues === 'function') {
try {
return crypto.getRandomValues(new Uint32Array(1))[0];
} catch (err) {}
}
// Use randomBytes method (NodeJS)
if (typeof crypto.randomBytes === 'function') {
try {
return crypto.randomBytes(4).readInt32LE();
} catch (err) {}
}
}
throw new Error('Native crypto module could not be used to get secure random number.');
};
/*
* Local polyfill of Object.create
*/
var create = Object.create || (function () {
function F() {}
return function (obj) {
var subtype;
F.prototype = obj;
subtype = new F();
F.prototype = null;
return subtype;
};
}());
/**
* CryptoJS namespace.
*/
var C = {};
/**
* Library namespace.
*/
var C_lib = C.lib = {};
/**
* Base object for prototypal inheritance.
*/
var Base = C_lib.Base = (function () {
return {
/**
* Creates a new object that inherits from this object.
*
* @param {Object} overrides Properties to copy into the new object.
*
* @return {Object} The new object.
*
* @static
*
* @example
*
* var MyType = CryptoJS.lib.Base.extend({
* field: 'value',
*
* method: function () {
* }
* });
*/
extend: function (overrides) {
// Spawn
var subtype = create(this);
// Augment
if (overrides) {
subtype.mixIn(overrides);
}
// Create default initializer
if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
subtype.init = function () {
subtype.$super.init.apply(this, arguments);
};
}
// Initializer's prototype is the subtype object
subtype.init.prototype = subtype;
// Reference supertype
subtype.$super = this;
return subtype;
},
/**
* Extends this object and runs the init method.
* Arguments to create() will be passed to init().
*
* @return {Object} The new object.
*
* @static
*
* @example
*
* var instance = MyType.create();
*/
create: function () {
var instance = this.extend();
instance.init.apply(instance, arguments);
return instance;
},
/**
* Initializes a newly created object.
* Override this method to add some logic when your objects are created.
*
* @example
*
* var MyType = CryptoJS.lib.Base.extend({
* init: function () {
* // ...
* }
* });
*/
init: function () {
},
/**
* Copies properties into this object.
*
* @param {Object} properties The properties to mix in.
*
* @example
*
* MyType.mixIn({
* field: 'value'
* });
*/
mixIn: function (properties) {
for (var propertyName in properties) {
if (properties.hasOwnProperty(propertyName)) {
this[propertyName] = properties[propertyName];
}
}
// IE won't copy toString using the loop above
if (properties.hasOwnProperty('toString')) {
this.toString = properties.toString;
}
},
/**
* Creates a copy of this object.
*
* @return {Object} The clone.
*
* @example
*
* var clone = instance.clone();
*/
clone: function () {
return this.init.prototype.extend(this);
}
};
}());
/**
* An array of 32-bit words.
*
* @property {Array} words The array of 32-bit words.
* @property {number} sigBytes The number of significant bytes in this word array.
*/
var WordArray = C_lib.WordArray = Base.extend({
/**
* Initializes a newly created word array.
*
* @param {Array} words (Optional) An array of 32-bit words.
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.create();
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
*/
init: function (words, sigBytes) {
words = this.words = words || [];
if (sigBytes != undefined) {
this.sigBytes = sigBytes;
} else {
this.sigBytes = words.length * 4;
}
},
/**
* Converts this word array to a string.
*
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
*
* @return {string} The stringified word array.
*
* @example
*
* var string = wordArray + '';
* var string = wordArray.toString();
* var string = wordArray.toString(CryptoJS.enc.Utf8);
*/
toString: function (encoder) {
return (encoder || Hex).stringify(this);
},
/**
* Concatenates a word array to this word array.
*
* @param {WordArray} wordArray The word array to append.
*
* @return {WordArray} This word array.
*
* @example
*
* wordArray1.concat(wordArray2);
*/
concat: function (wordArray) {
// Shortcuts
var thisWords = this.words;
var thatWords = wordArray.words;
var thisSigBytes = this.sigBytes;
var thatSigBytes = wordArray.sigBytes;
// Clamp excess bits
this.clamp();
// Concat
if (thisSigBytes % 4) {
// Copy one byte at a time
for (var i = 0; i < thatSigBytes; i++) {
var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
}
} else {
// Copy one word at a time
for (var j = 0; j < thatSigBytes; j += 4) {
thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];
}
}
this.sigBytes += thatSigBytes;
// Chainable
return this;
},
/**
* Removes insignificant bits.
*
* @example
*
* wordArray.clamp();
*/
clamp: function () {
// Shortcuts
var words = this.words;
var sigBytes = this.sigBytes;
// Clamp
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
words.length = Math.ceil(sigBytes / 4);
},
/**
* Creates a copy of this word array.
*
* @return {WordArray} The clone.
*
* @example
*
* var clone = wordArray.clone();
*/
clone: function () {
var clone = Base.clone.call(this);
clone.words = this.words.slice(0);
return clone;
},
/**
* Creates a word array filled with random bytes.
*
* @param {number} nBytes The number of random bytes to generate.
*
* @return {WordArray} The random word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.random(16);
*/
random: function (nBytes) {
var words = [];
for (var i = 0; i < nBytes; i += 4) {
words.push(cryptoSecureRandomInt());
}
return new WordArray.init(words, nBytes);
}
});
/**
* Encoder namespace.
*/
var C_enc = C.enc = {};
/**
* Hex encoding strategy.
*/
var Hex = C_enc.Hex = {
/**
* Converts a word array to a hex string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The hex string.
*
* @static
*
* @example
*
* var hexString = CryptoJS.enc.Hex.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var hexChars = [];
for (var i = 0; i < sigBytes; i++) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
hexChars.push((bite >>> 4).toString(16));
hexChars.push((bite & 0x0f).toString(16));
}
return hexChars.join('');
},
/**
* Converts a hex string to a word array.
*
* @param {string} hexStr The hex string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Hex.parse(hexString);
*/
parse: function (hexStr) {
// Shortcut
var hexStrLength = hexStr.length;
// Convert
var words = [];
for (var i = 0; i < hexStrLength; i += 2) {
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
}
return new WordArray.init(words, hexStrLength / 2);
}
};
/**
* Latin1 encoding strategy.
*/
var Latin1 = C_enc.Latin1 = {
/**
* Converts a word array to a Latin1 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Latin1 string.
*
* @static
*
* @example
*
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var latin1Chars = [];
for (var i = 0; i < sigBytes; i++) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
latin1Chars.push(String.fromCharCode(bite));
}
return latin1Chars.join('');
},
/**
* Converts a Latin1 string to a word array.
*
* @param {string} latin1Str The Latin1 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
*/
parse: function (latin1Str) {
// Shortcut
var latin1StrLength = latin1Str.length;
// Convert
var words = [];
for (var i = 0; i < latin1StrLength; i++) {
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
}
return new WordArray.init(words, latin1StrLength);
}
};
/**
* UTF-8 encoding strategy.
*/
var Utf8 = C_enc.Utf8 = {
/**
* Converts a word array to a UTF-8 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The UTF-8 string.
*
* @static
*
* @example
*
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
*/
stringify: function (wordArray) {
try {
return decodeURIComponent(escape(Latin1.stringify(wordArray)));
} catch (e) {
throw new Error('Malformed UTF-8 data');
}
},
/**
* Converts a UTF-8 string to a word array.
*
* @param {string} utf8Str The UTF-8 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
*/
parse: function (utf8Str) {
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
}
};
/**
* Abstract buffered block algorithm template.
*
* The property blockSize must be implemented in a concrete subtype.
*
* @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
*/
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
/**
* Resets this block algorithm's data buffer to its initial state.
*
* @example
*
* bufferedBlockAlgorithm.reset();
*/
reset: function () {
// Initial values
this._data = new WordArray.init();
this._nDataBytes = 0;
},
/**
* Adds new data to this block algorithm's buffer.
*
* @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
*
* @example
*
* bufferedBlockAlgorithm._append('data');
* bufferedBlockAlgorithm._append(wordArray);
*/
_append: function (data) {
// Convert string to WordArray, else assume WordArray already
if (typeof data == 'string') {
data = Utf8.parse(data);
}
// Append
this._data.concat(data);
this._nDataBytes += data.sigBytes;
},
/**
* Processes available data blocks.
*
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
*
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
*
* @return {WordArray} The processed data.
*
* @example
*
* var processedData = bufferedBlockAlgorithm._process();
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
*/
_process: function (doFlush) {
var processedWords;
// Shortcuts
var data = this._data;
var dataWords = data.words;
var dataSigBytes = data.sigBytes;
var blockSize = this.blockSize;
var blockSizeBytes = blockSize * 4;
// Count blocks ready
var nBlocksReady = dataSigBytes / blockSizeBytes;
if (doFlush) {
// Round up to include partial blocks
nBlocksReady = Math.ceil(nBlocksReady);
} else {
// Round down to include only full blocks,
// less the number of blocks that must remain in the buffer
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
}
// Count words ready
var nWordsReady = nBlocksReady * blockSize;
// Count bytes ready
var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
// Process blocks
if (nWordsReady) {
for (var offset = 0; offset < nWordsReady; offset += blockSize) {
// Perform concrete-algorithm logic
this._doProcessBlock(dataWords, offset);
}
// Remove processed words
processedWords = dataWords.splice(0, nWordsReady);
data.sigBytes -= nBytesReady;
}
// Return processed words
return new WordArray.init(processedWords, nBytesReady);
},
/**
* Creates a copy of this object.
*
* @return {Object} The clone.
*
* @example
*
* var clone = bufferedBlockAlgorithm.clone();
*/
clone: function () {
var clone = Base.clone.call(this);
clone._data = this._data.clone();
return clone;
},
_minBufferSize: 0
});
/**
* Abstract hasher template.
*
* @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
*/
var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
/**
* Configuration options.
*/
cfg: Base.extend(),
/**
* Initializes a newly created hasher.
*
* @param {Object} cfg (Optional) The configuration options to use for this hash computation.
*
* @example
*
* var hasher = CryptoJS.algo.SHA256.create();
*/
init: function (cfg) {
// Apply config defaults
this.cfg = this.cfg.extend(cfg);
// Set initial values
this.reset();
},
/**
* Resets this hasher to its initial state.
*
* @example
*
* hasher.reset();
*/
reset: function () {
// Reset data buffer
BufferedBlockAlgorithm.reset.call(this);
// Perform concrete-hasher logic
this._doReset();
},
/**
* Updates this hasher with a message.
*
* @param {WordArray|string} messageUpdate The message to append.
*
* @return {Hasher} This hasher.
*
* @example
*
* hasher.update('message');
* hasher.update(wordArray);
*/
update: function (messageUpdate) {
// Append
this._append(messageUpdate);
// Update the hash
this._process();
// Chainable
return this;
},
/**
* Finalizes the hash computation.
* Note that the finalize operation is effectively a destructive, read-once operation.
*
* @param {WordArray|string} messageUpdate (Optional) A final message update.
*
* @return {WordArray} The hash.
*
* @example
*
* var hash = hasher.finalize();
* var hash = hasher.finalize('message');
* var hash = hasher.finalize(wordArray);
*/
finalize: function (messageUpdate) {
// Final message update
if (messageUpdate) {
this._append(messageUpdate);
}
// Perform concrete-hasher logic
var hash = this._doFinalize();
return hash;
},
blockSize: 512/32,
/**
* Creates a shortcut function to a hasher's object interface.
*
* @param {Hasher} hasher The hasher to create a helper for.
*
* @return {Function} The shortcut function.
*
* @static
*
* @example
*
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
*/
_createHelper: function (hasher) {
return function (message, cfg) {
return new hasher.init(cfg).finalize(message);
};
},
/**
* Creates a shortcut function to the HMAC's object interface.
*
* @param {Hasher} hasher The hasher to use in this HMAC helper.
*
* @return {Function} The shortcut function.
*
* @static
*
* @example
*
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
*/
_createHmacHelper: function (hasher) {
return function (message, key) {
return new C_algo.HMAC.init(hasher, key).finalize(message);
};
}
});
/**
* Algorithm namespace.
*/
var C_algo = C.algo = {};
return C;
}(Math));
return CryptoJS;
}));

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,470 @@
<wiki:toc/>
----
= Quick-start Guide =
== Hashers ==
=== The Hasher Algorithms ===
==== MD5 ====
MD5 is a widely used hash function. It's been used in a variety of security applications and is also commonly used to check the integrity of files. Though, MD5 is not collision resistant, and it isn't suitable for applications like SSL certificates or digital signatures that rely on this property.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/md5.js"></script>
<script>
var hash = CryptoJS.MD5("Message");
</script>
}}}
==== SHA-1 ====
The SHA hash functions were designed by the National Security Agency (NSA). SHA-1 is the most established of the existing SHA hash functions, and it's used in a variety of security applications and protocols. Though, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha1.js"></script>
<script>
var hash = CryptoJS.SHA1("Message");
</script>
}}}
==== SHA-2 ====
SHA-256 is one of the four variants in the SHA-2 set. It isn't as widely used as SHA-1, though it appears to provide much better security.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script>
<script>
var hash = CryptoJS.SHA256("Message");
</script>
}}}
SHA-512 is largely identical to SHA-256 but operates on 64-bit words rather than 32.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha512.js"></script>
<script>
var hash = CryptoJS.SHA512("Message");
</script>
}}}
CryptoJS also supports SHA-224 and SHA-384, which are largely identical but truncated versions of SHA-256 and SHA-512 respectively.
==== SHA-3 ====
SHA-3 is the winner of a five-year competition to select a new cryptographic hash algorithm where 64 competing designs were evaluated.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha3.js"></script>
<script>
var hash = CryptoJS.SHA3("Message");
</script>
}}}
SHA-3 can be configured to output hash lengths of one of 224, 256, 384, or 512 bits. The default is 512 bits.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha3.js"></script>
<script>
var hash = CryptoJS.SHA3("Message", { outputLength: 512 });
var hash = CryptoJS.SHA3("Message", { outputLength: 384 });
var hash = CryptoJS.SHA3("Message", { outputLength: 256 });
var hash = CryptoJS.SHA3("Message", { outputLength: 224 });
</script>
}}}
==== RIPEMD-160 ====
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/ripemd160.js"></script>
<script>
var hash = CryptoJS.RIPEMD160("Message");
</script>
}}}
=== The Hasher Input ===
The hash algorithms accept either strings or instances of CryptoJS.lib.WordArray. A WordArray object represents an array of 32-bit words. When you pass a string, it's automatically converted to a WordArray encoded as UTF-8.
=== The Hasher Output ===
The hash you get back isn't a string yet. It's a WordArray object. When you use a WordArray object in a string context, it's automatically converted to a hex string.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script>
<script>
var hash = CryptoJS.SHA256("Message");
alert(typeof hash); // object
alert(hash); // 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91
</script>
}}}
You can convert a WordArray object to other formats by explicitly calling the toString method and passing an encoder.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-base64-min.js"></script>
<script>
var hash = CryptoJS.SHA256("Message");
alert(hash.toString(CryptoJS.enc.Base64)); // L3dmip37+NWEi57rSnFFypTG7ZI25Kdz9tyvpRMrL5E=
alert(hash.toString(CryptoJS.enc.Latin1)); // /wf<77><66>ûøÕ<C3B8><C395><EFBFBD>ëJqEÊ<45>Æí<C386>6ä§söܯ¥+/<2F>
alert(hash.toString(CryptoJS.enc.Hex)); // 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91
</script>
}}}
=== Progressive Hashing ===
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/sha256.js"></script>
<script>
var sha256 = CryptoJS.algo.SHA256.create();
sha256.update("Message Part 1");
sha256.update("Message Part 2");
sha256.update("Message Part 3");
var hash = sha256.finalize();
</script>
}}}
== HMAC ==
Keyed-hash message authentication codes (HMAC) is a mechanism for message authentication using cryptographic hash functions.
HMAC can be used in combination with any iterated cryptographic hash function.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-md5.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha1.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha256.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha512.js"></script>
<script>
var hash = CryptoJS.HmacMD5("Message", "Secret Passphrase");
var hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase");
var hash = CryptoJS.HmacSHA256("Message", "Secret Passphrase");
var hash = CryptoJS.HmacSHA512("Message", "Secret Passphrase");
</script>
}}}
=== Progressive HMAC Hashing ===
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/hmac-sha256.js"></script>
<script>
var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, "Secret Passphrase");
hmac.update("Message Part 1");
hmac.update("Message Part 2");
hmac.update("Message Part 3");
var hash = hmac.finalize();
</script>
}}}
== PBKDF2 ==
PBKDF2 is a password-based key derivation function. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.
A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/pbkdf2.js"></script>
<script>
var salt = CryptoJS.lib.WordArray.random(128/8);
var key128Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 128/32 });
var key256Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 256/32 });
var key512Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 512/32 });
var key512Bits1000Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, { keySize: 512/32, iterations: 1000 });
</script>
}}}
== Ciphers ==
=== The Cipher Algorithms ===
==== AES ====
The Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script>
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
</script>
}}}
CryptoJS supports AES-128, AES-192, and AES-256. It will pick the variant by the size of the key you pass in. If you use a passphrase, then it will generate a 256-bit key.
==== DES, Triple DES ====
DES is a previously dominant algorithm for encryption, and was published as an official Federal Information Processing Standard (FIPS). DES is now considered to be insecure due to the small key size.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/tripledes.js"></script>
<script>
var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase");
var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase");
</script>
}}}
Triple DES applies DES three times to each block to increase the key size. The algorithm is believed to be secure in this form.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/tripledes.js"></script>
<script>
var encrypted = CryptoJS.TripleDES.encrypt("Message", "Secret Passphrase");
var decrypted = CryptoJS.TripleDES.decrypt(encrypted, "Secret Passphrase");
</script>
}}}
==== Rabbit ====
Rabbit is a high-performance stream cipher and a finalist in the eSTREAM Portfolio. It is one of the four designs selected after a 3 1/2-year process where 22 designs were evaluated.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rabbit.js"></script>
<script>
var encrypted = CryptoJS.Rabbit.encrypt("Message", "Secret Passphrase");
var decrypted = CryptoJS.Rabbit.decrypt(encrypted, "Secret Passphrase");
</script>
}}}
==== RC4, RC4Drop ====
RC4 is a widely-used stream cipher. It's used in popular protocols such as SSL and WEP. Although remarkable for its simplicity and speed, the algorithm's history doesn't inspire confidence in its security.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rc4.js"></script>
<script>
var encrypted = CryptoJS.RC4.encrypt("Message", "Secret Passphrase");
var decrypted = CryptoJS.RC4.decrypt(encrypted, "Secret Passphrase");
</script>
}}}
It was discovered that the first few bytes of keystream are strongly non-random and leak information about the key. We can defend against this attack by discarding the initial portion of the keystream. This modified algorithm is traditionally called RC4-drop.
By default, 192 words (768 bytes) are dropped, but you can configure the algorithm to drop any number of words.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/rc4.js"></script>
<script>
var encrypted = CryptoJS.RC4Drop.encrypt("Message", "Secret Passphrase");
var encrypted = CryptoJS.RC4Drop.encrypt("Message", "Secret Passphrase", { drop: 3072/4 });
var decrypted = CryptoJS.RC4Drop.decrypt(encrypted, "Secret Passphrase", { drop: 3072/4 });
</script>
}}}
=== Custom Key and IV ===
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script>
var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');
var iv = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv });
</script>
}}}
=== Block Modes and Padding ===
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/mode-cfb-min.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/pad-ansix923-min.js"></script>
<script>
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase", { mode: CryptoJS.mode.CFB, padding: CryptoJS.pad.AnsiX923 });
</script>
}}}
CryptoJS supports the following modes:
* CBC (the default)
* CFB
* CTR
* OFB
* ECB
And CryptoJS supports the following padding schemes:
* Pkcs7 (the default)
* Iso97971
* AnsiX923
* Iso10126
* ZeroPadding
* NoPadding
=== The Cipher Input ===
For the plaintext message, the cipher algorithms accept either strings or instances of CryptoJS.lib.WordArray.
For the key, when you pass a string, it's treated as a passphrase and used to derive an actual key and IV. Or you can pass a WordArray that represents the actual key. If you pass the actual key, you must also pass the actual IV.
For the ciphertext, the cipher algorithms accept either strings or instances of CryptoJS.lib.CipherParams. A CipherParams object represents a collection of parameters such as the IV, a salt, and the raw ciphertext itself. When you pass a string, it's automatically converted to a CipherParams object according to a configurable format strategy.
=== The Cipher Output ===
The plaintext you get back after decryption is a WordArray object. See Hashers' Output for more detail.
The ciphertext you get back after encryption isn't a string yet. It's a CipherParams object. A CipherParams object gives you access to all the parameters used during encryption. When you use a CipherParams object in a string context, it's automatically converted to a string according to a format strategy. The default is an OpenSSL-compatible format.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script>
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
alert(encrypted.key); // 74eb593087a982e2a6f5dded54ecd96d1fd0f3d44a58728cdcd40c55227522223
alert(encrypted.iv); // 7781157e2629b094f0e3dd48c4d786115
alert(encrypted.salt); // 7a25f9132ec6a8b34
alert(encrypted.ciphertext); // 73e54154a15d1beeb509d9e12f1e462a0
alert(encrypted); // U2FsdGVkX1+iX5Ey7GqLND5UFUoV0b7rUJ2eEvHkYqA=
</script>
}}}
You can define your own formats in order to be compatible with other crypto implementations. A format is an object with two methods—stringify and parse—that converts between CipherParams objects and ciphertext strings.
Here's how you might write a JSON formatter:
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script>
var JsonFormatter = {
stringify: function (cipherParams) {
// create json object with ciphertext
var jsonObj = {
ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64)
};
// optionally add iv and salt
if (cipherParams.iv) {
jsonObj.iv = cipherParams.iv.toString();
}
if (cipherParams.salt) {
jsonObj.s = cipherParams.salt.toString();
}
// stringify json object
return JSON.stringify(jsonObj);
},
parse: function (jsonStr) {
// parse json string
var jsonObj = JSON.parse(jsonStr);
// extract ciphertext from json object, and create cipher params object
var cipherParams = CryptoJS.lib.CipherParams.create({
ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct)
});
// optionally extract iv and salt
if (jsonObj.iv) {
cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv)
}
if (jsonObj.s) {
cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s)
}
return cipherParams;
}
};
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase", { format: JsonFormatter });
alert(encrypted); // {"ct":"tZ4MsEnfbcDOwqau68aOrQ==","iv":"8a8c8fd8fe33743d3638737ea4a00698","s":"ba06373c8f57179c"}
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase", { format: JsonFormatter });
alert(decrypted.toString(CryptoJS.enc.Utf8)); // Message
</script>
}}}
=== Progressive Ciphering ===
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script>
var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');
var iv = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv });
var ciphertextPart1 = aesEncryptor.process("Message Part 1");
var ciphertextPart2 = aesEncryptor.process("Message Part 2");
var ciphertextPart3 = aesEncryptor.process("Message Part 3");
var ciphertextPart4 = aesEncryptor.finalize();
var aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv });
var plaintextPart1 = aesDecryptor.process(ciphertextPart1);
var plaintextPart2 = aesDecryptor.process(ciphertextPart2);
var plaintextPart3 = aesDecryptor.process(ciphertextPart3);
var plaintextPart4 = aesDecryptor.process(ciphertextPart4);
var plaintextPart5 = aesDecryptor.finalize();
</script>
}}}
=== Interoperability ===
==== With OpenSSL ====
Encrypt with OpenSSL:
{{{
openssl enc -aes-256-cbc -in infile -out outfile -pass pass:"Secret Passphrase" -e -base64
}}}
Decrypt with CryptoJS:
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/rollups/aes.js"></script>
<script>
var decrypted = CryptoJS.AES.decrypt(openSSLEncrypted, "Secret Passphrase");
</script>
}}}
== Encoders ==
CryptoJS can convert from encoding formats such as Base64, Latin1 or Hex to WordArray objects and vica versa.
{{{
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/core-min.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-utf16-min.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1/build/components/enc-base64-min.js"></script>
<script>
var words = CryptoJS.enc.Base64.parse('SGVsbG8sIFdvcmxkIQ==');
var base64 = CryptoJS.enc.Base64.stringify(words);
var words = CryptoJS.enc.Latin1.parse('Hello, World!');
var latin1 = CryptoJS.enc.Latin1.stringify(words);
var words = CryptoJS.enc.Hex.parse('48656c6c6f2c20576f726c6421');
var hex = CryptoJS.enc.Hex.stringify(words);
var words = CryptoJS.enc.Utf8.parse('𤭢');
var utf8 = CryptoJS.enc.Utf8.stringify(words);
var words = CryptoJS.enc.Utf16.parse('Hello, World!');
var utf16 = CryptoJS.enc.Utf16.stringify(words);
var words = CryptoJS.enc.Utf16LE.parse('Hello, World!');
var utf16 = CryptoJS.enc.Utf16LE.stringify(words);
</script>
}}}

View File

@@ -0,0 +1,136 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var C_enc = C.enc;
/**
* Base64 encoding strategy.
*/
var Base64 = C_enc.Base64 = {
/**
* Converts a word array to a Base64 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Base64 string.
*
* @static
*
* @example
*
* var base64String = CryptoJS.enc.Base64.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var map = this._map;
// Clamp excess bits
wordArray.clamp();
// Convert
var base64Chars = [];
for (var i = 0; i < sigBytes; i += 3) {
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
}
}
// Add padding
var paddingChar = map.charAt(64);
if (paddingChar) {
while (base64Chars.length % 4) {
base64Chars.push(paddingChar);
}
}
return base64Chars.join('');
},
/**
* Converts a Base64 string to a word array.
*
* @param {string} base64Str The Base64 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Base64.parse(base64String);
*/
parse: function (base64Str) {
// Shortcuts
var base64StrLength = base64Str.length;
var map = this._map;
var reverseMap = this._reverseMap;
if (!reverseMap) {
reverseMap = this._reverseMap = [];
for (var j = 0; j < map.length; j++) {
reverseMap[map.charCodeAt(j)] = j;
}
}
// Ignore padding
var paddingChar = map.charAt(64);
if (paddingChar) {
var paddingIndex = base64Str.indexOf(paddingChar);
if (paddingIndex !== -1) {
base64StrLength = paddingIndex;
}
}
// Convert
return parseLoop(base64Str, base64StrLength, reverseMap);
},
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
};
function parseLoop(base64Str, base64StrLength, reverseMap) {
var words = [];
var nBytes = 0;
for (var i = 0; i < base64StrLength; i++) {
if (i % 4) {
var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
var bitsCombined = bits1 | bits2;
words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
nBytes++;
}
}
return WordArray.create(words, nBytes);
}
}());
return CryptoJS.enc.Base64;
}));

View File

@@ -0,0 +1,140 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var C_enc = C.enc;
/**
* Base64url encoding strategy.
*/
var Base64url = C_enc.Base64url = {
/**
* Converts a word array to a Base64url string.
*
* @param {WordArray} wordArray The word array.
*
* @param {boolean} urlSafe Whether to use url safe
*
* @return {string} The Base64url string.
*
* @static
*
* @example
*
* var base64String = CryptoJS.enc.Base64url.stringify(wordArray);
*/
stringify: function (wordArray, urlSafe=true) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var map = urlSafe ? this._safe_map : this._map;
// Clamp excess bits
wordArray.clamp();
// Convert
var base64Chars = [];
for (var i = 0; i < sigBytes; i += 3) {
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
}
}
// Add padding
var paddingChar = map.charAt(64);
if (paddingChar) {
while (base64Chars.length % 4) {
base64Chars.push(paddingChar);
}
}
return base64Chars.join('');
},
/**
* Converts a Base64url string to a word array.
*
* @param {string} base64Str The Base64url string.
*
* @param {boolean} urlSafe Whether to use url safe
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Base64url.parse(base64String);
*/
parse: function (base64Str, urlSafe=true) {
// Shortcuts
var base64StrLength = base64Str.length;
var map = urlSafe ? this._safe_map : this._map;
var reverseMap = this._reverseMap;
if (!reverseMap) {
reverseMap = this._reverseMap = [];
for (var j = 0; j < map.length; j++) {
reverseMap[map.charCodeAt(j)] = j;
}
}
// Ignore padding
var paddingChar = map.charAt(64);
if (paddingChar) {
var paddingIndex = base64Str.indexOf(paddingChar);
if (paddingIndex !== -1) {
base64StrLength = paddingIndex;
}
}
// Convert
return parseLoop(base64Str, base64StrLength, reverseMap);
},
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
_safe_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
};
function parseLoop(base64Str, base64StrLength, reverseMap) {
var words = [];
var nBytes = 0;
for (var i = 0; i < base64StrLength; i++) {
if (i % 4) {
var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
var bitsCombined = bits1 | bits2;
words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
nBytes++;
}
}
return WordArray.create(words, nBytes);
}
}());
return CryptoJS.enc.Base64url;
}));

View File

@@ -0,0 +1,18 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.enc.Hex;
}));

View File

@@ -0,0 +1,18 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.enc.Latin1;
}));

View File

@@ -0,0 +1,149 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var C_enc = C.enc;
/**
* UTF-16 BE encoding strategy.
*/
var Utf16BE = C_enc.Utf16 = C_enc.Utf16BE = {
/**
* Converts a word array to a UTF-16 BE string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The UTF-16 BE string.
*
* @static
*
* @example
*
* var utf16String = CryptoJS.enc.Utf16.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var utf16Chars = [];
for (var i = 0; i < sigBytes; i += 2) {
var codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff;
utf16Chars.push(String.fromCharCode(codePoint));
}
return utf16Chars.join('');
},
/**
* Converts a UTF-16 BE string to a word array.
*
* @param {string} utf16Str The UTF-16 BE string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Utf16.parse(utf16String);
*/
parse: function (utf16Str) {
// Shortcut
var utf16StrLength = utf16Str.length;
// Convert
var words = [];
for (var i = 0; i < utf16StrLength; i++) {
words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16);
}
return WordArray.create(words, utf16StrLength * 2);
}
};
/**
* UTF-16 LE encoding strategy.
*/
C_enc.Utf16LE = {
/**
* Converts a word array to a UTF-16 LE string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The UTF-16 LE string.
*
* @static
*
* @example
*
* var utf16Str = CryptoJS.enc.Utf16LE.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var utf16Chars = [];
for (var i = 0; i < sigBytes; i += 2) {
var codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff);
utf16Chars.push(String.fromCharCode(codePoint));
}
return utf16Chars.join('');
},
/**
* Converts a UTF-16 LE string to a word array.
*
* @param {string} utf16Str The UTF-16 LE string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Utf16LE.parse(utf16Str);
*/
parse: function (utf16Str) {
// Shortcut
var utf16StrLength = utf16Str.length;
// Convert
var words = [];
for (var i = 0; i < utf16StrLength; i++) {
words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16));
}
return WordArray.create(words, utf16StrLength * 2);
}
};
function swapEndian(word) {
return ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff);
}
}());
return CryptoJS.enc.Utf16;
}));

View File

@@ -0,0 +1,18 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.enc.Utf8;
}));

View File

@@ -0,0 +1,134 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./sha1", "./hmac"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var Base = C_lib.Base;
var WordArray = C_lib.WordArray;
var C_algo = C.algo;
var MD5 = C_algo.MD5;
/**
* This key derivation function is meant to conform with EVP_BytesToKey.
* www.openssl.org/docs/crypto/EVP_BytesToKey.html
*/
var EvpKDF = C_algo.EvpKDF = Base.extend({
/**
* Configuration options.
*
* @property {number} keySize The key size in words to generate. Default: 4 (128 bits)
* @property {Hasher} hasher The hash algorithm to use. Default: MD5
* @property {number} iterations The number of iterations to perform. Default: 1
*/
cfg: Base.extend({
keySize: 128/32,
hasher: MD5,
iterations: 1
}),
/**
* Initializes a newly created key derivation function.
*
* @param {Object} cfg (Optional) The configuration options to use for the derivation.
*
* @example
*
* var kdf = CryptoJS.algo.EvpKDF.create();
* var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 });
* var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 });
*/
init: function (cfg) {
this.cfg = this.cfg.extend(cfg);
},
/**
* Derives a key from a password.
*
* @param {WordArray|string} password The password.
* @param {WordArray|string} salt A salt.
*
* @return {WordArray} The derived key.
*
* @example
*
* var key = kdf.compute(password, salt);
*/
compute: function (password, salt) {
var block;
// Shortcut
var cfg = this.cfg;
// Init hasher
var hasher = cfg.hasher.create();
// Initial values
var derivedKey = WordArray.create();
// Shortcuts
var derivedKeyWords = derivedKey.words;
var keySize = cfg.keySize;
var iterations = cfg.iterations;
// Generate key
while (derivedKeyWords.length < keySize) {
if (block) {
hasher.update(block);
}
block = hasher.update(password).finalize(salt);
hasher.reset();
// Iterations
for (var i = 1; i < iterations; i++) {
block = hasher.finalize(block);
hasher.reset();
}
derivedKey.concat(block);
}
derivedKey.sigBytes = keySize * 4;
return derivedKey;
}
});
/**
* Derives a key from a password.
*
* @param {WordArray|string} password The password.
* @param {WordArray|string} salt A salt.
* @param {Object} cfg (Optional) The configuration options to use for this computation.
*
* @return {WordArray} The derived key.
*
* @static
*
* @example
*
* var key = CryptoJS.EvpKDF(password, salt);
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 });
* var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 });
*/
C.EvpKDF = function (password, salt, cfg) {
return EvpKDF.create(cfg).compute(password, salt);
};
}());
return CryptoJS.EvpKDF;
}));

View File

@@ -0,0 +1,66 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./cipher-core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./cipher-core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function (undefined) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var CipherParams = C_lib.CipherParams;
var C_enc = C.enc;
var Hex = C_enc.Hex;
var C_format = C.format;
var HexFormatter = C_format.Hex = {
/**
* Converts the ciphertext of a cipher params object to a hexadecimally encoded string.
*
* @param {CipherParams} cipherParams The cipher params object.
*
* @return {string} The hexadecimally encoded string.
*
* @static
*
* @example
*
* var hexString = CryptoJS.format.Hex.stringify(cipherParams);
*/
stringify: function (cipherParams) {
return cipherParams.ciphertext.toString(Hex);
},
/**
* Converts a hexadecimally encoded ciphertext string to a cipher params object.
*
* @param {string} input The hexadecimally encoded string.
*
* @return {CipherParams} The cipher params object.
*
* @static
*
* @example
*
* var cipherParams = CryptoJS.format.Hex.parse(hexString);
*/
parse: function (input) {
var ciphertext = Hex.parse(input);
return CipherParams.create({ ciphertext: ciphertext });
}
};
}());
return CryptoJS.format.Hex;
}));

View File

@@ -0,0 +1,18 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./cipher-core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./cipher-core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.format.OpenSSL;
}));

View File

@@ -0,0 +1,18 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./md5"), require("./hmac"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./md5", "./hmac"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.HmacMD5;
}));

View File

@@ -0,0 +1,18 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./ripemd160"), require("./hmac"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./ripemd160", "./hmac"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.HmacRIPEMD160;
}));

View File

@@ -0,0 +1,18 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./sha1", "./hmac"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.HmacSHA1;
}));

View File

@@ -0,0 +1,18 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./sha256"), require("./sha224"), require("./hmac"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./sha256", "./sha224", "./hmac"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.HmacSHA224;
}));

Some files were not shown because too many files have changed in this diff Show More