├── pages
├── home
│ ├── home.json
│ ├── home.wxml
│ ├── home.wxss
│ └── home.js
├── remove
│ ├── remove.json
│ ├── remove.wxml
│ ├── remove.wxss
│ └── remove.js
├── me
│ ├── me.json
│ ├── me.wxml
│ ├── me.js
│ └── me.wxss
├── about
│ ├── about.json
│ ├── about.wxml
│ ├── about.wxss
│ └── about.js
└── logs
│ ├── logs.json
│ ├── logs.wxss
│ ├── logs.wxml
│ └── logs.js
├── code.jpg
├── images
├── arrow.png
├── clear.png
├── avatar.png
├── douyin.png
├── huoshan.png
├── kuaishou.png
├── me-init.png
├── meipai.png
├── pipixia.png
├── weishi.png
├── home-init.png
├── me-active.png
├── me-banner.png
└── home-active.png
├── sitemap.json
├── README.md
├── app.wxss
├── .gitignore
├── utils
├── util.js
└── md5.js
├── project.config.json
├── app.json
└── app.js
/pages/home/home.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/remove/remove.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/pages/me/me.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "个人中心"
3 | }
--------------------------------------------------------------------------------
/pages/about/about.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "关于我们"
3 | }
--------------------------------------------------------------------------------
/pages/logs/logs.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "查看启动日志"
3 | }
--------------------------------------------------------------------------------
/code.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/code.jpg
--------------------------------------------------------------------------------
/images/arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/arrow.png
--------------------------------------------------------------------------------
/images/clear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/clear.png
--------------------------------------------------------------------------------
/images/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/avatar.png
--------------------------------------------------------------------------------
/images/douyin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/douyin.png
--------------------------------------------------------------------------------
/images/huoshan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/huoshan.png
--------------------------------------------------------------------------------
/images/kuaishou.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/kuaishou.png
--------------------------------------------------------------------------------
/images/me-init.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/me-init.png
--------------------------------------------------------------------------------
/images/meipai.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/meipai.png
--------------------------------------------------------------------------------
/images/pipixia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/pipixia.png
--------------------------------------------------------------------------------
/images/weishi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/weishi.png
--------------------------------------------------------------------------------
/images/home-init.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/home-init.png
--------------------------------------------------------------------------------
/images/me-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/me-active.png
--------------------------------------------------------------------------------
/images/me-banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/me-banner.png
--------------------------------------------------------------------------------
/images/home-active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yidierh/remove-code/HEAD/images/home-active.png
--------------------------------------------------------------------------------
/pages/logs/logs.wxss:
--------------------------------------------------------------------------------
1 | .log-list {
2 | display: flex;
3 | flex-direction: column;
4 | padding: 40rpx;
5 | }
6 | .log-item {
7 | margin: 10rpx;
8 | }
9 |
--------------------------------------------------------------------------------
/pages/about/about.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 免费提供抖音视频、快手视频、皮皮虾视频、微视视频、火山视频、美拍视频去水印服务。
4 |
--------------------------------------------------------------------------------
/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/pages/logs/logs.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{index + 1}}. {{log}}
5 |
6 |
7 |
--------------------------------------------------------------------------------
/pages/about/about.wxss:
--------------------------------------------------------------------------------
1 | /* pages/about/about.wxss */
2 | Page {
3 | background: #f4f4f4;
4 | }
5 |
6 | .container {
7 | padding: 50rpx 32rpx;
8 | }
9 |
10 | .container .about {
11 | font-size: 32rpx;
12 | color: #333;
13 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # remove-code
2 |
3 | #### 项目介绍
4 |
5 | 去水印小程序
6 |
7 | > 抖音的有点不稳定,有需要的自行更换接口;appid 自行配置
8 |
9 | #### 邮箱
10 |
11 | yidierh@gmail.com
12 |
13 | 
14 |
--------------------------------------------------------------------------------
/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | .container {
3 | height: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | align-items: center;
7 | justify-content: space-between;
8 | padding: 200rpx 0;
9 | box-sizing: border-box;
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | /test/unit/coverage/
8 | /test/e2e/reports/
9 | selenium-debug.log
10 |
11 | # Editor directories and files
12 | .idea
13 | .vscode
14 | *.suo
15 | *.ntvs*
16 | *.njsproj
17 | *.sln
18 |
--------------------------------------------------------------------------------
/pages/logs/logs.js:
--------------------------------------------------------------------------------
1 | //logs.js
2 | const util = require('../../utils/util.js')
3 |
4 | Page({
5 | data: {
6 | logs: []
7 | },
8 | onLoad: function () {
9 | this.setData({
10 | logs: (wx.getStorageSync('logs') || []).map(log => {
11 | return util.formatTime(new Date(log))
12 | })
13 | })
14 | }
15 | })
16 |
--------------------------------------------------------------------------------
/utils/util.js:
--------------------------------------------------------------------------------
1 | const formatTime = date => {
2 | const year = date.getFullYear()
3 | const month = date.getMonth() + 1
4 | const day = date.getDate()
5 | const hour = date.getHours()
6 | const minute = date.getMinutes()
7 | const second = date.getSeconds()
8 |
9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
10 | }
11 |
12 | const formatNumber = n => {
13 | n = n.toString()
14 | return n[1] ? n : '0' + n
15 | }
16 |
17 | module.exports = {
18 | formatTime: formatTime
19 | }
20 |
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "packOptions": {
4 | "ignore": []
5 | },
6 | "setting": {
7 | "urlCheck": true,
8 | "es6": true,
9 | "postcss": true,
10 | "minified": true,
11 | "newFeature": true
12 | },
13 | "compileType": "miniprogram",
14 | "libVersion": "2.2.4",
15 | "appid": "",
16 | "projectname": "remove-code",
17 | "debugOptions": {
18 | "hidedInDevtools": []
19 | },
20 | "isGameTourist": false,
21 | "simulatorType": "wechat",
22 | "simulatorPluginLibVersion": {},
23 | "condition": {
24 | "search": {
25 | "current": -1,
26 | "list": []
27 | },
28 | "conversation": {
29 | "current": -1,
30 | "list": []
31 | },
32 | "game": {
33 | "currentL": -1,
34 | "list": []
35 | },
36 | "miniprogram": {
37 | "current": -1,
38 | "list": []
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/pages/home/home.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{item.text}}
7 |
8 |
9 |
10 |
11 |
12 | {{item.text}}
13 |
14 |
15 |
--------------------------------------------------------------------------------
/pages/about/about.js:
--------------------------------------------------------------------------------
1 | // pages/about/about.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 |
9 | },
10 |
11 | /**
12 | * 生命周期函数--监听页面加载
13 | */
14 | onLoad: function (options) {
15 |
16 | },
17 |
18 | /**
19 | * 生命周期函数--监听页面初次渲染完成
20 | */
21 | onReady: function () {
22 |
23 | },
24 |
25 | /**
26 | * 生命周期函数--监听页面显示
27 | */
28 | onShow: function () {
29 |
30 | },
31 |
32 | /**
33 | * 生命周期函数--监听页面隐藏
34 | */
35 | onHide: function () {
36 |
37 | },
38 |
39 | /**
40 | * 生命周期函数--监听页面卸载
41 | */
42 | onUnload: function () {
43 |
44 | },
45 |
46 | /**
47 | * 页面相关事件处理函数--监听用户下拉动作
48 | */
49 | onPullDownRefresh: function () {
50 |
51 | },
52 |
53 | /**
54 | * 页面上拉触底事件的处理函数
55 | */
56 | onReachBottom: function () {
57 |
58 | },
59 |
60 | /**
61 | * 用户点击右上角分享
62 | */
63 | onShareAppMessage: function () {
64 |
65 | }
66 | })
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/home/home",
4 | "pages/me/me",
5 | "pages/remove/remove",
6 | "pages/logs/logs",
7 | "pages/about/about"
8 | ],
9 | "window": {
10 | "backgroundTextStyle": "light",
11 | "navigationBarBackgroundColor": "#fff",
12 | "navigationBarTitleText": "短视频去水印大师免费版",
13 | "navigationBarTextStyle": "black"
14 | },
15 | "tabBar": {
16 | "color": "#333",
17 | "selectedColor": "#ff5a44",
18 | "borderStyle": "black",
19 | "list": [
20 | {
21 | "selectedIconPath": "images/home-active.png",
22 | "iconPath": "images/home-init.png",
23 | "pagePath": "pages/home/home",
24 | "text": "视频"
25 | },
26 | {
27 | "selectedIconPath": "images/me-active.png",
28 | "iconPath": "images/me-init.png",
29 | "pagePath": "pages/me/me",
30 | "text": "我的"
31 | }
32 | ]
33 | },
34 | "sitemapLocation": "sitemap.json"
35 | }
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function () {
4 | // 展示本地存储能力
5 | var logs = wx.getStorageSync('logs') || []
6 | logs.unshift(Date.now())
7 | wx.setStorageSync('logs', logs)
8 |
9 | // 登录
10 | wx.login({
11 | success: res => {
12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId
13 | }
14 | })
15 | // 获取用户信息
16 | wx.getSetting({
17 | success: res => {
18 | if (res.authSetting['scope.userInfo']) {
19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
20 | wx.getUserInfo({
21 | success: res => {
22 | // 可以将 res 发送给后台解码出 unionId
23 | this.globalData.userInfo = res.userInfo
24 |
25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
26 | // 所以此处加入 callback 以防止这种情况
27 | if (this.userInfoReadyCallback) {
28 | this.userInfoReadyCallback(res)
29 | }
30 | }
31 | })
32 | }
33 | }
34 | })
35 | },
36 | globalData: {
37 | userInfo: null
38 | }
39 | })
--------------------------------------------------------------------------------
/pages/me/me.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 | 关于我们
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/pages/home/home.wxss:
--------------------------------------------------------------------------------
1 | /* pages/home/home.wxss */
2 |
3 | Page {
4 | background: #f4f4f4;
5 | }
6 |
7 | .container {
8 | padding: 0 24rpx;
9 | }
10 |
11 | .container .home-items {
12 | display: inline-flex;
13 | margin-top: 32rpx;
14 | width: 100%;
15 | height: 146rpx;
16 | background: #fff;
17 | border-radius: 28rpx;
18 | box-shadow: 0 0 10rpx 0
19 | rgba(0, 0, 0, 0.1);
20 | justify-content: center;
21 | align-items: center;
22 | }
23 |
24 | .container .home-items__disable {
25 | opacity: .5;
26 | }
27 |
28 | .container .container-top {
29 | display: inline-flex;
30 | width: 100%;
31 | justify-content: space-around;
32 | }
33 |
34 | .container .container-top .home-items-first {
35 | display: flex;
36 | margin-top: 32rpx;
37 | flex-direction: column;
38 | align-items: center;
39 | justify-content: center;
40 | width: 329rpx;
41 | height: 290rpx;
42 | background: #fff;
43 | border-radius: 28rpx;
44 | box-shadow: 0 0 10rpx 0
45 | rgba(0, 0, 0, 0.1);
46 | box-sizing: border-box;
47 | }
48 |
49 | .container .container-top .home-items-first .items-img-first {
50 | width: 160rpx;
51 | height: 160rpx;
52 | }
53 |
54 | .container .container-top .home-items-first .items-text-first {
55 | margin-top: 16rpx;
56 | font-size: 30rpx;
57 | }
58 |
59 | .container .home-items .items-img {
60 | margin-right: 32rpx;
61 | width: 86rpx;
62 | height: 86rpx;
63 | }
64 |
65 | .container .home-items .items-text {
66 | font-size: 30rpx;
67 | }
68 |
--------------------------------------------------------------------------------
/pages/remove/remove.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 请务必确认视频在APP中无水印,不然无法去掉水印
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | 使用说明
26 | 1.复制您想要去除水印的短视频链接
27 | 2.把复制的链接粘贴在输入框中(可以包含文字)
28 | 3.点击获取视频即可获得无水印链接
29 |
30 |
--------------------------------------------------------------------------------
/pages/home/home.js:
--------------------------------------------------------------------------------
1 | // pages/home/home.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | homeData: [
9 | {
10 | icon: '../../images/douyin.png',
11 | text: '抖音去水印',
12 | type: 'douyin'
13 | },
14 | {
15 | icon: '../../images/weishi.png',
16 | text: '微视去水印',
17 | type: 'weishi'
18 | },
19 | {
20 | icon: '../../images/huoshan.png',
21 | text: '火山去水印',
22 | type: 'huoshan'
23 | },
24 | {
25 | icon: '../../images/kuaishou.png',
26 | text: '快手去水印',
27 | type: 'kuaishou'
28 | },
29 | {
30 | icon: '../../images/meipai.png',
31 | text: '美拍去水印',
32 | type: 'meipai'
33 | },
34 | {
35 | icon: '../../images/pipixia.png',
36 | text: '皮皮虾去水印',
37 | type: 'pipixia'
38 | }
39 | ]
40 | },
41 |
42 | /**
43 | * 生命周期函数--监听页面加载
44 | */
45 | onLoad: function (options) {
46 |
47 | },
48 |
49 | /**
50 | * 生命周期函数--监听页面初次渲染完成
51 | */
52 | onReady: function () {
53 |
54 | },
55 |
56 | /**
57 | * 生命周期函数--监听页面显示
58 | */
59 | onShow: function () {
60 |
61 | },
62 |
63 | /**
64 | * 生命周期函数--监听页面隐藏
65 | */
66 | onHide: function () {
67 |
68 | },
69 |
70 | /**
71 | * 生命周期函数--监听页面卸载
72 | */
73 | onUnload: function () {
74 |
75 | },
76 |
77 | /**
78 | * 页面相关事件处理函数--监听用户下拉动作
79 | */
80 | onPullDownRefresh: function () {
81 |
82 | },
83 |
84 | /**
85 | * 页面上拉触底事件的处理函数
86 | */
87 | onReachBottom: function () {
88 |
89 | },
90 |
91 | /**
92 | * 用户点击右上角分享
93 | */
94 | onShareAppMessage: function () {
95 |
96 | }
97 | })
--------------------------------------------------------------------------------
/pages/me/me.js:
--------------------------------------------------------------------------------
1 | // pages/me/me.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | userInfo: ''
9 | },
10 | getUserInfo: function(e) {
11 | let _this = this
12 | if (e.detail.errMsg === "getUserInfo:ok") {
13 | _this.setData({
14 | 'userInfo': e.detail.userInfo
15 | })
16 | } else {
17 | _this.showNeed()
18 | }
19 | },
20 |
21 | /**
22 | * 请求授权
23 | */
24 | showNeed: function() {
25 | wx.showToast({
26 | title: '点击头像进行登录',
27 | icon: 'none'
28 | })
29 | },
30 |
31 | /**
32 | * 生命周期函数--监听页面加载
33 | */
34 | onLoad: function(options) {
35 | let _this = this
36 | //查看是否授权
37 | wx.getSetting({
38 | success: function(res) {
39 | if (res.authSetting['scope.userInfo']) {
40 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称
41 | wx.getUserInfo({
42 | success: function(res) {
43 | _this.setData({
44 | 'userInfo': res.userInfo
45 | })
46 | }
47 | })
48 | } else {
49 | _this.showNeed()
50 | }
51 | },
52 | fail(res) {
53 | _this.showNeed()
54 | }
55 | })
56 | },
57 |
58 | /**
59 | * 生命周期函数--监听页面初次渲染完成
60 | */
61 | onReady: function() {
62 |
63 | },
64 |
65 | /**
66 | * 生命周期函数--监听页面显示
67 | */
68 | onShow: function() {
69 |
70 | },
71 |
72 | /**
73 | * 生命周期函数--监听页面隐藏
74 | */
75 | onHide: function() {
76 |
77 | },
78 |
79 | /**
80 | * 生命周期函数--监听页面卸载
81 | */
82 | onUnload: function() {
83 |
84 | },
85 |
86 | /**
87 | * 页面相关事件处理函数--监听用户下拉动作
88 | */
89 | onPullDownRefresh: function() {
90 |
91 | },
92 |
93 | /**
94 | * 页面上拉触底事件的处理函数
95 | */
96 | onReachBottom: function() {
97 |
98 | },
99 |
100 | /**
101 | * 用户点击右上角分享
102 | */
103 | onShareAppMessage: function() {
104 |
105 | }
106 | })
--------------------------------------------------------------------------------
/pages/me/me.wxss:
--------------------------------------------------------------------------------
1 | /* pages/me/me.wxss */
2 | Page {
3 | background: #f4f4f4;
4 | }
5 |
6 | .me-header {
7 | position: relative;
8 | width: 100%;
9 | height: 413rpx;
10 | }
11 |
12 | .me-userInfo {
13 | position: absolute;
14 | display: flex;
15 | top: 172rpx;
16 | left: 0;
17 | flex-direction: column;
18 | align-items: center;
19 | width: 100%;
20 | }
21 |
22 | .me-header-avatar {
23 | width: 164rpx;
24 | height: 164rpx;
25 | border-radius: 50%;
26 | border: 5rpx solid rgba(255, 255, 255, 0.8);
27 | background: #fff;
28 | }
29 |
30 | .me-header-avatar-btn {
31 | padding: 0;
32 | width: 164rpx;
33 | height: 164rpx;
34 | border-radius: 50%;
35 | border: 5rpx solid rgba(255, 255, 255, 0.8);
36 | }
37 |
38 | .me-header-avatar-btn::after {
39 | border: none;
40 | }
41 |
42 | .me-header-avatar-btn .btn-image {
43 | width: 164rpx;
44 | height: 164rpx;
45 | }
46 |
47 | .me-header-text {
48 | margin-top: 10rpx;
49 | font-size: 30rpx;
50 | text-align: center;
51 | }
52 |
53 | .me-header-text-btn {
54 | margin-top: 20rpx;
55 | font-size: 30rpx;
56 | line-height: 30rpx;
57 | background: #fff;
58 | }
59 |
60 | .me-header-text-btn::after {
61 | border: none;
62 | }
63 |
64 | .me-header-banner {
65 | width: 100%;
66 | height: 100%;
67 | }
68 |
69 | .me-navigator {
70 | position: relative;
71 | display: inline-flex;
72 | padding: 0 24rpx;
73 | margin-top: 20rpx;
74 | width: 100%;
75 | height: 93rpx;
76 | align-items: center;
77 | background: #fff;
78 | box-sizing: border-box;
79 | }
80 |
81 | .me-navigator .me-navigator-text {
82 | margin-left: 16rpx;
83 | font-size: 30rpx;
84 | color: #333;
85 | }
86 |
87 | .me-navigator .me-navigatior-arrow {
88 | position: absolute;
89 | right: 24rpx;
90 | width: 14rpx;
91 | height: 26rpx;
92 | z-index: 10;
93 | }
94 |
95 | .me-get-wrapper {
96 | margin-top: 16rpx;
97 | padding: 24rpx;
98 | }
99 |
100 | .me-get-wrapper .me-get {
101 | margin: auto;
102 | font-size: 30rpx;
103 | height: 82rpx;
104 | line-height: 82rpx;
105 | background: #ff5a44;
106 | color: #fff;
107 | border-radius: 15rpx;
108 | }
109 |
110 | .btn-contact-view{
111 | width: 100%;
112 | position: fixed;
113 | bottom: 60rpx;
114 | }
115 |
116 | .btn-contact{
117 | line-height: 80rpx;
118 | width: 300rpx;
119 | height: 80rpx;
120 | background: #ff5a44;
121 | color: #fff;
122 | font-size: 30rpx;
123 | border-radius: 70rpx;
124 | }
125 |
--------------------------------------------------------------------------------
/pages/remove/remove.wxss:
--------------------------------------------------------------------------------
1 | /* pages/remove/remove.wxss */
2 |
3 | .container {
4 | padding: 40rpx 75rpx;
5 | box-sizing: border-box;
6 | }
7 |
8 | .container .remove-img {
9 | width: 120rpx;
10 | height: 120rpx;
11 | }
12 |
13 | .container .remove-content {
14 | margin-top: 72rpx;
15 | width: 100%;
16 | }
17 |
18 | .container .remove-content .remove-tips {
19 | display: block;
20 | width: 100%;
21 | font-size: 24rpx;
22 | color: #ff5a44;
23 | text-align: center;
24 | }
25 |
26 | .container .remove-content .remove-input-wrapper {
27 | position: relative;
28 | }
29 |
30 | .container .remove-content .remove-input-wrapper .remove-input {
31 | margin-top: 16rpx;
32 | padding: 0 72rpx 0 24rpx;
33 | width: 100%;
34 | height: 74rpx;
35 | font-size: 30rpx;
36 | border: 2rpx solid #d4d4d4;
37 | border-radius: 15rpx;
38 | box-sizing: border-box;
39 | }
40 |
41 | .container .remove-content .remove-input-wrapper .remove-clear {
42 | position: absolute;
43 | top: 22rpx;
44 | right: 24rpx;
45 | width: 34rpx;
46 | height: 34rpx;
47 | }
48 |
49 | .container .remove-btn-danger {
50 | margin-top: 32rpx;
51 | font-size: 30rpx;
52 | height: 82rpx;
53 | line-height: 82rpx;
54 | background: #ff5a44;
55 | color: #fff;
56 | border-radius: 15rpx;
57 | }
58 |
59 | .container .remove-getContent {
60 | margin-top: 72rpx;
61 | width: 100%;
62 | text-align: center;
63 | }
64 |
65 | .container .remove-getContent .url-wrapper {
66 | font-size: 24rpx;
67 | color: #ff5a44;
68 | overflow: hidden;
69 | text-overflow: ellipsis;
70 | white-space: nowrap;
71 | }
72 |
73 | .container .remove-getContent .remove-vedio {
74 | width: 600rpx;
75 | height: 450rpx;
76 | }
77 |
78 | .container .remove-getContent .remove-btn-wrapper {
79 | margin-top: 32rpx;
80 | display: inline-flex;
81 | justify-content: center;
82 | }
83 |
84 | .container .remove-getContent .remove-btn-wrapper .remove-btn-primary {
85 | margin-left: 48rpx;
86 | background: #fff;
87 | height: 82rpx;
88 | line-height: 82rpx;
89 | color: #ff5a44;
90 | border: 2rpx solid #ff5a44;
91 | }
92 |
93 | .container .remove-getContent .remove-btn-wrapper .bottom {
94 | margin-top: 0;
95 | width: 276rpx;
96 | }
97 |
98 | .container .copy-tips {
99 | display: flex;
100 | flex-direction: column;
101 | margin-top: 148rpx;
102 | }
103 |
104 | .container .copy-tips .tips-title {
105 | font-size: 28rpx;
106 | text-align: center;
107 | color: #333;
108 | }
109 |
110 | .container .copy-tips .tips-text {
111 | margin-top: 32rpx;
112 | font-size: 26rpx;
113 | color: #333;
114 | }
115 |
116 | /* 进度条 */
117 | progress {
118 | margin-top: 20rpx;
119 | }
--------------------------------------------------------------------------------
/pages/remove/remove.js:
--------------------------------------------------------------------------------
1 | // pages/remove/remove.js
2 | const MD5 = require('../../utils/md5.js')
3 |
4 | Page({
5 |
6 | /**
7 | * 页面的初始数据
8 | */
9 | data: {
10 | type: '',
11 | placeholder: '',
12 | removeUrl: '',
13 | icon: '',
14 | vedioUrl: '',
15 | showCancel: false,
16 | percent: '',
17 | showProgress: false,
18 | downStart: false
19 | },
20 |
21 | /**
22 | * 数据绑定
23 | */
24 | removeUrl: function (e) {
25 | let _this = this
26 | let _removeUrl = e.detail.value
27 | if (_removeUrl) {
28 | _removeUrl = _this.formatUrl(_removeUrl)
29 | this.setData({
30 | 'removeUrl': _removeUrl,
31 | 'showCancel': true
32 | })
33 | } else {
34 | this.setData({
35 | 'showCancel': false
36 | })
37 | }
38 | },
39 |
40 | /**
41 | * 生命周期函数--监听页面加载
42 | */
43 | onLoad: function (options) {
44 | let _type = options.type
45 | let _typeName = ''
46 | let _icon = ''
47 | if (_type === 'douyin') {
48 | _typeName = '抖音'
49 | _icon = '../../images/douyin.png'
50 | } else if (_type === 'weishi') {
51 | _typeName = '微视'
52 | _icon = '../../images/weishi.png'
53 | } else if (_type === 'huoshan') {
54 | _typeName = '火山'
55 | _icon = '../../images/huoshan.png'
56 | } else if (_type === 'kuaishou') {
57 | _typeName = '快手'
58 | _icon = '../../images/kuaishou.png'
59 | } else if (_type === 'meipai') {
60 | _typeName = '美拍'
61 | _icon = '../../images/meipai.png'
62 | } else if (_type === 'pipixia') {
63 | _typeName = '皮皮虾'
64 | _icon = '../../images/pipixia.png'
65 | }
66 | this.setData({
67 | type: options.type,
68 | placeholder: `请输入${_typeName}视频链接`,
69 | icon: _icon
70 | })
71 | },
72 |
73 | /**
74 | * 生命周期函数--监听页面初次渲染完成
75 | */
76 | onReady: function () {
77 | this.confirmClip()
78 | },
79 |
80 | /**
81 | * 生命周期函数--监听页面显示
82 | */
83 | onShow: function () {
84 |
85 | },
86 |
87 | /**
88 | * 生命周期函数--监听页面隐藏
89 | */
90 | onHide: function () {
91 |
92 | },
93 |
94 | /**
95 | * 生命周期函数--监听页面卸载
96 | */
97 | onUnload: function () {
98 |
99 | },
100 |
101 | /**
102 | * 页面相关事件处理函数--监听用户下拉动作
103 | */
104 | onPullDownRefresh: function () {
105 |
106 | },
107 |
108 | /**
109 | * 页面上拉触底事件的处理函数
110 | */
111 | onReachBottom: function () {
112 |
113 | },
114 |
115 | /**
116 | * 用户点击右上角分享
117 | */
118 | onShareAppMessage: function () {
119 |
120 | },
121 |
122 | /**
123 | * 获取视频
124 | */
125 | getVedio: function (e) {
126 | if (e.detail.errMsg === "getUserInfo:ok") {
127 | let _this = this
128 | let _url = _this.data.removeUrl
129 | let _type = _this.data.type
130 | let oppen_id = ''
131 | if (_url) {
132 | if (_url.indexOf('rmapi.h5youx.com')>0) {
133 | wx.showToast({
134 | title: '请输入正确的链接地址',
135 | icon: 'none'
136 | })
137 | return false
138 | } else {
139 | let reg = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/
140 | if (reg.test(_url)) {
141 | wx.showLoading({
142 | title: '正在获取...',
143 | mask: true
144 | })
145 | } else {
146 | wx.showToast({
147 | title: '请输入正确的链接地址',
148 | icon: 'none'
149 | })
150 | return false
151 | }
152 | }
153 | } else {
154 | wx.showToast({
155 | title: '请输入视频链接地址',
156 | icon: 'none'
157 | })
158 | return false
159 | }
160 | wx.request({
161 | url: 'https://rmapi.h5youx.com/vlink/s.php',
162 | method: 'GET',
163 | dataType: 'JSON',
164 | data: {
165 | link: _url,
166 | type: _type,
167 | sign: MD5.hex_md5(_url + _type + 'xiaochengxv')
168 | },
169 | success(res) {
170 | let _res = JSON.parse(res.data)
171 | if (_res.succ) {
172 | _this.setData({
173 | vedioUrl: _res.data.video
174 | })
175 | wx.hideLoading()
176 | } else {
177 | wx.hideLoading()
178 | wx.showToast({
179 | title: _res.retDesc,
180 | icon: 'none'
181 | })
182 | }
183 | },
184 | fail(res) {
185 | wx.showToast({
186 | title: '服务器繁忙',
187 | icon: 'none'
188 | })
189 | }
190 | })
191 | }
192 | },
193 |
194 | /**
195 | * 保存视频
196 | */
197 | saveVedio: function () {
198 | let _this = this
199 | wx.getSetting({
200 | success: (res) => {
201 | if (!res.authSetting['scope.writePhotosAlbum']) {
202 | wx.authorize({
203 | scope: 'scope.writePhotosAlbum',
204 | success() {
205 | _this.saveToAlbum()
206 | }
207 | })
208 | } else {
209 | _this.saveToAlbum()
210 | }
211 | }
212 | })
213 | },
214 |
215 | /**
216 | * 保存视频到相册
217 | */
218 | saveToAlbum: function () {
219 | let _vedioUrl = this.data.vedioUrl
220 | let _this = this
221 | wx.showLoading({
222 | title: '正在保存...',
223 | mask: true
224 | })
225 | const downloadTask = wx.downloadFile({
226 | url: _vedioUrl,
227 | success(res) {
228 | //保存视频到本地
229 | _this.setData({
230 | 'percent': '100'
231 | })
232 | wx.saveVideoToPhotosAlbum({
233 | filePath: res.tempFilePath,
234 | success(res) {
235 | wx.showToast({
236 | title: '保存成功',
237 | })
238 | _this.initStat()
239 | },
240 | fail(err) {
241 | _this.initStat()
242 | if (err.errMsg === "saveVideoToPhotosAlbum:fail auth deny") {
243 | wx.openSetting({
244 | success(res) {
245 | if (res.authSetting['scope.writePhotosAlbum']) {
246 | wx.showToast({
247 | title: '请再次保存视频',
248 | icon: 'none'
249 | })
250 | } else {
251 | wx.showToast({
252 | title: '请先允许授权',
253 | icon: 'none'
254 | })
255 | }
256 | }
257 | })
258 | }
259 | }
260 | })
261 | },
262 | fail(res) {
263 | wx.showToast({
264 | title: '请复制视频链接去外部浏览器下载',
265 | icon: 'none'
266 | })
267 | }
268 | })
269 |
270 | downloadTask.onProgressUpdate((res) => {
271 | _this.setData({
272 | 'percent': '95',
273 | downStart: true,
274 | showProgress: true
275 | })
276 | })
277 | },
278 |
279 | /**
280 | * 复制前判断剪切板有没有内容
281 | */
282 | confirmClip: function () {
283 | let _this = this
284 | wx.getClipboardData({
285 | success(res) {
286 | let _clipData = res.data
287 | if (_clipData.indexOf('http') >= 0) {
288 | wx.showModal({
289 | title: '提示',
290 | content: '检测到您的剪贴板有链接是否需要粘贴?',
291 | success(res) {
292 | if (res.confirm) {
293 | _clipData = _this.formatUrl(_clipData)
294 | _this.setData({
295 | 'removeUrl': _clipData,
296 | 'showCancel': true
297 | })
298 | }
299 | }
300 | })
301 | }
302 | }
303 | })
304 | },
305 |
306 | /**
307 | * 复制
308 | */
309 | copyUrl: function () {
310 | let _type = this.data.type
311 | let _vedioUrl = this.data.vedioUrl
312 | wx.setClipboardData({
313 | data: _vedioUrl,
314 | success(res) {
315 | wx.showToast({
316 | title: '复制成功',
317 | })
318 | },
319 | fail(res) {
320 | wx.showToast({
321 | title: '复制失败',
322 | icon: 'none'
323 | })
324 | }
325 | })
326 | },
327 |
328 | /**
329 | * 清除视频连接
330 | */
331 | clearUrl: function () {
332 | this.setData({
333 | 'removeUrl': '',
334 | 'showCancel': false
335 | })
336 | },
337 |
338 | /**
339 | * 获取文案中的链接
340 | */
341 | formatUrl: function (url) {
342 | if(url.indexOf('http') >= 0) {
343 | let reg = /(http:\/\/|https:\/\/)((\w|=|\?|\.|\/|&|-)+)/g
344 | let _data = reg.exec(url)
345 | if(_data) {
346 | url = encodeURI(_data[0])
347 | }
348 | }
349 | return url
350 | },
351 |
352 | /**
353 | * 保存完成状态复原
354 | */
355 | initStat: function () {
356 | wx.hideLoading()
357 | this.setData({
358 | showProgress: false
359 | })
360 | }
361 | })
--------------------------------------------------------------------------------
/utils/md5.js:
--------------------------------------------------------------------------------
1 | /*
2 | * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
3 | * Digest Algorithm, as defined in RFC 1321.
4 | * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6 | * Distributed under the BSD License
7 | * See http://pajhome.org.uk/crypt/md5 for more info.
8 | */
9 |
10 | /*
11 | * Configurable variables. You may need to tweak these to be compatible with
12 | * the server-side, but the defaults work in most cases.
13 | */
14 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
15 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
16 |
17 | /*
18 | * These are the functions you'll usually want to call
19 | * They take string arguments and return either hex or base-64 encoded strings
20 | */
21 | function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
22 | function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
23 | function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
24 | function hex_hmac_md5(k, d)
25 | { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
26 | function b64_hmac_md5(k, d)
27 | { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
28 | function any_hmac_md5(k, d, e)
29 | { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
30 |
31 | /*
32 | * Perform a simple self-test to see if the VM is working
33 | */
34 | function md5_vm_test()
35 | {
36 | return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
37 | }
38 |
39 | /*
40 | * Calculate the MD5 of a raw string
41 | */
42 | function rstr_md5(s)
43 | {
44 | return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
45 | }
46 |
47 | /*
48 | * Calculate the HMAC-MD5, of a key and some data (raw strings)
49 | */
50 | function rstr_hmac_md5(key, data)
51 | {
52 | var bkey = rstr2binl(key);
53 | if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
54 |
55 | var ipad = Array(16), opad = Array(16);
56 | for(var i = 0; i < 16; i++)
57 | {
58 | ipad[i] = bkey[i] ^ 0x36363636;
59 | opad[i] = bkey[i] ^ 0x5C5C5C5C;
60 | }
61 |
62 | var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
63 | return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
64 | }
65 |
66 | /*
67 | * Convert a raw string to a hex string
68 | */
69 | function rstr2hex(input)
70 | {
71 | try { hexcase } catch(e) { hexcase=0; }
72 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
73 | var output = "";
74 | var x;
75 | for(var i = 0; i < input.length; i++)
76 | {
77 | x = input.charCodeAt(i);
78 | output += hex_tab.charAt((x >>> 4) & 0x0F)
79 | + hex_tab.charAt( x & 0x0F);
80 | }
81 | return output;
82 | }
83 |
84 | /*
85 | * Convert a raw string to a base-64 string
86 | */
87 | function rstr2b64(input)
88 | {
89 | try { b64pad } catch(e) { b64pad=''; }
90 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
91 | var output = "";
92 | var len = input.length;
93 | for(var i = 0; i < len; i += 3)
94 | {
95 | var triplet = (input.charCodeAt(i) << 16)
96 | | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
97 | | (i + 2 < len ? input.charCodeAt(i+2) : 0);
98 | for(var j = 0; j < 4; j++)
99 | {
100 | if(i * 8 + j * 6 > input.length * 8) output += b64pad;
101 | else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
102 | }
103 | }
104 | return output;
105 | }
106 |
107 | /*
108 | * Convert a raw string to an arbitrary string encoding
109 | */
110 | function rstr2any(input, encoding)
111 | {
112 | var divisor = encoding.length;
113 | var i, j, q, x, quotient;
114 |
115 | /* Convert to an array of 16-bit big-endian values, forming the dividend */
116 | var dividend = Array(Math.ceil(input.length / 2));
117 | for(i = 0; i < dividend.length; i++)
118 | {
119 | dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
120 | }
121 |
122 | /*
123 | * Repeatedly perform a long division. The binary array forms the dividend,
124 | * the length of the encoding is the divisor. Once computed, the quotient
125 | * forms the dividend for the next step. All remainders are stored for later
126 | * use.
127 | */
128 | var full_length = Math.ceil(input.length * 8 /
129 | (Math.log(encoding.length) / Math.log(2)));
130 | var remainders = Array(full_length);
131 | for(j = 0; j < full_length; j++)
132 | {
133 | quotient = Array();
134 | x = 0;
135 | for(i = 0; i < dividend.length; i++)
136 | {
137 | x = (x << 16) + dividend[i];
138 | q = Math.floor(x / divisor);
139 | x -= q * divisor;
140 | if(quotient.length > 0 || q > 0)
141 | quotient[quotient.length] = q;
142 | }
143 | remainders[j] = x;
144 | dividend = quotient;
145 | }
146 |
147 | /* Convert the remainders to the output string */
148 | var output = "";
149 | for(i = remainders.length - 1; i >= 0; i--)
150 | output += encoding.charAt(remainders[i]);
151 |
152 | return output;
153 | }
154 |
155 | /*
156 | * Encode a string as utf-8.
157 | * For efficiency, this assumes the input is valid utf-16.
158 | */
159 | function str2rstr_utf8(input)
160 | {
161 | var output = "";
162 | var i = -1;
163 | var x, y;
164 |
165 | while(++i < input.length)
166 | {
167 | /* Decode utf-16 surrogate pairs */
168 | x = input.charCodeAt(i);
169 | y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
170 | if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
171 | {
172 | x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
173 | i++;
174 | }
175 |
176 | /* Encode output as utf-8 */
177 | if(x <= 0x7F)
178 | output += String.fromCharCode(x);
179 | else if(x <= 0x7FF)
180 | output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
181 | 0x80 | ( x & 0x3F));
182 | else if(x <= 0xFFFF)
183 | output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
184 | 0x80 | ((x >>> 6 ) & 0x3F),
185 | 0x80 | ( x & 0x3F));
186 | else if(x <= 0x1FFFFF)
187 | output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
188 | 0x80 | ((x >>> 12) & 0x3F),
189 | 0x80 | ((x >>> 6 ) & 0x3F),
190 | 0x80 | ( x & 0x3F));
191 | }
192 | return output;
193 | }
194 |
195 | /*
196 | * Encode a string as utf-16
197 | */
198 | function str2rstr_utf16le(input)
199 | {
200 | var output = "";
201 | for(var i = 0; i < input.length; i++)
202 | output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
203 | (input.charCodeAt(i) >>> 8) & 0xFF);
204 | return output;
205 | }
206 |
207 | function str2rstr_utf16be(input)
208 | {
209 | var output = "";
210 | for(var i = 0; i < input.length; i++)
211 | output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
212 | input.charCodeAt(i) & 0xFF);
213 | return output;
214 | }
215 |
216 | /*
217 | * Convert a raw string to an array of little-endian words
218 | * Characters >255 have their high-byte silently ignored.
219 | */
220 | function rstr2binl(input)
221 | {
222 | var output = Array(input.length >> 2);
223 | for(var i = 0; i < output.length; i++)
224 | output[i] = 0;
225 | for(var i = 0; i < input.length * 8; i += 8)
226 | output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
227 | return output;
228 | }
229 |
230 | /*
231 | * Convert an array of little-endian words to a string
232 | */
233 | function binl2rstr(input)
234 | {
235 | var output = "";
236 | for(var i = 0; i < input.length * 32; i += 8)
237 | output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
238 | return output;
239 | }
240 |
241 | /*
242 | * Calculate the MD5 of an array of little-endian words, and a bit length.
243 | */
244 | function binl_md5(x, len)
245 | {
246 | /* append padding */
247 | x[len >> 5] |= 0x80 << ((len) % 32);
248 | x[(((len + 64) >>> 9) << 4) + 14] = len;
249 |
250 | var a = 1732584193;
251 | var b = -271733879;
252 | var c = -1732584194;
253 | var d = 271733878;
254 |
255 | for(var i = 0; i < x.length; i += 16)
256 | {
257 | var olda = a;
258 | var oldb = b;
259 | var oldc = c;
260 | var oldd = d;
261 |
262 | a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
263 | d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
264 | c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
265 | b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
266 | a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
267 | d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
268 | c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
269 | b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
270 | a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
271 | d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
272 | c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
273 | b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
274 | a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
275 | d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
276 | c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
277 | b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
278 |
279 | a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
280 | d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
281 | c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
282 | b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
283 | a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
284 | d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
285 | c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
286 | b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
287 | a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
288 | d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
289 | c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
290 | b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
291 | a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
292 | d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
293 | c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
294 | b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
295 |
296 | a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
297 | d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
298 | c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
299 | b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
300 | a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
301 | d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
302 | c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
303 | b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
304 | a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
305 | d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
306 | c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
307 | b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
308 | a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
309 | d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
310 | c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
311 | b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
312 |
313 | a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
314 | d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
315 | c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
316 | b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
317 | a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
318 | d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
319 | c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
320 | b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
321 | a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
322 | d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
323 | c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
324 | b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
325 | a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
326 | d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
327 | c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
328 | b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
329 |
330 | a = safe_add(a, olda);
331 | b = safe_add(b, oldb);
332 | c = safe_add(c, oldc);
333 | d = safe_add(d, oldd);
334 | }
335 | return Array(a, b, c, d);
336 | }
337 |
338 | /*
339 | * These functions implement the four basic operations the algorithm uses.
340 | */
341 | function md5_cmn(q, a, b, x, s, t)
342 | {
343 | return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
344 | }
345 | function md5_ff(a, b, c, d, x, s, t)
346 | {
347 | return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
348 | }
349 | function md5_gg(a, b, c, d, x, s, t)
350 | {
351 | return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
352 | }
353 | function md5_hh(a, b, c, d, x, s, t)
354 | {
355 | return md5_cmn(b ^ c ^ d, a, b, x, s, t);
356 | }
357 | function md5_ii(a, b, c, d, x, s, t)
358 | {
359 | return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
360 | }
361 |
362 | /*
363 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally
364 | * to work around bugs in some JS interpreters.
365 | */
366 | function safe_add(x, y)
367 | {
368 | var lsw = (x & 0xFFFF) + (y & 0xFFFF);
369 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
370 | return (msw << 16) | (lsw & 0xFFFF);
371 | }
372 |
373 | /*
374 | * Bitwise rotate a 32-bit number to the left.
375 | */
376 | function bit_rol(num, cnt)
377 | {
378 | return (num << cnt) | (num >>> (32 - cnt));
379 | }
380 |
381 | module.exports = {
382 | hex_md5: hex_md5
383 | }
--------------------------------------------------------------------------------