mirror of
https://github.com/zarfadev/MobaXterm-Keygen.git
synced 2026-08-28 22:00:51 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [zarfadev]
|
||||||
|
patreon: zarfala
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
# MobaXterm Keygen & Customizer 🚀
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
> ⭐ **Please star this repository if you find it helpful!** ⭐
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
A modern, user-friendly web tool for generating activation keys and customizing MobaXterm, the ultimate terminal emulator for Windows with an integrated X11 server, SSH client, and comprehensive network toolset.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **✨ Clean, Modern UI** - Responsive design optimized for both desktop and mobile
|
||||||
|
- **🌓 Dark/Light Mode** - Toggle between themes with a click
|
||||||
|
- **🔒 Multiple Editions Support** - Generate keys for different MobaXterm editions
|
||||||
|
- **👥 Custom User Count** - Specify the number of concurrent users
|
||||||
|
- **💾 One-Click Downloads** - Instantly download your custom activation file
|
||||||
|
- **🔧 Complete Customizer** - Create personalized settings without the official customizer tool
|
||||||
|
- **🖼️ Custom Logo Support** - Replace the default MobaXterm logo with your own
|
||||||
|
- **📑 Bookmarks Manager** - Pre-define SSH, FTP, and other connection profiles
|
||||||
|
- **🔌 Plugin Integration** - Include plugins in your custom configuration
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
- Works with **MobaXterm versions 20.X, 25.2, and 25.3**
|
||||||
|
- Supports both portable and installer editions
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
### Key Generator
|
||||||
|
|
||||||
|
1. **Visit the Generator**: Go to the [MobaXterm Key Generator](https://moba-xterm-keygen.vercel.app/)
|
||||||
|
2. **Fill in the Form**:
|
||||||
|
- Select the desired MobaXterm edition
|
||||||
|
- Enter a username (letters only)
|
||||||
|
- Choose your MobaXterm version (20.X or 25.X)
|
||||||
|
- Specify the number of users
|
||||||
|
3. **Download**: Click "Download Key" to get your Custom.mxtpro file
|
||||||
|
4. **Activate**: Place the generated file in your MobaXterm installation directory:
|
||||||
|
```
|
||||||
|
C:\Program Files (x86)\Mobatek\MobaXterm
|
||||||
|
```
|
||||||
|
|
||||||
|
### Customizer
|
||||||
|
|
||||||
|
1. **Go to the Customizer Tab** in the web interface
|
||||||
|
2. **Configure Your Settings**:
|
||||||
|
- **Banner**: Create a personalized welcome message
|
||||||
|
- **Profile**: Configure a custom bash profile (similar to /etc/profile in Linux)
|
||||||
|
- **Settings**: Toggle MobaXterm features on/off
|
||||||
|
- **Logo**: Upload your custom logo image
|
||||||
|
- **Bookmarks**: Create predefined connections for your users
|
||||||
|
- **Plugins**: Add optional MobaXterm plugins (.mxt3 files)
|
||||||
|
3. **Generate Settings**: Click "Generate Configuration File" to download your settings
|
||||||
|
4. **Apply Settings**: Use either method below to apply your customization
|
||||||
|
|
||||||
|
### Settings Merger
|
||||||
|
|
||||||
|
1. **Go to the Custom Settings Merger Tab**
|
||||||
|
2. **Upload Files**:
|
||||||
|
- Your license key file (Custom.mxtpro)
|
||||||
|
- Your customization file (MobaXterm customization.custom)
|
||||||
|
3. **Merge**: Create a single file with both your license and custom settings
|
||||||
|
4. **Deploy**: Copy the merged Custom.mxtpro to your MobaXterm installation directory
|
||||||
|
|
||||||
|
## Installation Guide
|
||||||
|
|
||||||
|
### Step 1: Download MobaXterm
|
||||||
|
Download the latest version from the [official MobaXterm website](https://mobaxterm.mobatek.net/download-home-edition.html).
|
||||||
|
|
||||||
|
### Step 2: Generate Your Key & Customization
|
||||||
|
Use our tool to:
|
||||||
|
1. Create your activation key
|
||||||
|
2. Customize your settings (optional)
|
||||||
|
3. Merge your license with your customization (optional)
|
||||||
|
|
||||||
|
### Step 3: Activate MobaXterm
|
||||||
|
1. Locate your MobaXterm installation folder:
|
||||||
|
- **Default Path**: `C:\Program Files (x86)\Mobatek\MobaXterm`
|
||||||
|
- Or right-click the MobaXterm shortcut and select "Open file location"
|
||||||
|
2. Copy the `Custom.mxtpro` file to this directory
|
||||||
|
3. Start MobaXterm - your license and customizations should now be applied!
|
||||||
|
|
||||||
|
### Alternative Customization Method
|
||||||
|
|
||||||
|
MobaXterm.exe has a customizer mode that you can access by adding the parameter "-customizer":
|
||||||
|
|
||||||
|
```
|
||||||
|
.\MobaXterm.exe -customizer
|
||||||
|
```
|
||||||
|
|
||||||
|
This official tool also allows you to export your settings to a file named "MobaXterm customization.custom". Our web-based customizer provides similar functionality but is accessible directly in your browser.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
1. **Activation Not Working?**
|
||||||
|
- Verify you're using a compatible version (20.X, 25.2, or 25.3)
|
||||||
|
- Make sure the file is in the correct location
|
||||||
|
- Check that the file is named exactly `Custom.mxtpro`
|
||||||
|
|
||||||
|
2. **Error During Key Generation?**
|
||||||
|
- Ensure all form fields are filled correctly
|
||||||
|
- Username must contain only letters (no spaces, numbers, or special characters)
|
||||||
|
- Try refreshing the page and generating again
|
||||||
|
|
||||||
|
3. **Customization Not Applying?**
|
||||||
|
- Verify that you've merged the customization with your license file
|
||||||
|
- Make sure the merged file is named exactly `Custom.mxtpro`
|
||||||
|
- Try restarting MobaXterm after placing the file in the installation directory
|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
This tool uses client-side processing to generate valid license keys and customization files based on your inputs. Everything is generated directly in your browser - no data is sent to any server, ensuring your privacy and security.
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
|
||||||
|
This tool is provided for educational purposes only. Please support the developers by purchasing a license for commercial use.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Built With
|
||||||
|
- Vue.js
|
||||||
|
- Tailwind CSS
|
||||||
|
- Modern JavaScript
|
||||||
|
|
||||||
|
### Version History
|
||||||
|
- **v2.5** - Added support for version 25.3
|
||||||
|
- **v2.4** - Added full MobaXterm customizer functionality
|
||||||
|
- **v2.3** - Added custom settings merger
|
||||||
|
- **v2.2** - Dark mode and mobile optimization
|
||||||
|
- **v2.1** - Added support for version 25.2
|
||||||
|
- **v2.0** - Major UI redesign
|
||||||
|
- **v1.0** - Initial release
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Created with ❤️ by Zarfala
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
⭐ [Star this repository on GitHub!](https://github.com/zarfadev/MobaXterm-Keygen) ⭐
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
NOTE: This is just an experiment and
|
||||||
|
could use some changes to improve performance:
|
||||||
|
|
||||||
|
https://x.com/actualTimWilson/status/1730753841795158313
|
||||||
|
|
||||||
|
See a production optimized version here: https://charmui.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Inter, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes jumbo {
|
||||||
|
from {
|
||||||
|
background-position: 50% 50%, 50% 50%;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-position: 350% 50%, 350% 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New Styles for Form Isolation */
|
||||||
|
.box-main {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jumbo {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jumbo {
|
||||||
|
--stripes: repeating-linear-gradient(
|
||||||
|
100deg,
|
||||||
|
#fff 0%,
|
||||||
|
#fff 7%,
|
||||||
|
transparent 10%,
|
||||||
|
transparent 12%,
|
||||||
|
#fff 16%
|
||||||
|
);
|
||||||
|
--stripesDark: repeating-linear-gradient(
|
||||||
|
100deg,
|
||||||
|
#000 0%,
|
||||||
|
#000 7%,
|
||||||
|
transparent 10%,
|
||||||
|
transparent 12%,
|
||||||
|
#000 16%
|
||||||
|
);
|
||||||
|
--rainbow: repeating-linear-gradient(
|
||||||
|
100deg,
|
||||||
|
#60a5fa 10%,
|
||||||
|
#e879f9 15%,
|
||||||
|
#60a5fa 20%,
|
||||||
|
#5eead4 25%,
|
||||||
|
#60a5fa 30%
|
||||||
|
);
|
||||||
|
background-image: var(--stripes), var(--rainbow);
|
||||||
|
background-size: 300%, 200%;
|
||||||
|
background-position: 50% 50%, 50% 50%;
|
||||||
|
|
||||||
|
filter: blur(10px) invert(100%);
|
||||||
|
|
||||||
|
mask-image: radial-gradient(ellipse at 100% 0%, black 40%, transparent 70%);
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jumbo::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background-image: var(--stripes), var(--rainbow);
|
||||||
|
background-size: 200%, 100%;
|
||||||
|
animation: jumbo 60s linear infinite;
|
||||||
|
background-attachment: fixed;
|
||||||
|
mix-blend-mode: difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .jumbo {
|
||||||
|
background-image: var(--stripesDark), var(--rainbow);
|
||||||
|
filter: blur(10px) opacity(50%) saturate(200%);
|
||||||
|
}
|
||||||
|
.dark .jumbo::after {
|
||||||
|
background-image: var(--stripesDark), var(--rainbow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-white {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(255 255 255);
|
||||||
|
}
|
||||||
Vendored
+905
@@ -0,0 +1,905 @@
|
|||||||
|
/*!
|
||||||
|
Pure v2.0.3
|
||||||
|
Copyright 2013 Yahoo!
|
||||||
|
Licensed under the BSD License.
|
||||||
|
https://github.com/pure-css/pure/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
normalize.css v | MIT License | git.io/normalize
|
||||||
|
Copyright (c) Nicolas Gallagher and Jonathan Neal
|
||||||
|
*/
|
||||||
|
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||||
|
html {
|
||||||
|
line-height: 1.15;
|
||||||
|
-webkit-text-size-adjust: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: .67em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
-webkit-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
height: 0;
|
||||||
|
overflow: visible
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: monospace, monospace;
|
||||||
|
font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: none;
|
||||||
|
text-decoration: underline;
|
||||||
|
-webkit-text-decoration: underline dotted;
|
||||||
|
text-decoration: underline dotted
|
||||||
|
}
|
||||||
|
|
||||||
|
b, strong {
|
||||||
|
font-weight: bolder
|
||||||
|
}
|
||||||
|
|
||||||
|
code, kbd, samp {
|
||||||
|
font-family: monospace, monospace;
|
||||||
|
font-size: 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%
|
||||||
|
}
|
||||||
|
|
||||||
|
sub, sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -.25em
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -.5em
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none
|
||||||
|
}
|
||||||
|
|
||||||
|
button, input, optgroup, select, textarea {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 100%;
|
||||||
|
line-height: 1.15;
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
button, input {
|
||||||
|
overflow: visible
|
||||||
|
}
|
||||||
|
|
||||||
|
button, select {
|
||||||
|
text-transform: none
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=button], [type=reset], [type=submit], button {
|
||||||
|
-webkit-appearance: button
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner {
|
||||||
|
border-style: none;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=button]:-moz-focusring, [type=reset]:-moz-focusring, [type=submit]:-moz-focusring, button:-moz-focusring {
|
||||||
|
outline: 1px dotted ButtonText
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
padding: .35em .75em .625em
|
||||||
|
}
|
||||||
|
|
||||||
|
legend {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: inherit;
|
||||||
|
display: table;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
white-space: normal
|
||||||
|
}
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=checkbox], [type=radio] {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=number]::-webkit-inner-spin-button, [type=number]::-webkit-outer-spin-button {
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=search] {
|
||||||
|
-webkit-appearance: textfield;
|
||||||
|
outline-offset: -2px
|
||||||
|
}
|
||||||
|
|
||||||
|
[type=search]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
font: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
details {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item
|
||||||
|
}
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-family: sans-serif
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden, [hidden] {
|
||||||
|
display: none !important
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-img {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-g {
|
||||||
|
letter-spacing: -.31em;
|
||||||
|
text-rendering: optimizespeed;
|
||||||
|
font-family: FreeSans, Arimo, "Droid Sans", Helvetica, Arial, sans-serif;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-flow: row wrap;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
-ms-flex-line-pack: start;
|
||||||
|
align-content: flex-start
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (-ms-high-contrast:none), (-ms-high-contrast:active) {
|
||||||
|
table .pure-g {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.opera-only :-o-prefocus, .pure-g {
|
||||||
|
word-spacing: -.43em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u {
|
||||||
|
display: inline-block;
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-spacing: normal;
|
||||||
|
vertical-align: top;
|
||||||
|
text-rendering: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-g [class*=pure-u] {
|
||||||
|
font-family: sans-serif
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1, .pure-u-1-1, .pure-u-1-12, .pure-u-1-2, .pure-u-1-24, .pure-u-1-3, .pure-u-1-4, .pure-u-1-5, .pure-u-1-6, .pure-u-1-8, .pure-u-10-24, .pure-u-11-12, .pure-u-11-24, .pure-u-12-24, .pure-u-13-24, .pure-u-14-24, .pure-u-15-24, .pure-u-16-24, .pure-u-17-24, .pure-u-18-24, .pure-u-19-24, .pure-u-2-24, .pure-u-2-3, .pure-u-2-5, .pure-u-20-24, .pure-u-21-24, .pure-u-22-24, .pure-u-23-24, .pure-u-24-24, .pure-u-3-24, .pure-u-3-4, .pure-u-3-5, .pure-u-3-8, .pure-u-4-24, .pure-u-4-5, .pure-u-5-12, .pure-u-5-24, .pure-u-5-5, .pure-u-5-6, .pure-u-5-8, .pure-u-6-24, .pure-u-7-12, .pure-u-7-24, .pure-u-7-8, .pure-u-8-24, .pure-u-9-24 {
|
||||||
|
display: flex;
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-spacing: normal;
|
||||||
|
vertical-align: top;
|
||||||
|
text-rendering: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1-24 {
|
||||||
|
width: 4.1667%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1-12, .pure-u-2-24 {
|
||||||
|
width: 8.3333%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1-8, .pure-u-3-24 {
|
||||||
|
width: 12.5%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1-6, .pure-u-4-24 {
|
||||||
|
width: 16.6667%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1-5 {
|
||||||
|
width: 20%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-5-24 {
|
||||||
|
width: 20.8333%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1-4, .pure-u-6-24 {
|
||||||
|
width: 25%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-7-24 {
|
||||||
|
width: 29.1667%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1-3, .pure-u-8-24 {
|
||||||
|
width: 33.3333%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-3-8, .pure-u-9-24 {
|
||||||
|
width: 37.5%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-2-5 {
|
||||||
|
width: 40%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-10-24, .pure-u-5-12 {
|
||||||
|
width: 41.6667%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-11-24 {
|
||||||
|
width: 45.8333%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1-2, .pure-u-12-24 {
|
||||||
|
width: 50%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-13-24 {
|
||||||
|
width: 54.1667%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-14-24, .pure-u-7-12 {
|
||||||
|
width: 58.3333%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-3-5 {
|
||||||
|
width: 60%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-15-24, .pure-u-5-8 {
|
||||||
|
width: 62.5%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-16-24, .pure-u-2-3 {
|
||||||
|
width: 66.6667%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-17-24 {
|
||||||
|
width: 70.8333%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-18-24, .pure-u-3-4 {
|
||||||
|
width: 75%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-19-24 {
|
||||||
|
width: 79.1667%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-4-5 {
|
||||||
|
width: 80%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-20-24, .pure-u-5-6 {
|
||||||
|
width: 83.3333%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-21-24, .pure-u-7-8 {
|
||||||
|
width: 87.5%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-11-12, .pure-u-22-24 {
|
||||||
|
width: 91.6667%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-23-24 {
|
||||||
|
width: 95.8333%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-u-1, .pure-u-1-1, .pure-u-24-24, .pure-u-5-5 {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: normal;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button::-moz-focus-inner {
|
||||||
|
padding: 0;
|
||||||
|
border: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-group {
|
||||||
|
letter-spacing: -.31em;
|
||||||
|
text-rendering: optimizespeed
|
||||||
|
}
|
||||||
|
|
||||||
|
.opera-only :-o-prefocus, .pure-button-group {
|
||||||
|
word-spacing: -.43em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-group .pure-button {
|
||||||
|
letter-spacing: normal;
|
||||||
|
word-spacing: normal;
|
||||||
|
vertical-align: top;
|
||||||
|
text-rendering: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 100%;
|
||||||
|
padding: .5em 1em;
|
||||||
|
color: rgba(0, 0, 0, .8);
|
||||||
|
border: none transparent;
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-hover, .pure-button:focus, .pure-button:hover {
|
||||||
|
background-image: -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(40%, rgba(0, 0, 0, .05)), to(rgba(0, 0, 0, .1)));
|
||||||
|
background-image: linear-gradient(transparent, rgba(0, 0, 0, .05) 40%, rgba(0, 0, 0, .1))
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button:focus {
|
||||||
|
outline: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-active, .pure-button:active {
|
||||||
|
-webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, .15) inset, 0 0 6px rgba(0, 0, 0, .2) inset;
|
||||||
|
box-shadow: 0 0 0 1px rgba(0, 0, 0, .15) inset, 0 0 6px rgba(0, 0, 0, .2) inset;
|
||||||
|
border-color: #000
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-disabled, .pure-button-disabled:active, .pure-button-disabled:focus, .pure-button-disabled:hover, .pure-button[disabled] {
|
||||||
|
border: none;
|
||||||
|
background-image: none;
|
||||||
|
opacity: .4;
|
||||||
|
cursor: not-allowed;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
pointer-events: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-hidden {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-primary, .pure-button-selected, a.pure-button-primary, a.pure-button-selected {
|
||||||
|
background-color: #0078e7;
|
||||||
|
color: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-group .pure-button {
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
border-right: 1px solid rgba(0, 0, 0, .2)
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-group .pure-button:first-child {
|
||||||
|
border-top-left-radius: 2px;
|
||||||
|
border-bottom-left-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-button-group .pure-button:last-child {
|
||||||
|
border-top-right-radius: 2px;
|
||||||
|
border-bottom-right-radius: 2px;
|
||||||
|
border-right: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input[type=color], .pure-form input[type=date], .pure-form input[type=datetime-local], .pure-form input[type=datetime], .pure-form input[type=email], .pure-form input[type=month], .pure-form input[type=number], .pure-form input[type=password], .pure-form input[type=search], .pure-form input[type=tel], .pure-form input[type=text], .pure-form input[type=time], .pure-form input[type=url], .pure-form input[type=week], .pure-form select, .pure-form textarea {
|
||||||
|
padding: .5em .6em;
|
||||||
|
display: inline-block;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: .5rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-color: rgb(209 213 219 / 1);
|
||||||
|
background-color: #f9fafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input:not([type]) {
|
||||||
|
padding: .5em .6em;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: normal;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: .5rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-color: #ccc;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input[type=color] {
|
||||||
|
padding: .2em .5em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input[type=color]:focus, .pure-form input[type=date]:focus, .pure-form input[type=datetime-local]:focus, .pure-form input[type=datetime]:focus, .pure-form input[type=email]:focus, .pure-form input[type=month]:focus, .pure-form input[type=number]:focus, .pure-form input[type=password]:focus, .pure-form input[type=search]:focus, .pure-form input[type=tel]:focus, .pure-form input[type=text]:focus, .pure-form input[type=time]:focus, .pure-form input[type=url]:focus, .pure-form input[type=week]:focus, .pure-form select:focus, .pure-form textarea:focus {
|
||||||
|
outline: 0;
|
||||||
|
border-color: #129fea
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input:not([type]):focus {
|
||||||
|
outline: 0;
|
||||||
|
border-color: #129fea
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input[type=checkbox]:focus, .pure-form input[type=file]:focus, .pure-form input[type=radio]:focus {
|
||||||
|
outline: thin solid #129fea;
|
||||||
|
outline: 1px auto #129fea
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-checkbox, .pure-form .pure-radio {
|
||||||
|
margin: .5em 0;
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input[type=color][disabled], .pure-form input[type=date][disabled], .pure-form input[type=datetime-local][disabled], .pure-form input[type=datetime][disabled], .pure-form input[type=email][disabled], .pure-form input[type=month][disabled], .pure-form input[type=number][disabled], .pure-form input[type=password][disabled], .pure-form input[type=search][disabled], .pure-form input[type=tel][disabled], .pure-form input[type=text][disabled], .pure-form input[type=time][disabled], .pure-form input[type=url][disabled], .pure-form input[type=week][disabled], .pure-form select[disabled], .pure-form textarea[disabled] {
|
||||||
|
cursor: not-allowed;
|
||||||
|
background-color: #eaeded;
|
||||||
|
color: #cad2d3
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input:not([type])[disabled] {
|
||||||
|
cursor: not-allowed;
|
||||||
|
background-color: #eaeded;
|
||||||
|
color: #cad2d3
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input[readonly], .pure-form select[readonly], .pure-form textarea[readonly] {
|
||||||
|
background-color: #eee;
|
||||||
|
color: #777;
|
||||||
|
border-color: #ccc
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input:focus:invalid, .pure-form select:focus:invalid, .pure-form textarea:focus:invalid {
|
||||||
|
color: #b94a48;
|
||||||
|
border-color: #e9322d
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input[type=checkbox]:focus:invalid:focus, .pure-form input[type=file]:focus:invalid:focus, .pure-form input[type=radio]:focus:invalid:focus {
|
||||||
|
outline-color: #e9322d
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form select {
|
||||||
|
height: 2.3em !important;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form select[multiple] {
|
||||||
|
height: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form label {
|
||||||
|
margin: .5em 0 .2em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form fieldset {
|
||||||
|
margin: 0;
|
||||||
|
padding: .35em 0 .75em;
|
||||||
|
border: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form legend {
|
||||||
|
display: block;
|
||||||
|
padding: .3em 0;
|
||||||
|
margin-bottom: .3em;
|
||||||
|
color: #333;
|
||||||
|
/* border-bottom: 1px solid #e5e5e5 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-stacked input[type=color], .pure-form-stacked input[type=date], .pure-form-stacked input[type=datetime-local], .pure-form-stacked input[type=datetime], .pure-form-stacked input[type=email], .pure-form-stacked input[type=file], .pure-form-stacked input[type=month], .pure-form-stacked input[type=number], .pure-form-stacked input[type=password], .pure-form-stacked input[type=search], .pure-form-stacked input[type=tel], .pure-form-stacked input[type=text], .pure-form-stacked input[type=time], .pure-form-stacked input[type=url], .pure-form-stacked input[type=week], .pure-form-stacked label, .pure-form-stacked select, .pure-form-stacked textarea {
|
||||||
|
display: block;
|
||||||
|
margin: .25em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-stacked input:not([type]) {
|
||||||
|
display: block;
|
||||||
|
margin: .25em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-aligned input, .pure-form-aligned select, .pure-form-aligned textarea, .pure-form-message-inline {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-aligned textarea {
|
||||||
|
vertical-align: top
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-aligned .pure-control-group {
|
||||||
|
margin-bottom: .5em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-aligned .pure-control-group label {
|
||||||
|
text-align: right;
|
||||||
|
display: inline;
|
||||||
|
padding: 0.3em;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 10em;
|
||||||
|
margin: 0 1em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-aligned .pure-controls {
|
||||||
|
margin: 1.5em 0 0 11em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-input-rounded, .pure-form input.pure-input-rounded {
|
||||||
|
border-radius: 2em;
|
||||||
|
padding: .5em 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-group fieldset {
|
||||||
|
margin-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-group input, .pure-form .pure-group textarea {
|
||||||
|
display: block;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 0 -1px;
|
||||||
|
border-radius: 0;
|
||||||
|
position: relative;
|
||||||
|
top: -1px
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-group input:focus, .pure-form .pure-group textarea:focus {
|
||||||
|
z-index: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-group input:first-child, .pure-form .pure-group textarea:first-child {
|
||||||
|
top: 1px;
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-group input:first-child:last-child, .pure-form .pure-group textarea:first-child:last-child {
|
||||||
|
top: 1px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-group input:last-child, .pure-form .pure-group textarea:last-child {
|
||||||
|
top: -2px;
|
||||||
|
border-radius: 0 0 4px 4px;
|
||||||
|
margin: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-group button {
|
||||||
|
margin: .35em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-input-1 {
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-input-3-4 {
|
||||||
|
width: 75%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-input-2-3 {
|
||||||
|
width: 66%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-input-1-2 {
|
||||||
|
width: 50%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-input-1-3 {
|
||||||
|
width: 33%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form .pure-input-1-4 {
|
||||||
|
width: 25%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-message-inline {
|
||||||
|
display: inline-block;
|
||||||
|
padding-left: .3em;
|
||||||
|
color: #666;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: .875em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-message {
|
||||||
|
display: block;
|
||||||
|
color: #666;
|
||||||
|
font-size: .875em
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width :480px) {
|
||||||
|
.pure-form button[type=submit] {
|
||||||
|
margin: .7em 0 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form input:not([type]), .pure-form input[type=color], .pure-form input[type=date], .pure-form input[type=datetime-local], .pure-form input[type=datetime], .pure-form input[type=email], .pure-form input[type=month], .pure-form input[type=number], .pure-form input[type=password], .pure-form input[type=search], .pure-form input[type=tel], .pure-form input[type=text], .pure-form input[type=time], .pure-form input[type=url], .pure-form input[type=week], .pure-form label {
|
||||||
|
margin-bottom: .3em;
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-group input:not([type]), .pure-group input[type=color], .pure-group input[type=date], .pure-group input[type=datetime-local], .pure-group input[type=datetime], .pure-group input[type=email], .pure-group input[type=month], .pure-group input[type=number], .pure-group input[type=password], .pure-group input[type=search], .pure-group input[type=tel], .pure-group input[type=text], .pure-group input[type=time], .pure-group input[type=url], .pure-group input[type=week] {
|
||||||
|
margin-bottom: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-aligned .pure-control-group label {
|
||||||
|
margin-bottom: .3em;
|
||||||
|
text-align: left;
|
||||||
|
display: block;
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-aligned .pure-controls {
|
||||||
|
margin: 1.5em 0 0 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-form-message, .pure-form-message-inline {
|
||||||
|
display: block;
|
||||||
|
font-size: .75em;
|
||||||
|
padding: .2em 0 .8em
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-fixed {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-item, .pure-menu-list {
|
||||||
|
position: relative
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-item {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
height: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-heading, .pure-menu-link {
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
white-space: nowrap
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal {
|
||||||
|
width: 100%;
|
||||||
|
white-space: nowrap
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal .pure-menu-list {
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal .pure-menu-heading, .pure-menu-horizontal .pure-menu-item, .pure-menu-horizontal .pure-menu-separator {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-item .pure-menu-item {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-children {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
left: 100%;
|
||||||
|
top: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
z-index: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal .pure-menu-children {
|
||||||
|
left: 0;
|
||||||
|
top: auto;
|
||||||
|
width: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-active>.pure-menu-children, .pure-menu-allow-hover:hover>.pure-menu-children {
|
||||||
|
display: block;
|
||||||
|
position: absolute
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-has-children>.pure-menu-link:after {
|
||||||
|
padding-left: .5em;
|
||||||
|
content: "\25B8";
|
||||||
|
font-size: small
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal .pure-menu-has-children>.pure-menu-link:after {
|
||||||
|
content: "\25BE"
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-scrollable {
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-scrollable .pure-menu-list {
|
||||||
|
display: block
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal.pure-menu-scrollable .pure-menu-list {
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal.pure-menu-scrollable {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: .5em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal .pure-menu-children .pure-menu-separator, .pure-menu-separator {
|
||||||
|
background-color: #ccc;
|
||||||
|
height: 1px;
|
||||||
|
margin: .3em 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal .pure-menu-separator {
|
||||||
|
width: 1px;
|
||||||
|
height: 1.3em;
|
||||||
|
margin: 0 .3em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-horizontal .pure-menu-children .pure-menu-separator {
|
||||||
|
display: block;
|
||||||
|
width: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-heading {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #565d64
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-link {
|
||||||
|
color: #777
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-children {
|
||||||
|
background-color: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-disabled, .pure-menu-heading, .pure-menu-link {
|
||||||
|
padding: .5em 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-disabled {
|
||||||
|
opacity: .5
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-disabled .pure-menu-link:hover {
|
||||||
|
background-color: transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-active>.pure-menu-link, .pure-menu-link:focus, .pure-menu-link:hover {
|
||||||
|
background-color: #eee
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-menu-selected>.pure-menu-link, .pure-menu-selected>.pure-menu-link:visited {
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
empty-cells: show;
|
||||||
|
border: 1px solid #cbcbcb
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table caption {
|
||||||
|
color: #000;
|
||||||
|
font: italic 85%/1 arial, sans-serif;
|
||||||
|
padding: 1em 0;
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table td, .pure-table th {
|
||||||
|
border-left: 1px solid #cbcbcb;
|
||||||
|
border-width: 0 0 0 1px;
|
||||||
|
font-size: inherit;
|
||||||
|
margin: 0;
|
||||||
|
overflow: visible;
|
||||||
|
padding: .5em 1em
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table thead {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
color: #000;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table td {
|
||||||
|
background-color: transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table-odd td {
|
||||||
|
background-color: #f2f2f2
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table-striped tr:nth-child(2n-1) td {
|
||||||
|
background-color: #f2f2f2
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table-bordered td {
|
||||||
|
border-bottom: 1px solid #cbcbcb
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table-bordered tbody>tr:last-child>td {
|
||||||
|
border-bottom-width: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table-horizontal td, .pure-table-horizontal th {
|
||||||
|
border-width: 0 0 1px 0;
|
||||||
|
border-bottom: 1px solid #cbcbcb
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-table-horizontal tbody>tr:last-child>td {
|
||||||
|
border-bottom-width: 0
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
.box-main {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auto-center {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-main {
|
||||||
|
padding-right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-input {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-input-tips-wrap {
|
||||||
|
color: rgb(255, 52, 52);
|
||||||
|
position: absolute;
|
||||||
|
left: 10px;
|
||||||
|
bottom: 50px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
box-shadow: inset 0 1px 3px #ddd;
|
||||||
|
background-color: white;
|
||||||
|
width: auto;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-input-tips {
|
||||||
|
position: relative;
|
||||||
|
top: 10px;
|
||||||
|
margin: 0 20px;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
font-size: large;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-input-arrow {
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
top: 49px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border: 10px solid;
|
||||||
|
border-color: gray transparent transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote {
|
||||||
|
margin-top: 30px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
+506
@@ -0,0 +1,506 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>MobaXterm Keygen</title>
|
||||||
|
<meta name="description" content="Website created with love by Zarfala" />
|
||||||
|
<link rel="icon" href="https://i.imgur.com/FtcF9ZP.png" />
|
||||||
|
<link href="./css/pure-min.css?=2" rel="stylesheet" />
|
||||||
|
<link href="./css/style.css" rel="stylesheet" />
|
||||||
|
<link href="./css/fire.css" rel="stylesheet" />
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
<script>
|
||||||
|
tailwind.config = {
|
||||||
|
darkMode: "class",
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
screens: {
|
||||||
|
'xs': '475px',
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
primary: {
|
||||||
|
50: '#eef2ff',
|
||||||
|
100: '#e0e7ff',
|
||||||
|
500: '#6366f1',
|
||||||
|
600: '#4f46e5',
|
||||||
|
700: '#4338ca',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<!-- Preloader style -->
|
||||||
|
<style>
|
||||||
|
#preloader {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #111;
|
||||||
|
z-index: 9999;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
transition: opacity 0.5s ease-in-out, visibility 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
#preloader.fade-out {
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
.spinner {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border: 5px solid rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top-color: #6366f1;
|
||||||
|
animation: spin 1s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.content-hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.5s ease-in-out, visibility 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
.content-visible {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<!-- Meta tags for better SEO and sharing -->
|
||||||
|
<meta property="og:title" content="MobaXterm Keygen" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:description" content="Website created with love by Zarfala" />
|
||||||
|
<meta property="og:image" content="https://i.imgur.com/FtcF9ZP.png" />
|
||||||
|
<meta property="og:site_name" content="MobaXterm Keygen" />
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:title" content="MobaXterm Keygen">
|
||||||
|
<meta name="twitter:description" content="Website created with love by Zarfala">
|
||||||
|
<meta name="twitter:image" content="https://i.imgur.com/FtcF9ZP.png">
|
||||||
|
</head>
|
||||||
|
<body class="transition-colors duration-300">
|
||||||
|
<!-- Preloader -->
|
||||||
|
<div id="preloader">
|
||||||
|
<div class="spinner"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main id="main-content" class="content-hidden">
|
||||||
|
<div class="relative flex min-h-screen flex-col items-center justify-center bg-white dark:bg-black transition-colors duration-300 overflow-hidden px-4">
|
||||||
|
<!-- Background effect -->
|
||||||
|
<div class="flex inset-0 overflow-hidden">
|
||||||
|
<div class="jumbo absolute opacity-60"></div>
|
||||||
|
</div>
|
||||||
|
<div class="box-main w-full max-w-xl mx-auto">
|
||||||
|
<div id="app" class="relative z-10 p-6 sm:p-10 w-full text-left shadow-lg rounded-xl bg-white dark:bg-slate-900/80 dark:backdrop-blur dark:ring-1 dark:ring-inset dark:ring-white/10 transition-all duration-300">
|
||||||
|
<!-- Header Section -->
|
||||||
|
<header class="mb-8 text-center">
|
||||||
|
<h1 class="relative flex flex-col xs:flex-row items-center justify-center text-4xl sm:text-5xl font-bold text-gray-800 dark:text-white dark:opacity-95 transition-colors">
|
||||||
|
<span>MobaXterm</span>
|
||||||
|
<span class="mt-2 xs:mt-0 xs:ml-2 rounded-xl bg-current p-2 text-[0.7em] leading-none">
|
||||||
|
<span class="text-white dark:text-black">Keygen</span>
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<!-- Version Badge -->
|
||||||
|
<div class="mt-4 inline-flex items-center px-3 py-1 rounded-full bg-gradient-to-r from-indigo-500 via-purple-500 to-pink-500 text-sm font-medium text-white"> Compatible with versions 20.X, 25.2 and 25.3 </div>
|
||||||
|
<!-- Theme Toggle -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<button onclick="toggleTheme()" class="px-3 py-1 border border-stone-200 rounded-full drop-shadow-sm text-sm text-stone-800 dark:text-white bg-white/40 dark:bg-black/40 backdrop-blur-lg hover:border-stone-300 transition-colors dark:border-stone-500 dark:hover:border-stone-400"> Toggle Theme </button>
|
||||||
|
</div>
|
||||||
|
<!-- Tab Navigation -->
|
||||||
|
<div class="mt-6 border-b border-gray-200 dark:border-gray-700">
|
||||||
|
<nav class="flex space-x-4" aria-label="Tabs">
|
||||||
|
<button @click="activeTab = 'keyGenerator'"
|
||||||
|
:class="[activeTab === 'keyGenerator' ? 'border-primary-500 text-primary-600 dark:text-primary-400' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300', 'px-1 pb-4 text-sm font-medium border-b-2']">
|
||||||
|
Key Generator
|
||||||
|
</button>
|
||||||
|
<button @click="activeTab = 'customMerger'"
|
||||||
|
:class="[activeTab === 'customMerger' ? 'border-primary-500 text-primary-600 dark:text-primary-400' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 dark:text-gray-400 dark:hover:text-gray-300', 'px-1 pb-4 text-sm font-medium border-b-2']">
|
||||||
|
Custom Settings Merger
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Key Generator Tab -->
|
||||||
|
<div v-if="activeTab === 'keyGenerator'">
|
||||||
|
<form @submit.prevent="validateAndGenerate">
|
||||||
|
<div class="space-y-6">
|
||||||
|
<div>
|
||||||
|
<label for="licenseType" class="block text-lg text-gray-700 dark:text-gray-300">Edition:</label>
|
||||||
|
<div class="relative">
|
||||||
|
<select name="licenseType" id="licenseType" v-model="licenseType" class="w-full mt-1 p-2 pr-8 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-colors appearance-none">
|
||||||
|
<option value="" disabled>Select an option</option>
|
||||||
|
<option v-for="(val, key) in LICENSE_TYPES" :value="val">{{key}}</option>
|
||||||
|
</select>
|
||||||
|
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 mt-1 text-gray-700 dark:text-gray-300">
|
||||||
|
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
||||||
|
<path d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p v-if="errors.licenseType" class="mt-1 text-red-500 text-sm">{{ errors.licenseType }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="userName" class="block text-lg text-gray-700 dark:text-gray-300">Username:</label>
|
||||||
|
<div class="relative">
|
||||||
|
<input type="text" id="userName" v-model="userName" @input="validateUserName" placeholder="Example defaultUser" class="w-full mt-1 p-2 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-colors" />
|
||||||
|
<p v-if="errors.userName" class="mt-1 text-red-500 text-sm">{{ errors.userName }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="versionName" class="block text-lg text-gray-700 dark:text-gray-300">Version:</label>
|
||||||
|
<div class="relative">
|
||||||
|
<input type="text" id="versionName" v-model="versionName" @input="validateVersion" placeholder="Example 25.3" class="w-full mt-1 p-2 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-colors" />
|
||||||
|
<p v-if="errors.versionName" class="mt-1 text-red-500 text-sm">{{ errors.versionName }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="userNum" class="block text-lg text-gray-700 dark:text-gray-300">Number of users:</label>
|
||||||
|
<div class="relative">
|
||||||
|
<input type="number" id="userNum" v-model="userNum" @input="validateUserNum" placeholder="Example 1" min="1" class="w-full mt-1 p-2 rounded-lg border border-gray-300 dark:border-gray-600 dark:bg-slate-800 dark:text-white focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none transition-colors" />
|
||||||
|
<p v-if="errors.userNum" class="mt-1 text-red-500 text-sm">{{ errors.userNum }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Download Button -->
|
||||||
|
<div class="text-center pt-4">
|
||||||
|
<button type="submit" class="w-full sm:w-auto px-6 py-3 bg-primary-600 text-white rounded-lg shadow-md hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors duration-200"> Download Key </button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Custom Settings Merger Tab -->
|
||||||
|
<div v-if="activeTab === 'customMerger'" class="space-y-6">
|
||||||
|
<div class="bg-slate-100 dark:bg-slate-800 p-4 rounded-lg mb-4">
|
||||||
|
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">How to Use Custom Settings Merger</h3>
|
||||||
|
<ol class="list-decimal list-inside space-y-2 text-sm text-gray-700 dark:text-gray-300">
|
||||||
|
<li>Generate a license key file using the Key Generator tab</li>
|
||||||
|
<li>Run MobaXterm with the <code class="bg-slate-200 dark:bg-slate-700 px-1 py-0.5 rounded">-customizer</code> parameter: <br>
|
||||||
|
<code class="bg-slate-200 dark:bg-slate-700 px-2 py-1 rounded block mt-1">.\MobaXterm.exe -customizer</code>
|
||||||
|
</li>
|
||||||
|
<li>Export your custom settings to a file named <code class="bg-slate-200 dark:bg-slate-700 px-1 py-0.5 rounded">MobaXterm customization.custom</code></li>
|
||||||
|
<li>Upload both your license key file and custom settings file below</li>
|
||||||
|
<li>Click "Merge Files" to create a combined activation file</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="licenseFileInput" class="block text-lg font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||||
|
License Key File (Custom.mxtpro):
|
||||||
|
</label>
|
||||||
|
<div class="relative">
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
id="licenseFileInput"
|
||||||
|
@change="handleLicenseFileUpload"
|
||||||
|
accept=".mxtpro"
|
||||||
|
class="block w-full text-sm text-gray-700 dark:text-gray-300
|
||||||
|
file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0
|
||||||
|
file:text-sm file:font-semibold
|
||||||
|
file:bg-primary-50 file:text-primary-700
|
||||||
|
hover:file:bg-primary-100 hover:file:text-primary-800
|
||||||
|
focus:outline-none focus:border-primary-500 focus:ring-2 focus:ring-primary-200
|
||||||
|
transition-colors duration-200
|
||||||
|
dark:file:bg-slate-700 dark:file:text-slate-100
|
||||||
|
dark:hover:file:bg-slate-600 dark:hover:file:text-white"
|
||||||
|
/>
|
||||||
|
<p v-if="errors.licenseFile" class="mt-1 text-red-500 text-sm">{{ errors.licenseFile }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="customSettingsFileInput" class="block text-lg text-gray-700 dark:text-gray-300">Custom Settings File (.custom):</label>
|
||||||
|
<input type="file" id="customSettingsFileInput" @change="handleCustomSettingsFileUpload" accept=".custom" class="block w-full text-sm text-gray-700 dark:text-gray-300
|
||||||
|
file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0
|
||||||
|
file:text-sm file:font-semibold
|
||||||
|
file:bg-primary-50 file:text-primary-700
|
||||||
|
hover:file:bg-primary-100 hover:file:text-primary-800
|
||||||
|
focus:outline-none focus:border-primary-500 focus:ring-2 focus:ring-primary-200
|
||||||
|
transition-colors duration-200
|
||||||
|
dark:file:bg-slate-700 dark:file:text-slate-100
|
||||||
|
dark:hover:file:bg-slate-600 dark:hover:file:text-white" />
|
||||||
|
<p v-if="errors.customSettingsFile" class="mt-1 text-red-500 text-sm">{{ errors.customSettingsFile }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center pt-4">
|
||||||
|
<button @click="mergeFiles" :disabled="!licenseFile || !customSettingsFile" class="w-full sm:w-auto px-6 py-3 bg-primary-600 text-white rounded-lg shadow-md hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors duration-200 disabled:bg-gray-400 disabled:cursor-not-allowed"> Merge Files </button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<footer class="mt-8 pt-6 border-t border-slate-200 dark:border-slate-700">
|
||||||
|
<div class="flex flex-col items-center space-y-4">
|
||||||
|
<div class="flex items-center space-x-2">
|
||||||
|
<span class="text-sm text-slate-600 dark:text-slate-400">Created with</span>
|
||||||
|
<span class="animate-pulse text-red-500">❤</span>
|
||||||
|
<span class="text-sm text-slate-600 dark:text-slate-400">by</span>
|
||||||
|
<span class="text-sm font-semibold bg-clip-text text-transparent bg-gradient-to-r from-purple-500 to-pink-500"> Zarfala </span>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-slate-600 dark:text-slate-400" style="margin-top: 0;"> UI/UX Design optimized for <span class="inline-block">
|
||||||
|
<span class="text-blue-500 font-semibold">Computer</span>
|
||||||
|
<span class="text-green-500 font-semibold">& Mobile</span>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<div class="text-xs text-slate-500 dark:text-slate-500" style="margin-top: 5px;"> v2.5 © 2025 All rights reserved </div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Toast notification -->
|
||||||
|
<div id="toast" class="fixed bottom-4 right-4 px-4 py-2 rounded-lg bg-green-500 text-white transform translate-y-16 opacity-0 transition-all duration-300 z-50 hidden">
|
||||||
|
License generated successfully!
|
||||||
|
</div>
|
||||||
|
<!-- Scripts -->
|
||||||
|
<script src="./js/vue.min-2.6.12.js"></script>
|
||||||
|
<script src="./js/FileSaver.js"></script>
|
||||||
|
<script src="./js/jszip.js"></script>
|
||||||
|
<script src="./js/fire.js"></script>
|
||||||
|
<script src="./js/alert.js"></script>
|
||||||
|
<script>
|
||||||
|
// Preloader functionality
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
// Hide preloader
|
||||||
|
setTimeout(function() {
|
||||||
|
const preloader = document.getElementById('preloader');
|
||||||
|
const mainContent = document.getElementById('main-content');
|
||||||
|
|
||||||
|
preloader.classList.add('fade-out');
|
||||||
|
mainContent.classList.remove('content-hidden');
|
||||||
|
mainContent.classList.add('content-visible');
|
||||||
|
|
||||||
|
// Remove preloader from DOM after transition completes
|
||||||
|
setTimeout(function() {
|
||||||
|
preloader.style.display = 'none';
|
||||||
|
}, 500);
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Theme toggle functionality
|
||||||
|
function toggleTheme() {
|
||||||
|
if (document.documentElement.classList.contains('dark')) {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
localStorage.theme = 'light';
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
localStorage.theme = 'dark';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for saved theme preference or prefer-color-scheme
|
||||||
|
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
||||||
|
document.documentElement.classList.add('dark');
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove('dark');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toast notification function
|
||||||
|
function showToast(message, type = 'success') {
|
||||||
|
const toast = document.getElementById('toast');
|
||||||
|
toast.textContent = message;
|
||||||
|
toast.classList.remove('hidden');
|
||||||
|
|
||||||
|
if (type === 'success') {
|
||||||
|
toast.classList.add('bg-green-500');
|
||||||
|
toast.classList.remove('bg-red-500');
|
||||||
|
} else {
|
||||||
|
toast.classList.add('bg-red-500');
|
||||||
|
toast.classList.remove('bg-green-500');
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.classList.remove('translate-y-16', 'opacity-0');
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.classList.add('translate-y-16', 'opacity-0');
|
||||||
|
setTimeout(() => {
|
||||||
|
toast.classList.add('hidden');
|
||||||
|
}, 300);
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="module">
|
||||||
|
import {
|
||||||
|
LicenseType,
|
||||||
|
generateLicense
|
||||||
|
} from './js/mobaXtermGenerater.js'
|
||||||
|
import {
|
||||||
|
mergeZipFiles
|
||||||
|
} from './js/mergeZipFiles.js'
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: '#app',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
LICENSE_TYPES: LicenseType,
|
||||||
|
licenseType: '',
|
||||||
|
userName: '',
|
||||||
|
versionName: '',
|
||||||
|
userNum: '',
|
||||||
|
activeTab: 'keyGenerator',
|
||||||
|
licenseFile: null,
|
||||||
|
customSettingsFile: null,
|
||||||
|
errors: {
|
||||||
|
licenseType: '',
|
||||||
|
userName: '',
|
||||||
|
versionName: '',
|
||||||
|
userNum: '',
|
||||||
|
licenseFile: '',
|
||||||
|
customSettingsFile: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
validateLicenseType() {
|
||||||
|
if (!this.licenseType) {
|
||||||
|
this.errors.licenseType = 'Please select an edition';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.errors.licenseType = '';
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
validateUserName() {
|
||||||
|
if (!this.userName) {
|
||||||
|
this.errors.userName = 'Username is required';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const regex = /^[a-zA-Z]+$/;
|
||||||
|
if (!regex.test(this.userName)) {
|
||||||
|
this.errors.userName = 'Only letters are allowed (no spaces, numbers or special characters)';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.errors.userName = '';
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
validateVersion() {
|
||||||
|
if (!this.versionName) {
|
||||||
|
this.errors.versionName = 'Version is required';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const regex = /^[1-9][0-9]*\.?\d{0,1}$/;
|
||||||
|
if (!regex.test(this.versionName)) {
|
||||||
|
this.errors.versionName = 'Enter a valid version format (e.g., 25.3)';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if version is supported
|
||||||
|
const majorVersion = parseInt(this.versionName.split('.')[0]);
|
||||||
|
if (majorVersion !== 20 && majorVersion !== 25) {
|
||||||
|
this.errors.versionName = 'Currently only versions 20.X and 25.X are supported';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.errors.versionName = '';
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
validateUserNum() {
|
||||||
|
if (!this.userNum) {
|
||||||
|
this.errors.userNum = 'Number of users is required';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const regex = /^[1-9]+\d*$/;
|
||||||
|
if (!regex.test(this.userNum)) {
|
||||||
|
this.errors.userNum = 'Enter a valid number greater than 0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.errors.userNum = '';
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
validateAndGenerate() {
|
||||||
|
// Validate all fields
|
||||||
|
const isLicenseTypeValid = this.validateLicenseType();
|
||||||
|
const isUserNameValid = this.validateUserName();
|
||||||
|
const isVersionValid = this.validateVersion();
|
||||||
|
const isUserNumValid = this.validateUserNum();
|
||||||
|
|
||||||
|
// Only generate if all validations pass
|
||||||
|
if (isLicenseTypeValid && isUserNameValid && isVersionValid && isUserNumValid) {
|
||||||
|
try {
|
||||||
|
let versionNameArr = this.versionName.split('.');
|
||||||
|
const majorVersion = parseInt(versionNameArr[0]);
|
||||||
|
const minorVersion = versionNameArr.length === 2 ? (parseInt(versionNameArr[1]) || 0) : 0;
|
||||||
|
|
||||||
|
let licenseStr = generateLicense(this.licenseType, this.userName, this.userNum, majorVersion, minorVersion);
|
||||||
|
this.generateLicenseFile(licenseStr);
|
||||||
|
showToast('License generated successfully!', 'success');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error generating license:', error);
|
||||||
|
showToast('Error generating license. Please try again.', 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
generateLicenseFile(licenseStr) {
|
||||||
|
let zip = new JSZip();
|
||||||
|
zip.file("Pro.key", licenseStr);
|
||||||
|
zip.generateAsync({
|
||||||
|
type: "blob"
|
||||||
|
}).then(function(content) {
|
||||||
|
saveAs(content, "Custom.mxtpro");
|
||||||
|
}).catch(function(error) {
|
||||||
|
console.error('Error creating zip file:', error);
|
||||||
|
showToast('Error creating license file. Please try again.', 'error');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleLicenseFileUpload(event) {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
if (file.name.toLowerCase().endsWith('.mxtpro')) {
|
||||||
|
this.licenseFile = file;
|
||||||
|
this.errors.licenseFile = '';
|
||||||
|
} else {
|
||||||
|
this.licenseFile = null;
|
||||||
|
this.errors.licenseFile = 'Please select a valid .mxtpro file';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleCustomSettingsFileUpload(event) {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
if (file.name.toLowerCase().endsWith('.custom')) {
|
||||||
|
this.customSettingsFile = file;
|
||||||
|
this.errors.customSettingsFile = '';
|
||||||
|
} else {
|
||||||
|
this.customSettingsFile = null;
|
||||||
|
this.errors.customSettingsFile = 'Please select a valid .custom file';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mergeFiles() {
|
||||||
|
if (!this.licenseFile || !this.customSettingsFile) {
|
||||||
|
showToast('Please upload both required files', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeZipFiles(this.licenseFile, this.customSettingsFile)
|
||||||
|
.then((mergedContent) => {
|
||||||
|
saveAs(mergedContent, "Custom.mxtpro");
|
||||||
|
showToast('Files merged successfully!', 'success');
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error merging files:', error);
|
||||||
|
showToast('Error merging files. Please try again.', 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// Set default version to 25.3
|
||||||
|
this.versionName = '25.3';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+188
@@ -0,0 +1,188 @@
|
|||||||
|
(function (global, factory) {
|
||||||
|
if (typeof define === "function" && define.amd) {
|
||||||
|
define([], factory);
|
||||||
|
} else if (typeof exports !== "undefined") {
|
||||||
|
factory();
|
||||||
|
} else {
|
||||||
|
var mod = {
|
||||||
|
exports: {}
|
||||||
|
};
|
||||||
|
factory();
|
||||||
|
global.FileSaver = mod.exports;
|
||||||
|
}
|
||||||
|
})(this, function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FileSaver.js
|
||||||
|
* A saveAs() FileSaver implementation.
|
||||||
|
*
|
||||||
|
* By Eli Grey, http://eligrey.com
|
||||||
|
*
|
||||||
|
* License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT)
|
||||||
|
* source : http://purl.eligrey.com/github/FileSaver.js
|
||||||
|
*/
|
||||||
|
// The one and only way of getting global scope in all environments
|
||||||
|
// https://stackoverflow.com/q/3277182/1008999
|
||||||
|
var _global = typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : typeof global === 'object' && global.global === global ? global : void 0;
|
||||||
|
|
||||||
|
function bom(blob, opts) {
|
||||||
|
if (typeof opts === 'undefined') opts = {
|
||||||
|
autoBom: false
|
||||||
|
};else if (typeof opts !== 'object') {
|
||||||
|
console.warn('Deprecated: Expected third argument to be a object');
|
||||||
|
opts = {
|
||||||
|
autoBom: !opts
|
||||||
|
};
|
||||||
|
} // prepend BOM for UTF-8 XML and text/* types (including HTML)
|
||||||
|
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
|
||||||
|
|
||||||
|
if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
|
||||||
|
return new Blob([String.fromCharCode(0xFEFF), blob], {
|
||||||
|
type: blob.type
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
function download(url, name, opts) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', url);
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
|
||||||
|
xhr.onload = function () {
|
||||||
|
saveAs(xhr.response, name, opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function () {
|
||||||
|
console.error('could not download file');
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function corsEnabled(url) {
|
||||||
|
var xhr = new XMLHttpRequest(); // use sync to avoid popup blocker
|
||||||
|
|
||||||
|
xhr.open('HEAD', url, false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
xhr.send();
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
return xhr.status >= 200 && xhr.status <= 299;
|
||||||
|
} // `a.click()` doesn't work for all browsers (#465)
|
||||||
|
|
||||||
|
|
||||||
|
function click(node) {
|
||||||
|
try {
|
||||||
|
node.dispatchEvent(new MouseEvent('click'));
|
||||||
|
} catch (e) {
|
||||||
|
var evt = document.createEvent('MouseEvents');
|
||||||
|
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null);
|
||||||
|
node.dispatchEvent(evt);
|
||||||
|
}
|
||||||
|
} // Detect WebView inside a native macOS app by ruling out all browsers
|
||||||
|
// We just need to check for 'Safari' because all other browsers (besides Firefox) include that too
|
||||||
|
// https://www.whatismybrowser.com/guides/the-latest-user-agent/macos
|
||||||
|
|
||||||
|
|
||||||
|
var isMacOSWebView = /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent);
|
||||||
|
var saveAs = _global.saveAs || ( // probably in some web worker
|
||||||
|
typeof window !== 'object' || window !== _global ? function saveAs() {}
|
||||||
|
/* noop */
|
||||||
|
// Use download attribute first if possible (#193 Lumia mobile) unless this is a macOS WebView
|
||||||
|
: 'download' in HTMLAnchorElement.prototype && !isMacOSWebView ? function saveAs(blob, name, opts) {
|
||||||
|
var URL = _global.URL || _global.webkitURL;
|
||||||
|
var a = document.createElement('a');
|
||||||
|
name = name || blob.name || 'download';
|
||||||
|
a.download = name;
|
||||||
|
a.rel = 'noopener'; // tabnabbing
|
||||||
|
// TODO: detect chrome extensions & packaged apps
|
||||||
|
// a.target = '_blank'
|
||||||
|
|
||||||
|
if (typeof blob === 'string') {
|
||||||
|
// Support regular links
|
||||||
|
a.href = blob;
|
||||||
|
|
||||||
|
if (a.origin !== location.origin) {
|
||||||
|
corsEnabled(a.href) ? download(blob, name, opts) : click(a, a.target = '_blank');
|
||||||
|
} else {
|
||||||
|
click(a);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Support blobs
|
||||||
|
a.href = URL.createObjectURL(blob);
|
||||||
|
setTimeout(function () {
|
||||||
|
URL.revokeObjectURL(a.href);
|
||||||
|
}, 4E4); // 40s
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
click(a);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
} // Use msSaveOrOpenBlob as a second approach
|
||||||
|
: 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, opts) {
|
||||||
|
name = name || blob.name || 'download';
|
||||||
|
|
||||||
|
if (typeof blob === 'string') {
|
||||||
|
if (corsEnabled(blob)) {
|
||||||
|
download(blob, name, opts);
|
||||||
|
} else {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.href = blob;
|
||||||
|
a.target = '_blank';
|
||||||
|
setTimeout(function () {
|
||||||
|
click(a);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
navigator.msSaveOrOpenBlob(bom(blob, opts), name);
|
||||||
|
}
|
||||||
|
} // Fallback to using FileReader and a popup
|
||||||
|
: function saveAs(blob, name, opts, popup) {
|
||||||
|
// Open a popup immediately do go around popup blocker
|
||||||
|
// Mostly only available on user interaction and the fileReader is async so...
|
||||||
|
popup = popup || open('', '_blank');
|
||||||
|
|
||||||
|
if (popup) {
|
||||||
|
popup.document.title = popup.document.body.innerText = 'downloading...';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof blob === 'string') return download(blob, name, opts);
|
||||||
|
var force = blob.type === 'application/octet-stream';
|
||||||
|
|
||||||
|
var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari;
|
||||||
|
|
||||||
|
var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent);
|
||||||
|
|
||||||
|
if ((isChromeIOS || force && isSafari || isMacOSWebView) && typeof FileReader !== 'undefined') {
|
||||||
|
// Safari doesn't allow downloading of blob URLs
|
||||||
|
var reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onloadend = function () {
|
||||||
|
var url = reader.result;
|
||||||
|
url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;');
|
||||||
|
if (popup) popup.location.href = url;else location = url;
|
||||||
|
popup = null; // reverse-tabnabbing #460
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsDataURL(blob);
|
||||||
|
} else {
|
||||||
|
var URL = _global.URL || _global.webkitURL;
|
||||||
|
var url = URL.createObjectURL(blob);
|
||||||
|
if (popup) popup.location = url;else location.href = url;
|
||||||
|
popup = null; // reverse-tabnabbing #460
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
}, 4E4); // 40s
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_global.saveAs = saveAs.saveAs = saveAs;
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined') {
|
||||||
|
module.exports = saveAs;
|
||||||
|
}
|
||||||
|
});
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
var estiloConsola = `
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: "Courier New", monospace;
|
||||||
|
color: red;
|
||||||
|
white-space: pre;
|
||||||
|
`;
|
||||||
|
|
||||||
|
var estiloZarfala = `
|
||||||
|
color: red;
|
||||||
|
white-space: pre;
|
||||||
|
`;
|
||||||
|
|
||||||
|
var mensajeZarfala = `
|
||||||
|
@@@@@@@@ @@@@@@ @@@@@@@ @@@@@@@@ @@@@@@ @@@ @@@@@@
|
||||||
|
@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@@ @@@ @@@@@@@@
|
||||||
|
@@! @@! @@@ @@! @@@ @@! @@! @@@ @@! @@! @@@
|
||||||
|
!@! !@! @!@ !@! @!@ !@! !@! @!@ !@! !@! @!@
|
||||||
|
@!! @!@!@!@! @!@!!@! @!!!:! @!@!@!@! @!! @!@!@!@!
|
||||||
|
!!! !!!@!!!! !!@!@! !!!!!: !!!@!!!! !!! !!!@!!!!
|
||||||
|
!!: !!: !!! !!: :!! !!: !!: !!! !!: !!: !!!
|
||||||
|
:!: :!: !:! :!: !:! :!: :!: !:! :!: :!: !:!
|
||||||
|
:: :::: :: ::: :: ::: :: :: ::: :: :::: :: :::
|
||||||
|
: :: : : : : : : : : : : : : : :: : : : : :
|
||||||
|
`;
|
||||||
|
|
||||||
|
function mostrarMensaje() {
|
||||||
|
console.clear();
|
||||||
|
console.log('%c' + mensajeZarfala, estiloZarfala);
|
||||||
|
console.log("%cSTOP!", "color:red;font-size:xx-large;font-weight:bold;"),
|
||||||
|
console.log(`%cThis is a browser feature intended for developers. Do not enter or paste code which you don't understand. It may allow attackers to steal your information or impersonate you. See https://en.wikipedia.org/wiki/Self-XSS for more details`, "font-size:large;"),
|
||||||
|
localStorage.do_NOT_share_jwt || localStorage.setItem("do_NOT_share_jwt", "do NOT share the JWT value. someone could steal your account");
|
||||||
|
}
|
||||||
|
|
||||||
|
var intermitente = true;
|
||||||
|
setInterval(function () {
|
||||||
|
mostrarMensaje();
|
||||||
|
intermitente = !intermitente;
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
mostrarMensaje();
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
function toggleTheme() {
|
||||||
|
if (document.body.classList.contains("dark"))
|
||||||
|
document.body.classList.remove("dark");
|
||||||
|
else
|
||||||
|
document.body.classList.add("dark");
|
||||||
|
}
|
||||||
+30
File diff suppressed because one or more lines are too long
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* Utility to merge MobaXterm key file with custom settings file
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges a custom settings file with the license file
|
||||||
|
* @param {Blob} licenseFile - The Custom.mxtpro license file (which is a ZIP containing Pro.key)
|
||||||
|
* @param {Blob} customSettingsFile - The MobaXterm customization.custom file (which is a ZIP with settings)
|
||||||
|
* @returns {Promise<Blob>} - A promise that resolves to the merged ZIP file
|
||||||
|
*/
|
||||||
|
function mergeZipFiles(licenseFile, customSettingsFile) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Create a new JSZip instance for the merged result
|
||||||
|
const mergedZip = new JSZip();
|
||||||
|
const licenseZip = new JSZip();
|
||||||
|
const settingsZip = new JSZip();
|
||||||
|
|
||||||
|
// First load the license file
|
||||||
|
licenseZip.loadAsync(licenseFile)
|
||||||
|
.then((licenseContents) => {
|
||||||
|
// Then load the custom settings file
|
||||||
|
return settingsZip.loadAsync(customSettingsFile)
|
||||||
|
.then((settingsContents) => {
|
||||||
|
// Get the Pro.key file from license ZIP
|
||||||
|
return licenseContents.file("Pro.key").async("string")
|
||||||
|
.then((proKeyContent) => {
|
||||||
|
// Add the Pro.key to the merged zip
|
||||||
|
mergedZip.file("Pro.key", proKeyContent);
|
||||||
|
|
||||||
|
// Add all files from the custom settings ZIP
|
||||||
|
const promises = [];
|
||||||
|
settingsContents.forEach((relativePath, file) => {
|
||||||
|
if (!file.dir) {
|
||||||
|
const promise = file.async("blob").then((content) => {
|
||||||
|
mergedZip.file(relativePath, content);
|
||||||
|
});
|
||||||
|
promises.push(promise);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promises).then(() => {
|
||||||
|
// Generate the final merged ZIP file
|
||||||
|
return mergedZip.generateAsync({type: "blob"});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((mergedContent) => {
|
||||||
|
resolve(mergedContent);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error merging ZIP files:", error);
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export { mergeZipFiles };
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
const VariantBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split('');
|
||||||
|
const VariantBase64Dict = {};
|
||||||
|
VariantBase64Table.forEach((val, i) => VariantBase64Dict[i] = val);
|
||||||
|
const VariantBase64ReverseDict = {};
|
||||||
|
VariantBase64Table.forEach((val, i) => VariantBase64ReverseDict[val] = i);
|
||||||
|
|
||||||
|
/** license type */
|
||||||
|
const LicenseType = {
|
||||||
|
Professional: 1,
|
||||||
|
Educational: 3,
|
||||||
|
Personal: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte[] is base64 encoded
|
||||||
|
* @param {array[Number]} bs
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function VariantBase64Encode(bs) {
|
||||||
|
let result = [];
|
||||||
|
let blocks_count = Math.floor(bs.length / 3);
|
||||||
|
let left_bytes = bs.length % 3;
|
||||||
|
|
||||||
|
let coding_int, block;
|
||||||
|
for (let i = 0; i < blocks_count; i++) {
|
||||||
|
coding_int = bs.slice(3 * i, 3 * i + 3).toInt();
|
||||||
|
//coding_int = int.from_bytes(bs[3 * i: 3 * i + 3], 'little');
|
||||||
|
block = VariantBase64Dict[coding_int & 0x3f];
|
||||||
|
block += VariantBase64Dict[(coding_int >> 6) & 0x3f];
|
||||||
|
block += VariantBase64Dict[(coding_int >> 12) & 0x3f];
|
||||||
|
block += VariantBase64Dict[(coding_int >> 18) & 0x3f];
|
||||||
|
result = result.concat(block.toBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (left_bytes) {
|
||||||
|
case 0:
|
||||||
|
return result;
|
||||||
|
case 1:
|
||||||
|
coding_int = bs.slice(3 * blocks_count).toInt();
|
||||||
|
block = VariantBase64Dict[coding_int & 0x3f];
|
||||||
|
block += VariantBase64Dict[(coding_int >> 6) & 0x3f];
|
||||||
|
result = result.concat(block.toBytes());
|
||||||
|
return result;
|
||||||
|
default:
|
||||||
|
coding_int = bs.slice(3 * blocks_count).toInt();
|
||||||
|
block = VariantBase64Dict[coding_int & 0x3f];
|
||||||
|
block += VariantBase64Dict[(coding_int >> 6) & 0x3f];
|
||||||
|
block += VariantBase64Dict[(coding_int >> 12) & 0x3f];
|
||||||
|
result = result.concat(block.toBytes());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function EncryptBytes(key, bs) {
|
||||||
|
let result = [];
|
||||||
|
bs.forEach(val => {
|
||||||
|
result.push(val ^ ((key >> 8) & 0xff))
|
||||||
|
key = result[-1] & key | 0x482D
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DecryptBytes(key, bs) {
|
||||||
|
let result = [];
|
||||||
|
bs.forEach(val => {
|
||||||
|
result.push(val ^ ((key >> 8) & 0xff));
|
||||||
|
key = val & key | 0x482D;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte[] to int for low before high byte[] Python3 in.from_bytes(byte[], 'little')
|
||||||
|
* @param {Number} offset Offset, default 0
|
||||||
|
* @returns byte[] converted to init
|
||||||
|
*/
|
||||||
|
Array.prototype.toInt = function (offset = 0) {
|
||||||
|
let value = ((this[offset] & 0xFF)
|
||||||
|
| ((this[offset + 1] & 0xFF) << 8)
|
||||||
|
| ((this[offset + 2] & 0xFF) << 16)
|
||||||
|
| ((this[offset + 3] & 0xFF) << 24)
|
||||||
|
);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte[] to string
|
||||||
|
*/
|
||||||
|
Array.prototype.bytesToStr = function () {
|
||||||
|
var str = '',
|
||||||
|
_arr = this;
|
||||||
|
for (var i = 0; i < _arr.length; i++) {
|
||||||
|
var one = _arr[i].toString(2),
|
||||||
|
v = one.match(/^1+?(?=0)/);
|
||||||
|
if (v && one.length == 8) {
|
||||||
|
var bytesLength = v[0].length;
|
||||||
|
var store = _arr[i].toString(2).slice(7 - bytesLength);
|
||||||
|
for (var st = 1; st < bytesLength; st++) {
|
||||||
|
store += _arr[st + i].toString(2).slice(2);
|
||||||
|
}
|
||||||
|
str += String.fromCharCode(parseInt(store, 2));
|
||||||
|
i += bytesLength - 1;
|
||||||
|
} else {
|
||||||
|
str += String.fromCharCode(_arr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String to btye[]
|
||||||
|
*/
|
||||||
|
String.prototype.toBytes = function () {
|
||||||
|
var bytes = new Array();
|
||||||
|
var len, char;
|
||||||
|
len = this.length;
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
char = this.charCodeAt(i);
|
||||||
|
if (char >= 0x010000 && char <= 0x10FFFF) {
|
||||||
|
bytes.push(((char >> 18) & 0x07) | 0xF0);
|
||||||
|
bytes.push(((char >> 12) & 0x3F) | 0x80);
|
||||||
|
bytes.push(((char >> 6) & 0x3F) | 0x80);
|
||||||
|
bytes.push((char & 0x3F) | 0x80);
|
||||||
|
} else if (char >= 0x000800 && char <= 0x00FFFF) {
|
||||||
|
bytes.push(((char >> 12) & 0x0F) | 0xE0);
|
||||||
|
bytes.push(((char >> 6) & 0x3F) | 0x80);
|
||||||
|
bytes.push((char & 0x3F) | 0x80);
|
||||||
|
} else if (char >= 0x000080 && char <= 0x0007FF) {
|
||||||
|
bytes.push(((char >> 6) & 0x1F) | 0xC0);
|
||||||
|
bytes.push((char & 0x3F) | 0x80);
|
||||||
|
} else {
|
||||||
|
bytes.push(char & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} type License Type
|
||||||
|
* @param {string} userName user ID
|
||||||
|
* @param {Number} count Number of users supported by license
|
||||||
|
* @param {Number} majorVersion Major version number e.g. 21.0 is 21
|
||||||
|
* @param {Number} minorVersion Minor version number e.g. 21.0 is 0.
|
||||||
|
*/
|
||||||
|
function generateLicense(type, userName, count, majorVersion, minorVersion) {
|
||||||
|
/*
|
||||||
|
LicenseString = '%d#%s|%d%d#%d#%d3%d6%d#%d#%d#%d#' % (
|
||||||
|
Type,
|
||||||
|
UserName,
|
||||||
|
MajorVersion, MinorVersion,
|
||||||
|
Count,
|
||||||
|
MajorVersion, MinorVersion, MinorVersion,
|
||||||
|
0, # Unknown
|
||||||
|
0, # No Games flag. 0 means "NoGames = false". But it does not work.
|
||||||
|
0) # No Plugins flag. 0 means "NoPlugins = false". But it does not work.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let licenseSourceStr = `${type}#${userName}|${majorVersion}${minorVersion}#${count}#${majorVersion}3${minorVersion}6${minorVersion}#0#0#0#`;
|
||||||
|
return VariantBase64Encode(EncryptBytes(0x787, licenseSourceStr.toBytes())).bytesToStr();
|
||||||
|
}
|
||||||
|
|
||||||
|
export { LicenseType, generateLicense }
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user