cleaning structure
133
old code/DATABASE_SETUP_README.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Quick Database Setup for Trasabilitate Application
|
||||
|
||||
This script provides a complete one-step database setup for quick deployment of the Trasabilitate application.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before running the setup script, ensure:
|
||||
|
||||
1. **MariaDB is installed and running**
|
||||
2. **Database and user are created**:
|
||||
```sql
|
||||
CREATE DATABASE trasabilitate;
|
||||
CREATE USER 'trasabilitate'@'localhost' IDENTIFIED BY 'Initial01!';
|
||||
GRANT ALL PRIVILEGES ON trasabilitate.* TO 'trasabilitate'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
3. **Python virtual environment is activated**:
|
||||
```bash
|
||||
source ../recticel/bin/activate
|
||||
```
|
||||
4. **Python dependencies are installed**:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Quick Setup (Recommended)
|
||||
```bash
|
||||
cd /srv/quality_recticel/py_app
|
||||
source ../recticel/bin/activate
|
||||
python3 app/db_create_scripts/setup_complete_database.py
|
||||
```
|
||||
|
||||
### What the script creates:
|
||||
|
||||
#### MariaDB Tables:
|
||||
- `scan1_orders` - Quality scanning data for process 1
|
||||
- `scanfg_orders` - Quality scanning data for finished goods
|
||||
- `order_for_labels` - Label printing orders
|
||||
- `warehouse_locations` - Warehouse location management
|
||||
- `permissions` - System permissions
|
||||
- `role_permissions` - Role-permission mappings
|
||||
- `role_hierarchy` - User role hierarchy
|
||||
- `permission_audit_log` - Permission change audit trail
|
||||
|
||||
#### Database Triggers:
|
||||
- Auto-increment approved/rejected quantities based on quality codes
|
||||
- Triggers for both scan1_orders and scanfg_orders tables
|
||||
|
||||
#### SQLite Tables:
|
||||
- `users` - User authentication (in instance/users.db)
|
||||
- `roles` - User roles (in instance/users.db)
|
||||
|
||||
#### Configuration:
|
||||
- Updates `instance/external_server.conf` with correct database settings
|
||||
- Creates default superadmin user (username: `superadmin`, password: `superadmin123`)
|
||||
|
||||
#### Permission System:
|
||||
- 7 user roles (superadmin, admin, manager, quality_manager, warehouse_manager, quality_worker, warehouse_worker)
|
||||
- 25+ granular permissions for different application areas
|
||||
- Complete role hierarchy with inheritance
|
||||
|
||||
## After Setup
|
||||
|
||||
1. **Start the application**:
|
||||
```bash
|
||||
python3 run.py
|
||||
```
|
||||
|
||||
2. **Access the application**:
|
||||
- Local: http://127.0.0.1:8781
|
||||
- Network: http://192.168.0.205:8781
|
||||
|
||||
3. **Login with superadmin**:
|
||||
- Username: `superadmin`
|
||||
- Password: `superadmin123`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues:
|
||||
|
||||
1. **Database connection failed**:
|
||||
- Check if MariaDB is running: `sudo systemctl status mariadb`
|
||||
- Verify database exists: `sudo mysql -e "SHOW DATABASES;"`
|
||||
- Check user privileges: `sudo mysql -e "SHOW GRANTS FOR 'trasabilitate'@'localhost';"`
|
||||
|
||||
2. **Import errors**:
|
||||
- Ensure virtual environment is activated
|
||||
- Install missing dependencies: `pip install -r requirements.txt`
|
||||
|
||||
3. **Permission denied**:
|
||||
- Make script executable: `chmod +x app/db_create_scripts/setup_complete_database.py`
|
||||
- Check file ownership: `ls -la app/db_create_scripts/`
|
||||
|
||||
### Manual Database Recreation:
|
||||
|
||||
If you need to completely reset the database:
|
||||
|
||||
```bash
|
||||
# Drop and recreate database
|
||||
sudo mysql -e "DROP DATABASE IF EXISTS trasabilitate; CREATE DATABASE trasabilitate; GRANT ALL PRIVILEGES ON trasabilitate.* TO 'trasabilitate'@'localhost'; FLUSH PRIVILEGES;"
|
||||
|
||||
# Remove SQLite database
|
||||
rm -f instance/users.db
|
||||
|
||||
# Run setup script
|
||||
python3 app/db_create_scripts/setup_complete_database.py
|
||||
```
|
||||
|
||||
## Script Features
|
||||
|
||||
- ✅ **Comprehensive**: Creates all necessary database structure
|
||||
- ✅ **Safe**: Uses `IF NOT EXISTS` clauses to prevent conflicts
|
||||
- ✅ **Verified**: Includes verification step to confirm setup
|
||||
- ✅ **Informative**: Detailed output showing each step
|
||||
- ✅ **Error handling**: Clear error messages and troubleshooting hints
|
||||
- ✅ **Idempotent**: Can be run multiple times safely
|
||||
|
||||
## Development Notes
|
||||
|
||||
The script combines functionality from these individual scripts:
|
||||
- `create_scan_1db.py`
|
||||
- `create_scanfg_orders.py`
|
||||
- `create_order_for_labels_table.py`
|
||||
- `create_warehouse_locations_table.py`
|
||||
- `create_permissions_tables.py`
|
||||
- `create_roles_table.py`
|
||||
- `create_triggers.py`
|
||||
- `create_triggers_fg.py`
|
||||
- `populate_permissions.py`
|
||||
|
||||
For development or debugging, you can still run individual scripts if needed.
|
||||
319
old code/DOCKER_DEPLOYMENT.md
Normal file
@@ -0,0 +1,319 @@
|
||||
# Recticel Quality Application - Docker Deployment Guide
|
||||
|
||||
## 📋 Overview
|
||||
|
||||
This is a complete Docker-based deployment solution for the Recticel Quality Application. It includes:
|
||||
- **Flask Web Application** (Python 3.10)
|
||||
- **MariaDB 11.3 Database** with automatic initialization
|
||||
- **Gunicorn WSGI Server** for production-ready performance
|
||||
- **Automatic database schema setup** using existing setup scripts
|
||||
- **Superadmin user seeding** for immediate access
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- Docker Engine 20.10+
|
||||
- Docker Compose 2.0+
|
||||
- At least 2GB free disk space
|
||||
- Ports 8781 and 3306 available (or customize in .env)
|
||||
|
||||
### 1. Clone and Prepare
|
||||
|
||||
```bash
|
||||
cd /srv/quality_recticel
|
||||
```
|
||||
|
||||
### 2. Configure Environment (Optional)
|
||||
|
||||
Create a `.env` file from the example:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Edit `.env` to customize settings:
|
||||
```env
|
||||
MYSQL_ROOT_PASSWORD=your_secure_root_password
|
||||
DB_PORT=3306
|
||||
APP_PORT=8781
|
||||
INIT_DB=true
|
||||
SEED_DB=true
|
||||
```
|
||||
|
||||
### 3. Build and Deploy
|
||||
|
||||
Start all services:
|
||||
|
||||
```bash
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
This will:
|
||||
1. ✅ Build the Flask application Docker image
|
||||
2. ✅ Pull MariaDB 11.3 image
|
||||
3. ✅ Create and initialize the database
|
||||
4. ✅ Run all database schema creation scripts
|
||||
5. ✅ Seed the superadmin user
|
||||
6. ✅ Start the web application on port 8781
|
||||
|
||||
### 4. Verify Deployment
|
||||
|
||||
Check service status:
|
||||
```bash
|
||||
docker-compose ps
|
||||
```
|
||||
|
||||
View logs:
|
||||
```bash
|
||||
# All services
|
||||
docker-compose logs -f
|
||||
|
||||
# Just the web app
|
||||
docker-compose logs -f web
|
||||
|
||||
# Just the database
|
||||
docker-compose logs -f db
|
||||
```
|
||||
|
||||
### 5. Access the Application
|
||||
|
||||
Open your browser and navigate to:
|
||||
```
|
||||
http://localhost:8781
|
||||
```
|
||||
|
||||
**Default Login:**
|
||||
- Username: `superadmin`
|
||||
- Password: `superadmin123`
|
||||
|
||||
## 🔧 Management Commands
|
||||
|
||||
### Start Services
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Stop Services
|
||||
```bash
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
### Stop and Remove All Data (including database)
|
||||
```bash
|
||||
docker-compose down -v
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
```bash
|
||||
docker-compose restart
|
||||
```
|
||||
|
||||
### View Real-time Logs
|
||||
```bash
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
### Rebuild After Code Changes
|
||||
```bash
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
### Access Database Console
|
||||
```bash
|
||||
docker-compose exec db mariadb -u trasabilitate -p trasabilitate
|
||||
# Password: Initial01!
|
||||
```
|
||||
|
||||
### Execute Commands in App Container
|
||||
```bash
|
||||
docker-compose exec web bash
|
||||
```
|
||||
|
||||
## 📁 Data Persistence
|
||||
|
||||
The following data is persisted across container restarts:
|
||||
|
||||
- **Database Data:** Stored in Docker volume `mariadb_data`
|
||||
- **Application Logs:** Mapped to `./logs` directory
|
||||
- **Instance Config:** Mapped to `./instance` directory
|
||||
|
||||
## 🔐 Security Considerations
|
||||
|
||||
### Production Deployment Checklist:
|
||||
|
||||
1. **Change Default Passwords:**
|
||||
- Update `MYSQL_ROOT_PASSWORD` in `.env`
|
||||
- Update database password in `docker-compose.yml`
|
||||
- Change superadmin password after first login
|
||||
|
||||
2. **Use Environment Variables:**
|
||||
- Never commit `.env` file to version control
|
||||
- Use secrets management for production
|
||||
|
||||
3. **Network Security:**
|
||||
- If database access from host is not needed, remove the port mapping:
|
||||
```yaml
|
||||
# Comment out in docker-compose.yml:
|
||||
# ports:
|
||||
# - "3306:3306"
|
||||
```
|
||||
|
||||
4. **SSL/TLS:**
|
||||
- Configure reverse proxy (nginx/traefik) for HTTPS
|
||||
- Update gunicorn SSL configuration if needed
|
||||
|
||||
5. **Firewall:**
|
||||
- Only expose necessary ports
|
||||
- Use firewall rules to restrict access
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Database Connection Issues
|
||||
|
||||
If the app can't connect to the database:
|
||||
|
||||
```bash
|
||||
# Check database health
|
||||
docker-compose exec db healthcheck.sh --connect
|
||||
|
||||
# Check database logs
|
||||
docker-compose logs db
|
||||
|
||||
# Verify database is accessible
|
||||
docker-compose exec db mariadb -u trasabilitate -p -e "SHOW DATABASES;"
|
||||
```
|
||||
|
||||
### Application Not Starting
|
||||
|
||||
```bash
|
||||
# Check application logs
|
||||
docker-compose logs web
|
||||
|
||||
# Verify database initialization
|
||||
docker-compose exec web python3 -c "import mariadb; print('MariaDB module OK')"
|
||||
|
||||
# Restart with fresh initialization
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
If port 8781 or 3306 is already in use, edit `.env`:
|
||||
|
||||
```env
|
||||
APP_PORT=8782
|
||||
DB_PORT=3307
|
||||
```
|
||||
|
||||
Then restart:
|
||||
```bash
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Reset Everything
|
||||
|
||||
To start completely fresh:
|
||||
|
||||
```bash
|
||||
# Stop and remove all containers, networks, and volumes
|
||||
docker-compose down -v
|
||||
|
||||
# Remove any local data
|
||||
rm -rf logs/* instance/external_server.conf
|
||||
|
||||
# Start fresh
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
## 🔄 Updating the Application
|
||||
|
||||
### Update Application Code
|
||||
|
||||
1. Make your code changes
|
||||
2. Rebuild and restart:
|
||||
```bash
|
||||
docker-compose up -d --build web
|
||||
```
|
||||
|
||||
### Update Database Schema
|
||||
|
||||
If you need to run migrations or schema updates:
|
||||
|
||||
```bash
|
||||
docker-compose exec web python3 /app/app/db_create_scripts/setup_complete_database.py
|
||||
```
|
||||
|
||||
## 📊 Monitoring
|
||||
|
||||
### Health Checks
|
||||
|
||||
Both services have health checks configured:
|
||||
|
||||
```bash
|
||||
# Check overall status
|
||||
docker-compose ps
|
||||
|
||||
# Detailed health status
|
||||
docker inspect recticel-app | grep -A 10 Health
|
||||
docker inspect recticel-db | grep -A 10 Health
|
||||
```
|
||||
|
||||
### Resource Usage
|
||||
|
||||
```bash
|
||||
# View resource consumption
|
||||
docker stats recticel-app recticel-db
|
||||
```
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ Docker Compose Network │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌─────────────┐ │
|
||||
│ │ MariaDB │ │ Flask App │ │
|
||||
│ │ Container │◄─┤ Container │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ Port: 3306 │ │ Port: 8781 │ │
|
||||
│ └──────┬───────┘ └──────┬──────┘ │
|
||||
│ │ │ │
|
||||
└─────────┼─────────────────┼─────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
[Volume: [Logs &
|
||||
mariadb_data] Instance]
|
||||
```
|
||||
|
||||
## 📝 Environment Variables
|
||||
|
||||
### Database Configuration
|
||||
- `MYSQL_ROOT_PASSWORD`: MariaDB root password
|
||||
- `DB_HOST`: Database hostname (default: `db`)
|
||||
- `DB_PORT`: Database port (default: `3306`)
|
||||
- `DB_NAME`: Database name (default: `trasabilitate`)
|
||||
- `DB_USER`: Database user (default: `trasabilitate`)
|
||||
- `DB_PASSWORD`: Database password (default: `Initial01!`)
|
||||
|
||||
### Application Configuration
|
||||
- `FLASK_ENV`: Flask environment (default: `production`)
|
||||
- `FLASK_APP`: Flask app entry point (default: `run.py`)
|
||||
- `APP_PORT`: Application port (default: `8781`)
|
||||
|
||||
### Initialization Flags
|
||||
- `INIT_DB`: Run database initialization (default: `true`)
|
||||
- `SEED_DB`: Seed superadmin user (default: `true`)
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
For issues or questions:
|
||||
1. Check the logs: `docker-compose logs -f`
|
||||
2. Verify environment configuration
|
||||
3. Ensure all prerequisites are met
|
||||
4. Review this documentation
|
||||
|
||||
## 📄 License
|
||||
|
||||
[Your License Here]
|
||||
346
old code/DOCKER_SOLUTION_SUMMARY.md
Normal file
@@ -0,0 +1,346 @@
|
||||
# Recticel Quality Application - Docker Solution Summary
|
||||
|
||||
## 📦 What Has Been Created
|
||||
|
||||
A complete, production-ready Docker deployment solution for your Recticel Quality Application with the following components:
|
||||
|
||||
### Core Files Created
|
||||
|
||||
1. **`Dockerfile`** - Multi-stage Flask application container
|
||||
- Based on Python 3.10-slim
|
||||
- Installs all dependencies from requirements.txt
|
||||
- Configures Gunicorn WSGI server
|
||||
- Exposes port 8781
|
||||
|
||||
2. **`docker-compose.yml`** - Complete orchestration configuration
|
||||
- MariaDB 11.3 database service
|
||||
- Flask web application service
|
||||
- Automatic networking between services
|
||||
- Health checks for both services
|
||||
- Volume persistence for database and logs
|
||||
|
||||
3. **`docker-entrypoint.sh`** - Smart initialization script
|
||||
- Waits for database to be ready
|
||||
- Creates database configuration file
|
||||
- Runs database schema initialization
|
||||
- Seeds superadmin user
|
||||
- Starts the application
|
||||
|
||||
4. **`init-db.sql`** - MariaDB initialization
|
||||
- Creates database and user
|
||||
- Sets up permissions automatically
|
||||
|
||||
5. **`.env.example`** - Configuration template
|
||||
- Database passwords
|
||||
- Port configurations
|
||||
- Initialization flags
|
||||
|
||||
6. **`.dockerignore`** - Build optimization
|
||||
- Excludes unnecessary files from Docker image
|
||||
- Reduces image size
|
||||
|
||||
7. **`deploy.sh`** - One-command deployment script
|
||||
- Checks prerequisites
|
||||
- Creates configuration
|
||||
- Builds and starts services
|
||||
- Shows deployment status
|
||||
|
||||
8. **`Makefile`** - Convenient management commands
|
||||
- `make install` - First-time installation
|
||||
- `make up` - Start services
|
||||
- `make down` - Stop services
|
||||
- `make logs` - View logs
|
||||
- `make shell` - Access container
|
||||
- `make backup-db` - Backup database
|
||||
- And many more...
|
||||
|
||||
9. **`DOCKER_DEPLOYMENT.md`** - Complete documentation
|
||||
- Quick start guide
|
||||
- Management commands
|
||||
- Troubleshooting
|
||||
- Security considerations
|
||||
- Architecture diagrams
|
||||
|
||||
### Enhanced Files
|
||||
|
||||
10. **`setup_complete_database.py`** - Updated to support Docker
|
||||
- Now reads from environment variables
|
||||
- Fallback to config file for non-Docker deployments
|
||||
- Maintains backward compatibility
|
||||
|
||||
## 🎯 Key Features
|
||||
|
||||
### 1. Single-Command Deployment
|
||||
```bash
|
||||
./deploy.sh
|
||||
```
|
||||
This single command will:
|
||||
- ✅ Build Docker images
|
||||
- ✅ Create MariaDB database
|
||||
- ✅ Initialize all database tables and triggers
|
||||
- ✅ Seed superadmin user
|
||||
- ✅ Start the application
|
||||
|
||||
### 2. Complete Isolation
|
||||
- Application runs in its own container
|
||||
- Database runs in its own container
|
||||
- No system dependencies needed except Docker
|
||||
- No Python/MariaDB installation on host required
|
||||
|
||||
### 3. Data Persistence
|
||||
- Database data persists across restarts (Docker volume)
|
||||
- Application logs accessible on host
|
||||
- Configuration preserved
|
||||
|
||||
### 4. Production Ready
|
||||
- Gunicorn WSGI server (not Flask dev server)
|
||||
- Health checks for monitoring
|
||||
- Automatic restart on failure
|
||||
- Proper logging configuration
|
||||
- Resource isolation
|
||||
|
||||
### 5. Easy Management
|
||||
```bash
|
||||
# Start
|
||||
docker compose up -d
|
||||
|
||||
# Stop
|
||||
docker compose down
|
||||
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# Backup database
|
||||
make backup-db
|
||||
|
||||
# Restore database
|
||||
make restore-db BACKUP=backup_20231215.sql
|
||||
|
||||
# Access shell
|
||||
make shell
|
||||
|
||||
# Complete reset
|
||||
make reset
|
||||
```
|
||||
|
||||
## 🚀 Deployment Options
|
||||
|
||||
### Option 1: Quick Deploy (Recommended for Testing)
|
||||
```bash
|
||||
cd /srv/quality_recticel
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
### Option 2: Using Makefile (Recommended for Management)
|
||||
```bash
|
||||
cd /srv/quality_recticel
|
||||
make install # First time only
|
||||
make up # Start services
|
||||
make logs # Monitor
|
||||
```
|
||||
|
||||
### Option 3: Using Docker Compose Directly
|
||||
```bash
|
||||
cd /srv/quality_recticel
|
||||
cp .env.example .env
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## 📋 Prerequisites
|
||||
|
||||
The deployment **requires** Docker to be installed on the target system:
|
||||
|
||||
### Installing Docker on Ubuntu/Debian:
|
||||
```bash
|
||||
# Update package index
|
||||
sudo apt-get update
|
||||
|
||||
# Install dependencies
|
||||
sudo apt-get install -y ca-certificates curl gnupg
|
||||
|
||||
# Add Docker's official GPG key
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.gpg
|
||||
|
||||
# Set up the repository
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
|
||||
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
|
||||
# Install Docker Engine
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
|
||||
# Add current user to docker group (optional, to run without sudo)
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
After installation, log out and back in for group changes to take effect.
|
||||
|
||||
### Installing Docker on CentOS/RHEL:
|
||||
```bash
|
||||
sudo yum install -y yum-utils
|
||||
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────┐
|
||||
│ Docker Compose Stack │
|
||||
│ │
|
||||
│ ┌────────────────────┐ ┌───────────────────┐ │
|
||||
│ │ MariaDB 11.3 │ │ Flask App │ │
|
||||
│ │ Container │◄─────┤ Container │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ - Port: 3306 │ │ - Port: 8781 │ │
|
||||
│ │ - Volume: DB Data │ │ - Gunicorn WSGI │ │
|
||||
│ │ - Auto Init │ │ - Python 3.10 │ │
|
||||
│ │ - Health Checks │ │ - Health Checks │ │
|
||||
│ └──────────┬─────────┘ └─────────┬─────────┘ │
|
||||
│ │ │ │
|
||||
└─────────────┼──────────────────────────┼─────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
[mariadb_data] [logs directory]
|
||||
Docker Volume Host filesystem
|
||||
```
|
||||
|
||||
## 🔐 Security Features
|
||||
|
||||
1. **Database Isolation**: Database not exposed to host by default (can be configured)
|
||||
2. **Password Management**: All passwords in `.env` file (not committed to git)
|
||||
3. **User Permissions**: Proper MariaDB user with limited privileges
|
||||
4. **Network Isolation**: Services communicate on private Docker network
|
||||
5. **Production Mode**: Flask runs in production mode with Gunicorn
|
||||
|
||||
## 📊 What Gets Deployed
|
||||
|
||||
### Database Schema
|
||||
All tables from `setup_complete_database.py`:
|
||||
- `scan1_orders` - First scan orders
|
||||
- `scanfg_orders` - Final goods scan orders
|
||||
- `order_for_labels` - Label orders
|
||||
- `warehouse_locations` - Warehouse locations
|
||||
- `permissions` - Permission system
|
||||
- `role_permissions` - Role-based access
|
||||
- `role_hierarchy` - Role hierarchy
|
||||
- `permission_audit_log` - Audit logging
|
||||
- Plus SQLAlchemy tables: `users`, `roles`
|
||||
|
||||
### Initial Data
|
||||
- Superadmin user: `superadmin` / `superadmin123`
|
||||
|
||||
### Application Features
|
||||
- Complete Flask web application
|
||||
- Gunicorn WSGI server (4-8 workers depending on CPU)
|
||||
- Static file serving
|
||||
- Session management
|
||||
- Database connection pooling
|
||||
|
||||
## 🔄 Migration from Existing Deployment
|
||||
|
||||
If you have an existing non-Docker deployment:
|
||||
|
||||
### 1. Backup Current Data
|
||||
```bash
|
||||
# Backup database
|
||||
mysqldump -u trasabilitate -p trasabilitate > backup.sql
|
||||
|
||||
# Backup any uploaded files or custom data
|
||||
cp -r py_app/instance backup_instance/
|
||||
```
|
||||
|
||||
### 2. Deploy Docker Solution
|
||||
```bash
|
||||
cd /srv/quality_recticel
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
### 3. Restore Data (if needed)
|
||||
```bash
|
||||
# Restore database
|
||||
docker compose exec -T db mariadb -u trasabilitate -pInitial01! trasabilitate < backup.sql
|
||||
```
|
||||
|
||||
### 4. Stop Old Service
|
||||
```bash
|
||||
# Stop systemd service
|
||||
sudo systemctl stop trasabilitate
|
||||
sudo systemctl disable trasabilitate
|
||||
```
|
||||
|
||||
## 🎓 Learning Resources
|
||||
|
||||
- Docker Compose docs: https://docs.docker.com/compose/
|
||||
- Gunicorn configuration: https://docs.gunicorn.org/
|
||||
- MariaDB Docker: https://hub.docker.com/_/mariadb
|
||||
|
||||
## ✅ Testing Checklist
|
||||
|
||||
After deployment, verify:
|
||||
|
||||
- [ ] Services are running: `docker compose ps`
|
||||
- [ ] App is accessible: http://localhost:8781
|
||||
- [ ] Can log in with superadmin
|
||||
- [ ] Database contains tables: `make shell-db` then `SHOW TABLES;`
|
||||
- [ ] Logs are being written: `ls -la logs/`
|
||||
- [ ] Can restart services: `docker compose restart`
|
||||
- [ ] Data persists after restart
|
||||
|
||||
## 🆘 Support Commands
|
||||
|
||||
```bash
|
||||
# View all services
|
||||
docker compose ps
|
||||
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# Restart a specific service
|
||||
docker compose restart web
|
||||
|
||||
# Access web container shell
|
||||
docker compose exec web bash
|
||||
|
||||
# Access database
|
||||
docker compose exec db mariadb -u trasabilitate -p
|
||||
|
||||
# Check resource usage
|
||||
docker stats
|
||||
|
||||
# Remove everything and start fresh
|
||||
docker compose down -v
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
## 📝 Next Steps
|
||||
|
||||
1. **Install Docker** on the target server (if not already installed)
|
||||
2. **Review and customize** `.env` file after copying from `.env.example`
|
||||
3. **Run deployment**: `./deploy.sh`
|
||||
4. **Change default passwords** after first login
|
||||
5. **Set up reverse proxy** (nginx/traefik) for HTTPS if needed
|
||||
6. **Configure backups** using `make backup-db`
|
||||
7. **Monitor logs** regularly with `make logs`
|
||||
|
||||
## 🎉 Benefits of This Solution
|
||||
|
||||
1. **Portable**: Works on any system with Docker
|
||||
2. **Reproducible**: Same deployment every time
|
||||
3. **Isolated**: No conflicts with system packages
|
||||
4. **Easy Updates**: Just rebuild and restart
|
||||
5. **Scalable**: Can easily add more services
|
||||
6. **Professional**: Production-ready configuration
|
||||
7. **Documented**: Complete documentation included
|
||||
8. **Maintainable**: Simple management commands
|
||||
|
||||
---
|
||||
|
||||
**Your Flask application is now ready for modern, containerized deployment! 🚀**
|
||||
280
old code/FILES_CREATED.md
Normal file
@@ -0,0 +1,280 @@
|
||||
# ✅ Docker Solution - Files Created
|
||||
|
||||
## 📦 Complete Docker Deployment Package
|
||||
|
||||
Your Flask application has been packaged into a complete Docker solution. Here's everything that was created:
|
||||
|
||||
### Core Docker Files
|
||||
|
||||
```
|
||||
/srv/quality_recticel/
|
||||
├── Dockerfile # Flask app container definition
|
||||
├── docker-compose.yml # Multi-container orchestration
|
||||
├── docker-entrypoint.sh # Container initialization script
|
||||
├── init-db.sql # MariaDB initialization
|
||||
├── .dockerignore # Build optimization
|
||||
└── .env.example # Configuration template
|
||||
```
|
||||
|
||||
### Deployment & Management
|
||||
|
||||
```
|
||||
├── deploy.sh # One-command deployment script
|
||||
├── Makefile # Management commands (make up, make down, etc.)
|
||||
├── README-DOCKER.md # Quick start guide
|
||||
├── DOCKER_DEPLOYMENT.md # Complete deployment documentation
|
||||
└── DOCKER_SOLUTION_SUMMARY.md # This comprehensive summary
|
||||
```
|
||||
|
||||
### Modified Files
|
||||
|
||||
```
|
||||
py_app/app/db_create_scripts/
|
||||
└── setup_complete_database.py # Updated to support Docker env vars
|
||||
```
|
||||
|
||||
## 🎯 What This Deployment Includes
|
||||
|
||||
### Services
|
||||
1. **Flask Web Application**
|
||||
- Python 3.10
|
||||
- Gunicorn WSGI server (production-ready)
|
||||
- Auto-generated database configuration
|
||||
- Health checks
|
||||
- Automatic restart on failure
|
||||
|
||||
2. **MariaDB 11.3 Database**
|
||||
- Automatic initialization
|
||||
- User and database creation
|
||||
- Data persistence (Docker volume)
|
||||
- Health checks
|
||||
|
||||
### Features
|
||||
- ✅ Single-command deployment
|
||||
- ✅ Automatic database schema setup
|
||||
- ✅ Superadmin user seeding
|
||||
- ✅ Data persistence across restarts
|
||||
- ✅ Container health monitoring
|
||||
- ✅ Log collection and management
|
||||
- ✅ Production-ready configuration
|
||||
- ✅ Easy backup and restore
|
||||
- ✅ Complete isolation from host system
|
||||
|
||||
## 🚀 How to Deploy
|
||||
|
||||
### Prerequisites
|
||||
**Install Docker first:**
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||
sudo sh get-docker.sh
|
||||
sudo usermod -aG docker $USER
|
||||
# Log out and back in
|
||||
```
|
||||
|
||||
### Deploy
|
||||
```bash
|
||||
cd /srv/quality_recticel
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
That's it! Your application will be available at http://localhost:8781
|
||||
|
||||
## 📋 Usage Examples
|
||||
|
||||
### Basic Operations
|
||||
```bash
|
||||
# Start services
|
||||
docker compose up -d
|
||||
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# Stop services
|
||||
docker compose down
|
||||
|
||||
# Restart
|
||||
docker compose restart
|
||||
|
||||
# Check status
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
### Using Makefile (Recommended)
|
||||
```bash
|
||||
make install # First-time setup
|
||||
make up # Start services
|
||||
make down # Stop services
|
||||
make logs # View logs
|
||||
make logs-web # View only web logs
|
||||
make logs-db # View only database logs
|
||||
make shell # Access app container
|
||||
make shell-db # Access database console
|
||||
make backup-db # Backup database
|
||||
make status # Show service status
|
||||
make help # Show all commands
|
||||
```
|
||||
|
||||
### Advanced Operations
|
||||
```bash
|
||||
# Rebuild after code changes
|
||||
docker compose up -d --build web
|
||||
|
||||
# Access application shell
|
||||
docker compose exec web bash
|
||||
|
||||
# Run database commands
|
||||
docker compose exec db mariadb -u trasabilitate -p trasabilitate
|
||||
|
||||
# View resource usage
|
||||
docker stats recticel-app recticel-db
|
||||
|
||||
# Complete reset (removes all data!)
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
## 🗂️ Data Storage
|
||||
|
||||
### Persistent Data
|
||||
- **Database**: Stored in Docker volume `mariadb_data`
|
||||
- **Logs**: Mounted to `./logs` directory
|
||||
- **Config**: Mounted to `./instance` directory
|
||||
|
||||
### Backup Database
|
||||
```bash
|
||||
docker compose exec -T db mariadb-dump -u trasabilitate -pInitial01! trasabilitate > backup.sql
|
||||
```
|
||||
|
||||
### Restore Database
|
||||
```bash
|
||||
docker compose exec -T db mariadb -u trasabilitate -pInitial01! trasabilitate < backup.sql
|
||||
```
|
||||
|
||||
## 🔐 Default Credentials
|
||||
|
||||
### Application
|
||||
- URL: http://localhost:8781
|
||||
- Username: `superadmin`
|
||||
- Password: `superadmin123`
|
||||
- **⚠️ Change after first login!**
|
||||
|
||||
### Database
|
||||
- Host: `localhost:3306` (from host) or `db:3306` (from containers)
|
||||
- Database: `trasabilitate`
|
||||
- User: `trasabilitate`
|
||||
- Password: `Initial01!`
|
||||
- Root Password: Set in `.env` file
|
||||
|
||||
## 📊 Service Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ recticel-network (Docker) │
|
||||
│ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ recticel-db │ │ recticel-app │ │
|
||||
│ │ (MariaDB 11.3) │◄───────┤ (Flask/Python) │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ - Internal DB │ │ - Gunicorn │ │
|
||||
│ │ - Health Check │ │ - Health Check │ │
|
||||
│ │ - Auto Init │ │ - Auto Config │ │
|
||||
│ └────────┬────────┘ └────────┬────────┘ │
|
||||
│ │ │ │
|
||||
│ │ 3306 (optional) 8781 │ │
|
||||
└────────────┼──────────────────────────┼────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
[mariadb_data] [Host: 8781]
|
||||
Docker Volume Application Access
|
||||
```
|
||||
|
||||
## 🎓 Quick Reference
|
||||
|
||||
### Environment Variables (.env)
|
||||
```env
|
||||
MYSQL_ROOT_PASSWORD=rootpassword # MariaDB root password
|
||||
DB_PORT=3306 # Database port (external)
|
||||
APP_PORT=8781 # Application port
|
||||
INIT_DB=true # Run DB initialization
|
||||
SEED_DB=true # Seed superadmin user
|
||||
```
|
||||
|
||||
### Important Ports
|
||||
- `8781`: Flask application (web interface)
|
||||
- `3306`: MariaDB database (optional external access)
|
||||
|
||||
### Log Locations
|
||||
- Application logs: `./logs/access.log` and `./logs/error.log`
|
||||
- Container logs: `docker compose logs`
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Can't connect to application
|
||||
```bash
|
||||
# Check if services are running
|
||||
docker compose ps
|
||||
|
||||
# Check web logs
|
||||
docker compose logs web
|
||||
|
||||
# Verify port not in use
|
||||
netstat -tuln | grep 8781
|
||||
```
|
||||
|
||||
### Database connection issues
|
||||
```bash
|
||||
# Check database health
|
||||
docker compose exec db healthcheck.sh --connect
|
||||
|
||||
# View database logs
|
||||
docker compose logs db
|
||||
|
||||
# Test database connection
|
||||
docker compose exec web python3 -c "import mariadb; print('OK')"
|
||||
```
|
||||
|
||||
### Port already in use
|
||||
Edit `.env` file:
|
||||
```env
|
||||
APP_PORT=8782 # Change to available port
|
||||
DB_PORT=3307 # Change if needed
|
||||
```
|
||||
|
||||
### Start completely fresh
|
||||
```bash
|
||||
docker compose down -v
|
||||
rm -rf logs/* instance/external_server.conf
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
## 📖 Documentation Files
|
||||
|
||||
1. **README-DOCKER.md** - Quick start guide (start here!)
|
||||
2. **DOCKER_DEPLOYMENT.md** - Complete deployment guide
|
||||
3. **DOCKER_SOLUTION_SUMMARY.md** - Comprehensive overview
|
||||
4. **FILES_CREATED.md** - This file
|
||||
|
||||
## ✨ Benefits
|
||||
|
||||
- **No System Dependencies**: Only Docker required
|
||||
- **Portable**: Deploy on any system with Docker
|
||||
- **Reproducible**: Consistent deployments every time
|
||||
- **Isolated**: No conflicts with other applications
|
||||
- **Production-Ready**: Gunicorn, health checks, proper logging
|
||||
- **Easy Management**: Simple commands, one-line deployment
|
||||
- **Persistent**: Data survives container restarts
|
||||
- **Scalable**: Easy to add more services
|
||||
|
||||
## 🎉 Success!
|
||||
|
||||
Your Recticel Quality Application is now containerized and ready for deployment!
|
||||
|
||||
**Next Steps:**
|
||||
1. Install Docker (if not already installed)
|
||||
2. Run `./deploy.sh`
|
||||
3. Access http://localhost:8781
|
||||
4. Log in with superadmin credentials
|
||||
5. Change default passwords
|
||||
6. Enjoy your containerized application!
|
||||
|
||||
For detailed instructions, see **README-DOCKER.md** or **DOCKER_DEPLOYMENT.md**.
|
||||
73
old code/README-DOCKER.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# 🚀 Quick Start - Docker Deployment
|
||||
|
||||
## What You Need
|
||||
- A server with Docker installed
|
||||
- 2GB free disk space
|
||||
- Ports 8781 and 3306 available
|
||||
|
||||
## Deploy in 3 Steps
|
||||
|
||||
### 1️⃣ Install Docker (if not already installed)
|
||||
|
||||
**Ubuntu/Debian:**
|
||||
```bash
|
||||
curl -fsSL https://get.docker.com -o get-docker.sh
|
||||
sudo sh get-docker.sh
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
Then log out and back in.
|
||||
|
||||
### 2️⃣ Deploy the Application
|
||||
```bash
|
||||
cd /srv/quality_recticel
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
### 3️⃣ Access Your Application
|
||||
Open browser: **http://localhost:8781**
|
||||
|
||||
**Login:**
|
||||
- Username: `superadmin`
|
||||
- Password: `superadmin123`
|
||||
|
||||
## 🎯 Done!
|
||||
|
||||
Your complete application with database is now running in Docker containers.
|
||||
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
# View logs
|
||||
docker compose logs -f
|
||||
|
||||
# Stop services
|
||||
docker compose down
|
||||
|
||||
# Restart services
|
||||
docker compose restart
|
||||
|
||||
# Backup database
|
||||
docker compose exec -T db mariadb-dump -u trasabilitate -pInitial01! trasabilitate > backup.sql
|
||||
```
|
||||
|
||||
## 📚 Full Documentation
|
||||
|
||||
See `DOCKER_DEPLOYMENT.md` for complete documentation.
|
||||
|
||||
## 🆘 Problems?
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
docker compose ps
|
||||
|
||||
# View detailed logs
|
||||
docker compose logs -f web
|
||||
|
||||
# Start fresh
|
||||
docker compose down -v
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Note:** This is a production-ready deployment using Gunicorn WSGI server, MariaDB 11.3, and proper health checks.
|
||||
36
old code/backup/db_test.html
Executable file
@@ -0,0 +1,36 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Database Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Database Connection Test</h2>
|
||||
<button id="test-btn">Test Database</button>
|
||||
<div id="result"></div>
|
||||
|
||||
<script>
|
||||
document.getElementById('test-btn').addEventListener('click', function() {
|
||||
const resultDiv = document.getElementById('result');
|
||||
resultDiv.innerHTML = 'Loading...';
|
||||
|
||||
fetch('/get_unprinted_orders')
|
||||
.then(response => {
|
||||
console.log('Response status:', response.status);
|
||||
if (response.ok) {
|
||||
return response.json();
|
||||
} else {
|
||||
throw new Error('HTTP ' + response.status);
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
console.log('Data received:', data);
|
||||
resultDiv.innerHTML = `<pre>${JSON.stringify(data, null, 2)}</pre>`;
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
resultDiv.innerHTML = 'Error: ' + error.message;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1085
old code/backup/print_module copy.html
Executable file
1383
old code/backup/print_module.html. old 1backup
Executable file
1374
old code/backup/print_module.html.old 2backup2
Executable file
1844
old code/backup/print_module.htmlold 3.bak
Executable file
1346
old code/backup/print_module_backup.html
Executable file
487
old code/backup/print_module_clean.html
Executable file
@@ -0,0 +1,487 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
#label-preview {
|
||||
background: #fafafa;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Enhanced table styling */
|
||||
.card.scan-table-card table.print-module-table.scan-table thead th {
|
||||
border-bottom: 2px solid #dee2e6 !important;
|
||||
background-color: #f8f9fa !important;
|
||||
padding: 0.25rem 0.4rem !important;
|
||||
text-align: left !important;
|
||||
font-weight: 600 !important;
|
||||
font-size: 10px !important;
|
||||
line-height: 1.2 !important;
|
||||
}
|
||||
|
||||
.card.scan-table-card table.print-module-table.scan-table {
|
||||
width: 100% !important;
|
||||
border-collapse: collapse !important;
|
||||
}
|
||||
|
||||
.card.scan-table-card table.print-module-table.scan-table tbody tr:hover td {
|
||||
background-color: #f8f9fa !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.card.scan-table-card table.print-module-table.scan-table tbody tr.selected td {
|
||||
background-color: #007bff !important;
|
||||
color: white !important;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="scan-container" style="display: flex; flex-direction: row; gap: 20px; width: 100%; align-items: flex-start;">
|
||||
<!-- Label Preview Card -->
|
||||
<div class="card scan-form-card" style="display: flex; flex-direction: column; justify-content: flex-start; align-items: center; min-height: 700px; width: 330px; flex-shrink: 0; position: relative; padding: 15px;">
|
||||
<div class="label-view-title" style="width: 100%; text-align: center; padding: 0 0 15px 0; font-size: 18px; font-weight: bold; letter-spacing: 0.5px;">Label View</div>
|
||||
|
||||
<!-- Label Preview Section -->
|
||||
<div id="label-preview" style="border: 1px solid #ddd; padding: 10px; position: relative; background: #fafafa; width: 301px; height: 434.7px;">
|
||||
<!-- Label content rectangle -->
|
||||
<div id="label-content" style="position: absolute; top: 65.7px; left: 11.34px; width: 227.4px; height: 321.3px; border: 2px solid #333; background: white;">
|
||||
<!-- Top row content: Company name -->
|
||||
<div style="position: absolute; top: 0; left: 0; right: 0; height: 32.13px; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 12px; color: #000; z-index: 10;">
|
||||
INNOFA ROMANIA SRL
|
||||
</div>
|
||||
|
||||
<!-- Row 2 content: Customer Name -->
|
||||
<div id="customer-name-row" style="position: absolute; top: 32.13px; left: 0; right: 0; height: 32.13px; display: flex; align-items: center; justify-content: center; font-size: 11px; color: #000;">
|
||||
<!-- Customer name will be populated here -->
|
||||
</div>
|
||||
|
||||
<!-- Horizontal dividing lines -->
|
||||
<div style="position: absolute; top: 32.13px; left: 0; right: 0; height: 1px; background: #999;"></div>
|
||||
<div style="position: absolute; top: 64.26px; left: 0; right: 0; height: 1px; background: #999;"></div>
|
||||
<div style="position: absolute; top: 96.39px; left: 0; right: 0; height: 1px; background: #999;"></div>
|
||||
<div style="position: absolute; top: 128.52px; left: 0; right: 0; height: 1px; background: #999;"></div>
|
||||
<div style="position: absolute; top: 160.65px; left: 0; right: 0; height: 1px; background: #999;"></div>
|
||||
<div style="position: absolute; top: 224.91px; left: 0; right: 0; height: 1px; background: #999;"></div>
|
||||
<div style="position: absolute; top: 257.04px; left: 0; right: 0; height: 1px; background: #999;"></div>
|
||||
<div style="position: absolute; top: 289.17px; left: 0; right: 0; height: 1px; background: #999;"></div>
|
||||
|
||||
<!-- Vertical dividing line -->
|
||||
<div style="position: absolute; left: 90.96px; top: 64.26px; width: 1px; height: 257.04px; background: #999;"></div>
|
||||
|
||||
<!-- Row 3: Quantity ordered -->
|
||||
<div style="position: absolute; top: 64.26px; left: 0; width: 90.96px; height: 32.13px; display: flex; align-items: center; padding-left: 5px; font-size: 10px; color: #000;">
|
||||
Quantity ordered
|
||||
</div>
|
||||
<div id="quantity-ordered-value" style="position: absolute; top: 64.26px; left: 90.96px; width: 136.44px; height: 32.13px; display: flex; align-items: center; justify-content: center; font-size: 13px; font-weight: bold; color: #000;">
|
||||
<!-- Quantity value will be populated here -->
|
||||
</div>
|
||||
|
||||
<!-- Row 4: Customer order -->
|
||||
<div style="position: absolute; top: 96.39px; left: 0; width: 90.96px; height: 32.13px; display: flex; align-items: center; padding-left: 5px; font-size: 10px; color: #000;">
|
||||
Customer order
|
||||
</div>
|
||||
<div id="client-order-info" style="position: absolute; top: 96.39px; left: 90.96px; width: 136.44px; height: 32.13px; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; color: #000;">
|
||||
<!-- Client order info will be populated here -->
|
||||
</div>
|
||||
|
||||
<!-- Row 5: Delivery date -->
|
||||
<div style="position: absolute; top: 128.52px; left: 0; width: 90.96px; height: 32.13px; display: flex; align-items: center; padding-left: 5px; font-size: 10px; color: #000;">
|
||||
Delivery date
|
||||
</div>
|
||||
<div id="delivery-date-value" style="position: absolute; top: 128.52px; left: 90.96px; width: 136.44px; height: 32.13px; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: bold; color: #000;">
|
||||
<!-- Delivery date value will be populated here -->
|
||||
</div>
|
||||
|
||||
<!-- Row 6: Description (double height) -->
|
||||
<div style="position: absolute; top: 160.65px; left: 0; width: 90.96px; height: 64.26px; display: flex; align-items: center; padding-left: 5px; font-size: 10px; color: #000;">
|
||||
Product description
|
||||
</div>
|
||||
<div id="description-value" style="position: absolute; top: 160.65px; left: 90.96px; width: 136.44px; height: 64.26px; display: flex; align-items: center; justify-content: center; font-size: 8px; color: #000; text-align: center; padding: 2px; overflow: hidden;">
|
||||
<!-- Description will be populated here -->
|
||||
</div>
|
||||
|
||||
<!-- Row 7: Size -->
|
||||
<div style="position: absolute; top: 224.91px; left: 0; width: 90.96px; height: 32.13px; display: flex; align-items: center; padding-left: 5px; font-size: 10px; color: #000;">
|
||||
Size
|
||||
</div>
|
||||
<div id="size-value" style="position: absolute; top: 224.91px; left: 90.96px; width: 136.44px; height: 32.13px; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: bold; color: #000;">
|
||||
<!-- Size value will be populated here -->
|
||||
</div>
|
||||
|
||||
<!-- Row 8: Article Code -->
|
||||
<div style="position: absolute; top: 257.04px; left: 0; width: 90.96px; height: 32.13px; display: flex; align-items: center; padding-left: 5px; font-size: 10px; color: #000;">
|
||||
Article code
|
||||
</div>
|
||||
<div id="article-code-value" style="position: absolute; top: 257.04px; left: 90.96px; width: 136.44px; height: 32.13px; display: flex; align-items: center; justify-content: center; font-size: 9px; font-weight: bold; color: #000;">
|
||||
<!-- Article code will be populated here -->
|
||||
</div>
|
||||
|
||||
<!-- Row 9: Production Order -->
|
||||
<div style="position: absolute; top: 289.17px; left: 0; width: 90.96px; height: 32.13px; display: flex; align-items: center; padding-left: 5px; font-size: 10px; color: #000;">
|
||||
Prod. order
|
||||
</div>
|
||||
<div id="prod-order-value" style="position: absolute; top: 289.17px; left: 90.96px; width: 136.44px; height: 32.13px; display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: bold; color: #000;">
|
||||
<!-- Production order will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom barcode section -->
|
||||
<div style="position: absolute; bottom: 28.35px; left: 11.34px; width: 227.4px; height: 28.35px; border: 2px solid #333; background: white; display: flex; align-items: center; justify-content: center;">
|
||||
<div id="barcode-text" style="font-family: 'Courier New', monospace; font-size: 12px; font-weight: bold; letter-spacing: 1px; color: #000;">
|
||||
<!-- Barcode text will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Vertical barcode (right side) -->
|
||||
<div style="position: absolute; right: 11.34px; top: 65.7px; width: 28.35px; height: 321.3px; border: 2px solid #333; background: white; writing-mode: vertical-lr; text-orientation: sideways; display: flex; align-items: center; justify-content: center;">
|
||||
<div id="vertical-barcode-text" style="font-family: 'Courier New', monospace; font-size: 10px; font-weight: bold; letter-spacing: 1px; color: #000; transform: rotate(180deg);">
|
||||
<!-- Vertical barcode text will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Print Options -->
|
||||
<div style="width: 100%; margin-top: 20px;">
|
||||
<!-- Print Method Selection -->
|
||||
<div style="margin-bottom: 15px;">
|
||||
<label style="font-size: 12px; font-weight: 600; color: #495057; margin-bottom: 8px; display: block;">
|
||||
📄 Print Method:
|
||||
</label>
|
||||
|
||||
<div class="form-check mb-2">
|
||||
<input class="form-check-input" type="radio" name="printMethod" id="pdfGenerate" value="pdf" checked>
|
||||
<label class="form-check-label" for="pdfGenerate" style="font-size: 11px; line-height: 1.3;">
|
||||
<strong>Generate PDF</strong><br>
|
||||
<span class="text-muted">Create PDF for manual printing (recommended)</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Print Button -->
|
||||
<div style="width: 100%; text-align: center; margin-bottom: 15px;">
|
||||
<button id="print-label-btn" class="btn btn-success" style="font-size: 14px; padding: 10px 30px; border-radius: 6px; font-weight: 600;">
|
||||
📄 Generate PDF Labels
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Print Information -->
|
||||
<div style="width: 100%; text-align: center; color: #6c757d; font-size: 11px; line-height: 1.4;">
|
||||
<div style="margin-bottom: 5px;">Creates sequential labels based on quantity</div>
|
||||
<small>(e.g., CP00000711-001 to CP00000711-063)</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Data Preview Card -->
|
||||
<div class="card scan-table-card" style="min-height: 700px; width: calc(100% - 350px); margin: 0;">
|
||||
<h3>Data Preview (Unprinted Orders)</h3>
|
||||
<button id="check-db-btn" class="btn btn-primary mb-3">Load Orders</button>
|
||||
<div class="report-table-container">
|
||||
<table class="scan-table print-module-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Comanda Productie</th>
|
||||
<th>Cod Articol</th>
|
||||
<th>Descr. Com. Prod</th>
|
||||
<th>Cantitate</th>
|
||||
<th>Data Livrare</th>
|
||||
<th>Dimensiune</th>
|
||||
<th>Com. Achiz. Client</th>
|
||||
<th>Nr. Linie</th>
|
||||
<th>Customer Name</th>
|
||||
<th>Customer Art. Nr.</th>
|
||||
<th>Open Order</th>
|
||||
<th>Line</th>
|
||||
<th>Printed</th>
|
||||
<th>Created</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="unprinted-orders-table">
|
||||
<!-- Data will be dynamically loaded here -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Simplified notification system
|
||||
function showNotification(message, type = 'info') {
|
||||
const existingNotifications = document.querySelectorAll('.notification');
|
||||
existingNotifications.forEach(n => n.remove());
|
||||
|
||||
const notification = document.createElement('div');
|
||||
notification.className = `notification alert alert-${type === 'error' ? 'danger' : type === 'success' ? 'success' : type === 'warning' ? 'warning' : 'info'}`;
|
||||
notification.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 9999;
|
||||
max-width: 350px;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
`;
|
||||
notification.innerHTML = `
|
||||
<div style="display: flex; align-items: center; justify-content: space-between;">
|
||||
<span style="flex: 1; padding-right: 10px;">${message}</span>
|
||||
<button type="button" onclick="this.parentElement.parentElement.remove()" style="background: none; border: none; font-size: 20px; cursor: pointer;">×</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(notification);
|
||||
|
||||
setTimeout(() => {
|
||||
if (notification.parentElement) {
|
||||
notification.remove();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// Database loading functionality
|
||||
document.getElementById('check-db-btn').addEventListener('click', function() {
|
||||
const button = this;
|
||||
const originalText = button.textContent;
|
||||
button.textContent = 'Loading...';
|
||||
button.disabled = true;
|
||||
|
||||
fetch('/get_unprinted_orders')
|
||||
.then(response => {
|
||||
if (response.status === 403) {
|
||||
return response.json().then(errorData => {
|
||||
throw new Error(`Access Denied: ${errorData.error}`);
|
||||
});
|
||||
} else if (!response.ok) {
|
||||
return response.text().then(text => {
|
||||
throw new Error(`HTTP ${response.status}: ${text}`);
|
||||
});
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
console.log('Received data:', data);
|
||||
const tbody = document.getElementById('unprinted-orders-table');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
if (data.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="15" style="text-align: center; padding: 20px; color: #28a745;"><strong>✅ All orders have been printed!</strong><br><small>No unprinted orders remaining.</small></td></tr>';
|
||||
clearLabelPreview();
|
||||
return;
|
||||
}
|
||||
|
||||
data.forEach((order, index) => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.dataset.orderId = order.id;
|
||||
tr.dataset.orderIndex = index;
|
||||
tr.style.cursor = 'pointer';
|
||||
tr.innerHTML = `
|
||||
<td style="font-size: 9px;">${order.id}</td>
|
||||
<td style="font-size: 9px;"><strong>${order.comanda_productie}</strong></td>
|
||||
<td style="font-size: 9px;">${order.cod_articol || '-'}</td>
|
||||
<td style="font-size: 9px;">${order.descr_com_prod}</td>
|
||||
<td style="text-align: right; font-weight: 600; font-size: 9px;">${order.cantitate}</td>
|
||||
<td style="text-align: center; font-size: 9px;">
|
||||
${order.data_livrare ? new Date(order.data_livrare).toLocaleDateString() : '-'}
|
||||
</td>
|
||||
<td style="text-align: center; font-size: 9px;">${order.dimensiune || '-'}</td>
|
||||
<td style="font-size: 9px;">${order.com_achiz_client || '-'}</td>
|
||||
<td style="text-align: right; font-size: 9px;">${order.nr_linie_com_client || '-'}</td>
|
||||
<td style="font-size: 9px;">${order.customer_name || '-'}</td>
|
||||
<td style="font-size: 9px;">${order.customer_article_number || '-'}</td>
|
||||
<td style="font-size: 9px;">${order.open_for_order || '-'}</td>
|
||||
<td style="text-align: right; font-size: 9px;">${order.line_number || '-'}</td>
|
||||
<td style="text-align: center; font-size: 9px;">
|
||||
${order.printed_labels == 1 ?
|
||||
'<span style="color: #28a745; font-weight: bold;">✅ Yes</span>' :
|
||||
'<span style="color: #dc3545;">❌ No</span>'}
|
||||
</td>
|
||||
<td style="font-size: 9px; color: #6c757d;">
|
||||
${order.created_at ? new Date(order.created_at).toLocaleString() : '-'}
|
||||
</td>
|
||||
`;
|
||||
|
||||
tr.addEventListener('click', function() {
|
||||
console.log('Row clicked:', order.id);
|
||||
|
||||
// Remove selection from other rows
|
||||
document.querySelectorAll('.print-module-table tbody tr').forEach(row => {
|
||||
row.classList.remove('selected');
|
||||
const cells = row.querySelectorAll('td');
|
||||
cells.forEach(cell => {
|
||||
cell.style.backgroundColor = '';
|
||||
cell.style.color = '';
|
||||
});
|
||||
});
|
||||
|
||||
// Select this row
|
||||
this.classList.add('selected');
|
||||
const cells = this.querySelectorAll('td');
|
||||
cells.forEach(cell => {
|
||||
cell.style.backgroundColor = '#007bff';
|
||||
cell.style.color = 'white';
|
||||
});
|
||||
|
||||
// Update label preview with selected order data
|
||||
updateLabelPreview(order);
|
||||
});
|
||||
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
// Auto-select first row
|
||||
setTimeout(() => {
|
||||
const firstRow = document.querySelector('.print-module-table tbody tr');
|
||||
if (firstRow && !firstRow.querySelector('td[colspan]')) {
|
||||
firstRow.click();
|
||||
}
|
||||
}, 100);
|
||||
|
||||
showNotification(`✅ Loaded ${data.length} unprinted orders`, 'success');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading orders:', error);
|
||||
const tbody = document.getElementById('unprinted-orders-table');
|
||||
tbody.innerHTML = '<tr><td colspan="15" style="text-align: center; padding: 20px; color: #dc3545;"><strong>❌ Failed to load data</strong><br><small>' + error.message + '</small></td></tr>';
|
||||
showNotification('❌ Failed to load orders: ' + error.message, 'error');
|
||||
})
|
||||
.finally(() => {
|
||||
button.textContent = originalText;
|
||||
button.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
// Update label preview with order data
|
||||
function updateLabelPreview(order) {
|
||||
document.getElementById('customer-name-row').textContent = order.customer_name || 'N/A';
|
||||
document.getElementById('quantity-ordered-value').textContent = order.cantitate || '0';
|
||||
document.getElementById('client-order-info').textContent =
|
||||
`${order.com_achiz_client || 'N/A'}-${order.nr_linie_com_client || '00'}`;
|
||||
document.getElementById('delivery-date-value').textContent =
|
||||
order.data_livrare ? new Date(order.data_livrare).toLocaleDateString() : 'N/A';
|
||||
document.getElementById('description-value').textContent = order.descr_com_prod || 'N/A';
|
||||
document.getElementById('size-value').textContent = order.dimensiune || 'N/A';
|
||||
document.getElementById('article-code-value').textContent = order.cod_articol || 'N/A';
|
||||
document.getElementById('prod-order-value').textContent = order.comanda_productie || 'N/A';
|
||||
document.getElementById('barcode-text').textContent = order.comanda_productie || 'N/A';
|
||||
document.getElementById('vertical-barcode-text').textContent =
|
||||
`${order.comanda_productie || '000000'}-${order.nr_linie_com_client ? String(order.nr_linie_com_client).padStart(2, '0') : '00'}`;
|
||||
}
|
||||
|
||||
// Clear label preview when no orders are available
|
||||
function clearLabelPreview() {
|
||||
document.getElementById('customer-name-row').textContent = 'No orders available';
|
||||
document.getElementById('quantity-ordered-value').textContent = '0';
|
||||
document.getElementById('client-order-info').textContent = 'N/A';
|
||||
document.getElementById('delivery-date-value').textContent = 'N/A';
|
||||
document.getElementById('size-value').textContent = 'N/A';
|
||||
document.getElementById('description-value').textContent = 'N/A';
|
||||
document.getElementById('article-code-value').textContent = 'N/A';
|
||||
document.getElementById('prod-order-value').textContent = 'N/A';
|
||||
document.getElementById('barcode-text').textContent = 'N/A';
|
||||
document.getElementById('vertical-barcode-text').textContent = '000000-00';
|
||||
}
|
||||
|
||||
// PDF Generation Handler
|
||||
document.getElementById('print-label-btn').addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Get selected order
|
||||
const selectedRow = document.querySelector('.print-module-table tbody tr.selected');
|
||||
if (!selectedRow) {
|
||||
showNotification('⚠️ Please select an order first from the table below.', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
handlePDFGeneration(selectedRow);
|
||||
});
|
||||
|
||||
// Handle PDF generation
|
||||
function handlePDFGeneration(selectedRow) {
|
||||
const orderId = selectedRow.dataset.orderId;
|
||||
const quantityCell = selectedRow.querySelector('td:nth-child(5)');
|
||||
const quantity = quantityCell ? parseInt(quantityCell.textContent) : 1;
|
||||
const prodOrderCell = selectedRow.querySelector('td:nth-child(2)');
|
||||
const prodOrder = prodOrderCell ? prodOrderCell.textContent.trim() : 'N/A';
|
||||
|
||||
const button = document.getElementById('print-label-btn');
|
||||
const originalText = button.textContent;
|
||||
button.textContent = 'Generating PDF...';
|
||||
button.disabled = true;
|
||||
|
||||
console.log(`Generating PDF for order ${orderId} with ${quantity} labels`);
|
||||
|
||||
// Generate PDF with paper-saving mode enabled (optimized for thermal printers)
|
||||
fetch(`/generate_labels_pdf/${orderId}/true`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.blob();
|
||||
})
|
||||
.then(blob => {
|
||||
// Create blob URL for PDF
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
// Create download link for PDF
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `labels_${prodOrder}_${quantity}pcs.pdf`;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
|
||||
// Also open PDF in new tab for printing
|
||||
const printWindow = window.open(url, '_blank');
|
||||
if (printWindow) {
|
||||
printWindow.focus();
|
||||
|
||||
// Wait for PDF to load, then show print dialog
|
||||
setTimeout(() => {
|
||||
printWindow.print();
|
||||
|
||||
// Clean up blob URL after print dialog is shown
|
||||
setTimeout(() => {
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 2000);
|
||||
}, 1500);
|
||||
} else {
|
||||
// If popup was blocked, clean up immediately
|
||||
setTimeout(() => {
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Show success message
|
||||
showNotification(`✅ PDF generated successfully!\n📊 Order: ${prodOrder}\n📦 Labels: ${quantity} pieces`, 'success');
|
||||
|
||||
// Refresh the orders table to reflect printed status
|
||||
setTimeout(() => {
|
||||
document.getElementById('check-db-btn').click();
|
||||
}, 1000);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error generating PDF:', error);
|
||||
showNotification('❌ Failed to generate PDF labels. Error: ' + error.message, 'error');
|
||||
})
|
||||
.finally(() => {
|
||||
// Reset button state
|
||||
button.textContent = originalText;
|
||||
button.disabled = false;
|
||||
});
|
||||
}
|
||||
|
||||
// Load orders on page load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
setTimeout(() => {
|
||||
document.getElementById('check-db-btn').click();
|
||||
}, 500);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
1110
old code/backup/print_moduleold but good.html
Executable file
5
old code/external_database_settings
Executable file
@@ -0,0 +1,5 @@
|
||||
Server Domain/IP Address: testserver.com
|
||||
Port: 3602
|
||||
Database Name: recticel
|
||||
Username: sa
|
||||
Password: 12345678
|
||||
15
old code/recticel-app.service
Normal file
@@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=Recticel Quality App
|
||||
After=network.target mariadb.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=ske087
|
||||
WorkingDirectory=/home/ske087/quality_recticel
|
||||
Environment=PATH=/home/ske087/quality_recticel/recticel/bin
|
||||
ExecStart=/home/ske087/quality_recticel/recticel/bin/python py_app/run.py
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
23
old code/to_do.txt
Executable file
@@ -0,0 +1,23 @@
|
||||
python3 -m venv recticel
|
||||
source recticel/bin/activate
|
||||
python /home/ske087/quality_recticel/py_app/run.py
|
||||
|
||||
sudo apt install mariadb-server mariadb-client
|
||||
sudo apt-get install libmariadb-dev libmariadb-dev-compat
|
||||
|
||||
sudo mysql -u root -p
|
||||
|
||||
root password : Initaial01! acasa Matei@123
|
||||
|
||||
CREATE DATABASE trasabilitate_database;
|
||||
CREATE USER 'trasabilitate'@'localhost' IDENTIFIED BY 'Initial01!';
|
||||
GRANT ALL PRIVILEGES ON trasabilitate_database.* TO 'trasabilitate'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
EXIT
|
||||
|
||||
|
||||
Server Domain/IP Address: testserver.com
|
||||
Port: 3602
|
||||
Database Name: recticel
|
||||
Username: sa
|
||||
Password: 12345678
|
||||
32
old code/to_do_install.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
# Steps to Prepare Environment for Installing Python Requirements
|
||||
|
||||
1. Change ownership of the project directory (if needed):
|
||||
sudo chown -R $USER:$USER /home/ske087/quality_recticel
|
||||
|
||||
2. Install Python venv module:
|
||||
sudo apt install -y python3-venv
|
||||
|
||||
3. Create and activate the virtual environment:
|
||||
python3 -m venv recticel
|
||||
source recticel/bin/activate
|
||||
|
||||
4. Install MariaDB server and development libraries:
|
||||
sudo apt install -y mariadb-server libmariadb-dev
|
||||
|
||||
5. Create MariaDB database and user:
|
||||
sudo mysql -e "CREATE DATABASE trasabilitate; CREATE USER 'sa'@'localhost' IDENTIFIED BY 'qasdewrftgbcgfdsrytkmbf\"b'; GRANT ALL PRIVILEGES ON quality.* TO 'sa'@'localhost'; FLUSH PRIVILEGES;"
|
||||
sa
|
||||
qasdewrftgbcgfdsrytkmbf\"b
|
||||
|
||||
trasabilitate
|
||||
Initial01!
|
||||
|
||||
6. Install build tools (for compiling Python packages):
|
||||
sudo apt install -y build-essential
|
||||
|
||||
7. Install Python development headers:
|
||||
sudo apt install -y python3-dev
|
||||
|
||||
8. Install Python requirements:
|
||||
pip install -r py_app/requirements.txt
|
||||
60
old code/tray/.github/workflows/build.yaml
vendored
Executable file
@@ -0,0 +1,60 @@
|
||||
name: build
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
ubuntu:
|
||||
runs-on: [ubuntu-latest]
|
||||
strategy:
|
||||
matrix:
|
||||
java: [11, 21]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: 'liberica'
|
||||
- run: sudo apt-get install nsis makeself
|
||||
- run: ant makeself
|
||||
- run: sudo out/qz-tray-*.run
|
||||
- run: /opt/qz-tray/qz-tray --version
|
||||
- run: ant nsis
|
||||
|
||||
macos:
|
||||
runs-on: [macos-latest]
|
||||
strategy:
|
||||
matrix:
|
||||
java: [11, 21]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: 'liberica'
|
||||
- run: brew install nsis makeself
|
||||
- run: ant pkgbuild
|
||||
- run: echo "Setting CA trust settings to 'allow' (https://github.com/actions/runner-images/issues/4519)"
|
||||
- run: security authorizationdb read com.apple.trust-settings.admin > /tmp/trust-settings-backup.xml
|
||||
- run: sudo security authorizationdb write com.apple.trust-settings.admin allow
|
||||
- run: sudo installer -pkg out/qz-tray-*.pkg -target /
|
||||
- run: echo "Restoring CA trust settings back to default"
|
||||
- run: sudo security authorizationdb write com.apple.trust-settings.admin < /tmp/trust-settings-backup.xml
|
||||
- run: "'/Applications/QZ Tray.app/Contents/MacOS/QZ Tray' --version"
|
||||
- run: ant makeself
|
||||
- run: ant nsis
|
||||
|
||||
windows:
|
||||
runs-on: [windows-latest]
|
||||
strategy:
|
||||
matrix:
|
||||
java: [11, 21]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java }}
|
||||
distribution: 'liberica'
|
||||
- run: choco install nsis
|
||||
- run: ant nsis
|
||||
- run: Start-Process -Wait ./out/qz-tray-*.exe -ArgumentList "/S"
|
||||
- run: "&'C:/Program Files/QZ Tray/qz-tray.exe' --wait --version|Out-Null"
|
||||
33
old code/tray/.gitignore
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
# Build outputs
|
||||
/out/
|
||||
*.class
|
||||
|
||||
# Node modules
|
||||
/js/node_modules
|
||||
|
||||
# JavaFX runtime (too large, should be downloaded)
|
||||
/lib/javafx*
|
||||
|
||||
# IDE files
|
||||
/.idea/workspace.xml
|
||||
/.idea/misc.xml
|
||||
/.idea/uiDesigner.xml
|
||||
/.idea/compiler.xml
|
||||
.idea/
|
||||
*.iml
|
||||
.vscode/
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
windows-debug-launcher.nsi.in
|
||||
|
||||
# Build artifacts
|
||||
/fx.zip
|
||||
/provision.json
|
||||
|
||||
# Private keys
|
||||
/ant/private/qz.ks
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
14
old code/tray/Dockerfile
Executable file
@@ -0,0 +1,14 @@
|
||||
FROM openjdk:11 as build
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y ant nsis makeself
|
||||
COPY . /usr/src/tray
|
||||
WORKDIR /usr/src/tray
|
||||
RUN ant makeself
|
||||
|
||||
FROM openjdk:11-jre as install
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y libglib2.0-bin
|
||||
COPY --from=build /usr/src/tray/out/*.run /tmp
|
||||
RUN find /tmp -iname "*.run" -exec {} \;
|
||||
WORKDIR /opt/qz-tray
|
||||
ENTRYPOINT ["/opt/qz-tray/qz-tray"]
|
||||
601
old code/tray/LICENSE.txt
Executable file
@@ -0,0 +1,601 @@
|
||||
ATTRIBUTION, LICENSING AND SUMMARY OF COMPONENTS
|
||||
Version 1.2, February 2016
|
||||
|
||||
Project Source Code (unless otherwise specified):
|
||||
Copyright (c) 2013-2016 QZ Industries, LLC
|
||||
LGPL-2.1 License (attached)
|
||||
https://qz.io
|
||||
|
||||
All API Examples (unless otherwise specified):
|
||||
Covers: JavaScript examples, Wiki API Examples, Signing API Examples
|
||||
Public Domain (no restrictions)
|
||||
______________________________________________________________________
|
||||
|
||||
Other licenses:
|
||||
|
||||
jOOR Reflection Library (As-Is, No Modifications)
|
||||
Copyright (c) 2011-2012, Lukas Eder, lukas.eder@gmail.com
|
||||
Apache License, Version 2.0 (attached), with Copyright Notice
|
||||
https://github.com/jOOQ/jOOR
|
||||
|
||||
|
||||
jetty Web Server Library (As-Is, No Modifications)
|
||||
Copyright (c) 1995-2014 Eclipse Foundation
|
||||
Apache License, Version 2.0 (attached), with Copyright Notice
|
||||
http://eclipse.org/jetty/
|
||||
|
||||
|
||||
Apache log4j (As-Is, No Modifications)
|
||||
Copyright (C) 1999-2005 The Apache Software Foundation
|
||||
Apache License, Version 2.0 (attached), with Copyright Notice
|
||||
https://logging.apache.org/
|
||||
|
||||
|
||||
Apache PDFBox (As-Is, No Modifications)
|
||||
Copyright (C) 2009–2015 The Apache Software Foundation
|
||||
Apache License, Version 2.0 (attached), with Copyright Notice
|
||||
https://pdfbox.apache.org/
|
||||
|
||||
|
||||
jSSC Library (As-Is, No Modifications)
|
||||
Copyright (c) 2010-2013 Alexey Sokolov (scream3r)
|
||||
LGPL-2.1 License (attached), with Copyright notice
|
||||
https://code.google.com/p/java-simple-serial-connector/
|
||||
|
||||
|
||||
hid4java (As-Is, No Modifications)
|
||||
Copyright (c) 2014 Gary Rowe
|
||||
MIT License (attached), with Copyright notice
|
||||
https://github.com/gary-rowe/hid4java
|
||||
|
||||
|
||||
jsemver (As-Is, No Modifications)
|
||||
Copyright 2012-2014 Zafar Khaja <zafarkhaja@gmail.com>
|
||||
MIT License (attached), with Copyright notice
|
||||
https://github.com/zafarkhaja/jsemver
|
||||
______________________________________________________________________
|
||||
|
||||
|
||||
LGPL 2.1
|
||||
Applies ONLY to: qz-tray, jssc
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
USA
|
||||
|
||||
END OF LGPL 2.1
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
|
||||
Apache 2.0
|
||||
Applies ONLY to: joor, jetty, Apache PDFBox, Apache log4j
|
||||
|
||||
|
||||
APACHE LICENSE
|
||||
Version 2.0, January 2004
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
END OF Apache 2.0
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
|
||||
MIT License
|
||||
Applies ONLY to: hid4java, jsemver
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
END OF MIT License
|
||||
|
||||
______________________________________________________________________
|
||||
|
||||
END OF ATTRIBUTION, LICENSING AND SUMMARY OF QZ-TRAY COMPONENTS
|
||||
23
old code/tray/README.md
Executable file
@@ -0,0 +1,23 @@
|
||||
QZ Tray
|
||||
========
|
||||
|
||||
[](../../actions) [](../../releases) [](../../issues) [](../../commits)
|
||||
|
||||
Browser plugin for sending documents and raw commands to a printer or attached device
|
||||
|
||||
## Getting Started
|
||||
* Download here https://qz.io/download/
|
||||
* See our [Getting Started](../../wiki/getting-started) guide.
|
||||
* Visit our home page https://qz.io.
|
||||
|
||||
## Support
|
||||
* File a bug via our [issue tracker](../../issues)
|
||||
* Ask the community via our [community support page](https://qz.io/support/)
|
||||
* Ask the developers via [premium support](https://qz.io/contact/) (fees may apply)
|
||||
|
||||
## Changelog
|
||||
* See our [most recent releases](../../releases)
|
||||
|
||||
## Java Developer Resources
|
||||
* [Install dependencies](../../wiki/install-dependencies)
|
||||
* [Compile, Package](../../wiki/compiling)
|
||||
11
old code/tray/SUPPORT.md
Executable file
@@ -0,0 +1,11 @@
|
||||
Please feel free to open bug reports on GitHub. Before opening an issue, we ask that you consider whether your issue is a support question, or a potential bug with the software.
|
||||
|
||||
If you have a support question, first [check the FAQ](https://qz.io/wiki/faq) and the [wiki](https://qz.io/wiki/Home). If you cannot find a solution please reach out to one of the appropriate channels:
|
||||
|
||||
### Community Support
|
||||
|
||||
If you need assistance using the software and do not have a paid subscription, please reference our community support channel: https://qz.io/support/
|
||||
|
||||
### Premium Support
|
||||
|
||||
If you have an active support license with QZ Industries, LLC, please send support requests to support@qz.io
|
||||
12
old code/tray/ant/apple/appdmg.json.in
Executable file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"title": "${project.name}",
|
||||
"background": "${basedir}/ant/apple/dmg-background.png",
|
||||
"icon-size": 128,
|
||||
"contents": [
|
||||
{ "x": 501, "y": 154, "type": "link", "path": "/Applications" },
|
||||
{ "x": 179, "y": 154, "type": "file", "path": "${build.dir}/${project.name}.app" }
|
||||
],
|
||||
"code-sign": {
|
||||
"signing-identity" : "${codesign.activeid}"
|
||||
}
|
||||
}
|
||||
28
old code/tray/ant/apple/apple-bundle.plist.in
Executable file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0"><dict>
|
||||
<key>CFBundleDevelopmentRegion</key><string>English</string>
|
||||
<key>CFBundleIconFile</key><string>${project.filename}</string>
|
||||
<key>CFBundleIdentifier</key><string>${apple.bundleid}</string>
|
||||
<key>CFBundlePackageType</key><string>APPL</string>
|
||||
<key>CFBundleGetInfoString</key><string>${project.name} ${build.version}</string>
|
||||
<key>CFBundleSignature</key><string>${project.name}</string>
|
||||
<key>CFBundleExecutable</key><string>${project.name}</string>
|
||||
<key>CFBundleVersion</key><string>${build.version}</string>
|
||||
<key>CFBundleShortVersionString</key><string>${build.version}</string>
|
||||
<key>CFBundleName</key><string>${project.name}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>${project.name}</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array><string>${vendor.name}</string></array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>LSArchitecturePriority</key>
|
||||
<array>
|
||||
<string>${apple.target.arch}</string>
|
||||
</array>
|
||||
</dict></plist>
|
||||
30
old code/tray/ant/apple/apple-entitlements.plist.in
Executable file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<${build.sandboxed}/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.all</key>
|
||||
<true/>
|
||||
<key>com.apple.security.print</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.usb</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.bluetooth</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
23
old code/tray/ant/apple/apple-postinstall.sh.in
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Halt on first error
|
||||
set -e
|
||||
|
||||
# Get working directory
|
||||
DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
pushd "$DIR/payload/${project.name}.app/Contents/MacOS/"
|
||||
|
||||
./"${project.name}" install >> "${install.log}" 2>&1
|
||||
popd
|
||||
|
||||
# Use install target from pkgbuild, an undocumented feature; fallback on sane location
|
||||
if [ -n "$2" ]; then
|
||||
pushd "$2/Contents/MacOS/"
|
||||
else
|
||||
pushd "/Applications/${project.name}.app/Contents/MacOS/"
|
||||
fi
|
||||
|
||||
./"${project.name}" certgen >> "${install.log}" 2>&1
|
||||
|
||||
# Start qz by calling open on the .app as an ordinary user
|
||||
su "$USER" -c "open ../../" || true
|
||||
31
old code/tray/ant/apple/apple-preinstall.sh.in
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Halt on first error
|
||||
set -e
|
||||
|
||||
# Clear the log for writing
|
||||
> "${install.log}"
|
||||
|
||||
# Log helper
|
||||
dbg () {
|
||||
echo -e "[BASH] $(date -Iseconds)\n\t$1" >> "${install.log}" 2>&1
|
||||
}
|
||||
|
||||
# Get working directory
|
||||
dbg "Calculating working directory..."
|
||||
DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
dbg "Using working directory $DIR"
|
||||
dbg "Switching to payload directory $DIR/payload/${project.name}.app/Contents/MacOS/"
|
||||
pushd "$DIR/payload/${project.name}.app/Contents/MacOS/" >> "${install.log}" 2>&1
|
||||
|
||||
# Offer to download Java if missing
|
||||
dbg "Checking for Java in payload directory..."
|
||||
if ! ./"${project.name}" --version >> "${install.log}" 2>&1; then
|
||||
dbg "Java was not found"
|
||||
osascript -e "tell app \"Installer\" to display dialog \"Java is required. Please install Java and try again.\""
|
||||
sudo -u "$USER" open "${java.download}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dbg "Java was found in payload directory, running preinstall"
|
||||
./"${project.name}" preinstall >> "${install.log}" 2>&1
|
||||
6
old code/tray/ant/apple/apple.properties
Executable file
@@ -0,0 +1,6 @@
|
||||
# Apple build properties
|
||||
apple.packager.signid=P5DMU6659X
|
||||
# jdk9+ flags
|
||||
# - Tray icon requires workaround https://github.com/dyorgio/macos-tray-icon-fixer/issues/9
|
||||
# - Dark theme requires workaround https://github.com/bobbylight/Darcula/issues/8
|
||||
apple.launch.jigsaw=--add-opens java.desktop/sun.lwawt.macosx=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-exports java.desktop/com.apple.laf=ALL-UNNAMED
|
||||
BIN
old code/tray/ant/apple/certs/apple-codesign.cer
Executable file
BIN
old code/tray/ant/apple/certs/apple-intermediate.cer
Executable file
BIN
old code/tray/ant/apple/certs/apple-packager.cer
Executable file
BIN
old code/tray/ant/apple/dmg-background.png
Executable file
|
After Width: | Height: | Size: 48 KiB |
BIN
old code/tray/ant/apple/dmg-background@2x.png
Executable file
|
After Width: | Height: | Size: 110 KiB |
376
old code/tray/ant/apple/installer.xml
Executable file
@@ -0,0 +1,376 @@
|
||||
<project name="apple-installer" basedir="../../" xmlns:if="ant:if">
|
||||
<property file="ant/project.properties"/>
|
||||
<import file="${basedir}/ant/version.xml"/>
|
||||
<import file="${basedir}/ant/platform-detect.xml"/>
|
||||
|
||||
<!--
|
||||
################################################################
|
||||
# Apple Installer #
|
||||
################################################################
|
||||
-->
|
||||
|
||||
<target name="build-pkg" depends="get-identity,add-certificates,get-version,platform-detect">
|
||||
<echo level="info">Creating installer using pkgbuild</echo>
|
||||
<!--
|
||||
#####################################
|
||||
# Create scripts, payload and pkg #
|
||||
#####################################
|
||||
-->
|
||||
|
||||
<mkdir dir="${build.dir}/scripts/payload"/>
|
||||
|
||||
<!-- Get the os-preferred name for the target architecture -->
|
||||
<condition property="apple.target.arch" value="arm64">
|
||||
<isset property="target.arch.aarch64"/>
|
||||
</condition>
|
||||
<property name="apple.target.arch" value="x86_64" description="fallback value"/>
|
||||
|
||||
<!-- Build app without sandboxing by default-->
|
||||
<property name="build.sandboxed" value="false"/>
|
||||
<antcall target="build-app">
|
||||
<param name="bundle.dir" value="${build.dir}/scripts/payload/${project.name}.app"/>
|
||||
</antcall>
|
||||
<!-- Add a break in the logs -->
|
||||
<antcall target="packaging"/>
|
||||
|
||||
<!-- scripts/ -->
|
||||
<copy file="ant/apple/apple-preinstall.sh.in" tofile="${build.dir}/scripts/preinstall">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
<copy file="ant/apple/apple-postinstall.sh.in" tofile="${build.dir}/scripts/postinstall">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
<chmod perm="a+x" type="file">
|
||||
<fileset dir="${build.dir}/scripts">
|
||||
<include name="preinstall"/>
|
||||
<include name="postinstall"/>
|
||||
</fileset>
|
||||
</chmod>
|
||||
|
||||
<exec executable="pkgbuild" failonerror="true">
|
||||
<arg value="--identifier"/>
|
||||
<arg value="${apple.bundleid}"/>
|
||||
|
||||
<arg value="--nopayload"/>
|
||||
|
||||
<arg value="--install-location"/>
|
||||
<arg value="/Applications/${project.name}.app"/>
|
||||
|
||||
<arg value="--scripts"/>
|
||||
<arg value="${build.dir}/scripts"/>
|
||||
|
||||
<arg value="--version"/>
|
||||
<arg value="${build.version}"/>
|
||||
|
||||
<arg value="--sign" if:true="${codesign.available}"/>
|
||||
<arg value="${codesign.activeid}" if:true="${codesign.available}"/>
|
||||
|
||||
<arg value="${out.dir}/${project.filename}${build.type}-${build.version}-${apple.target.arch}-unbranded.pkg"/>
|
||||
</exec>
|
||||
|
||||
<!-- Branding for qz only -->
|
||||
<condition property="pkg.background" value="pkg-background.tiff" else="pkg-background-blank.tiff">
|
||||
<equals arg1="${project.filename}" arg2="qz-tray"/>
|
||||
</condition>
|
||||
|
||||
<!-- Copy branded resources to out/resources -->
|
||||
<mkdir dir="${out.dir}/resources"/>
|
||||
<copy file="${basedir}/ant/apple/${pkg.background}" tofile="${out.dir}/resources/background.tiff" failonerror="true"/>
|
||||
|
||||
<!-- Create product definition plist that stipulates supported arch -->
|
||||
<copy file="ant/apple/product-def.plist.in" tofile="${build.dir}/product-def.plist">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<!-- Create a distribution.xml file for productbuild -->
|
||||
<exec executable="productbuild" failonerror="true">
|
||||
<arg value="--synthesize"/>
|
||||
|
||||
<arg value="--sign" if:true="${codesign.available}"/>
|
||||
<arg value="${codesign.activeid}" if:true="${codesign.available}"/>
|
||||
|
||||
<arg value="--timestamp"/>
|
||||
|
||||
<arg value="--package"/>
|
||||
<arg value="${out.dir}/${project.filename}${build.type}-${build.version}-${apple.target.arch}-unbranded.pkg"/>
|
||||
|
||||
<arg value="--product"/>
|
||||
<arg value="${build.dir}/product-def.plist"/>
|
||||
|
||||
<arg value="--scripts"/>
|
||||
<arg value="${build.dir}/scripts"/>
|
||||
|
||||
<arg value="${out.dir}/distribution.xml"/>
|
||||
</exec>
|
||||
|
||||
<!-- Inject title, background -->
|
||||
<replace file="${out.dir}/distribution.xml" token="<options customize">
|
||||
<replacevalue><![CDATA[<title>@project.name@ @build.version@</title>
|
||||
<background file="background.tiff" mime-type="image/tiff" alignment="bottomleft" scaling="none"/>
|
||||
<background-darkAqua file="background.tiff" mime-type="image/tiff" alignment="bottomleft" scaling="none"/>
|
||||
<options customize]]></replacevalue>
|
||||
<replacefilter token="@project.name@" value="${project.name}"/>
|
||||
<replacefilter token="@build.version@" value="${build.version}"/>
|
||||
</replace>
|
||||
|
||||
<!-- Create a branded .pkg using productbuild -->
|
||||
<exec executable="productbuild" dir="${out.dir}" failonerror="true">
|
||||
<arg value="--sign" if:true="${codesign.available}"/>
|
||||
<arg value="${codesign.activeid}" if:true="${codesign.available}"/>
|
||||
|
||||
<arg value="--timestamp"/>
|
||||
|
||||
<arg value="--distribution"/>
|
||||
<arg value="${out.dir}/distribution.xml"/>
|
||||
|
||||
<arg value="--resources"/>
|
||||
<arg value="${out.dir}/resources"/>
|
||||
|
||||
<arg value="--product"/>
|
||||
<arg value="${build.dir}/product-def.plist"/>
|
||||
|
||||
<arg value="--package-path"/>
|
||||
<arg value="${project.filename}${build.type}-${build.version}-${apple.target.arch}-unbranded.pkg"/>
|
||||
|
||||
<arg value="${out.dir}/${project.filename}${build.type}-${build.version}-${apple.target.arch}.pkg"/>
|
||||
</exec>
|
||||
|
||||
<!-- Cleanup unbranded version -->
|
||||
<delete file="${out.dir}/${project.filename}${build.type}-${build.version}-${apple.target.arch}-unbranded.pkg"/>
|
||||
</target>
|
||||
|
||||
<target name="build-dmg" depends="get-identity,add-certificates,get-version">
|
||||
<echo level="info">Creating app bundle</echo>
|
||||
<!--
|
||||
#####################################
|
||||
# Create payload and bundle as dmg #
|
||||
#####################################
|
||||
-->
|
||||
|
||||
<!-- Dmg JSON -->
|
||||
<copy file="ant/apple/appdmg.json.in" tofile="${build.dir}/appdmg.json">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<!-- Build app with sandboxing by default-->
|
||||
<property name="build.sandboxed" value="true"/>
|
||||
<antcall target="build-app">
|
||||
<param name="bundle.dir" value="${build.dir}/${project.name}.app"/>
|
||||
</antcall>
|
||||
<!-- Add a break in the logs -->
|
||||
<antcall target="packaging"/>
|
||||
|
||||
<exec executable="appdmg" failonerror="true">
|
||||
<arg value="${build.dir}/appdmg.json"/>
|
||||
<arg value="${out.dir}/${project.filename}${build.type}-${build.version}.dmg"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="build-app" depends="get-identity">
|
||||
<!-- App Bundle -->
|
||||
<mkdir dir="${bundle.dir}"/>
|
||||
|
||||
<!-- Contents/ -->
|
||||
<copy file="ant/apple/apple-bundle.plist.in" tofile="${bundle.dir}/Contents/Info.plist">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<!-- Contents/MacOS/ -->
|
||||
<mkdir dir="${bundle.dir}/Contents/MacOS"/>
|
||||
<copy file="ant/unix/unix-launcher.sh.in" tofile="${bundle.dir}/Contents/MacOS/${project.name}">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<!-- Contents/Resources/ -->
|
||||
<copy todir="${bundle.dir}/Contents/Resources">
|
||||
<fileset dir="${dist.dir}">
|
||||
<include name="${project.filename}.jar"/>
|
||||
<include name="LICENSE.txt"/>
|
||||
<include name="override.crt"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy file="assets/branding/apple-icon.icns" tofile="${bundle.dir}/Contents/Resources/${project.filename}.icns"/>
|
||||
|
||||
<copy file="ant/unix/unix-uninstall.sh.in" tofile="${bundle.dir}/Contents/Resources/uninstall">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<copy todir="${bundle.dir}/Contents/Resources/demo">
|
||||
<fileset dir="${dist.dir}/demo" includes="**"/>
|
||||
</copy>
|
||||
|
||||
<!-- Provision files -->
|
||||
<delete dir="${bundle.dir}/Contents/Resources/provision" failonerror="false"/>
|
||||
<copy todir="${bundle.dir}/Contents/Resources/provision" failonerror="false">
|
||||
<fileset dir="${provision.dir}" includes="**"/>
|
||||
</copy>
|
||||
<chmod perm="a+x" type="file" verbose="true">
|
||||
<fileset dir="${bundle.dir}/Contents/Resources/" casesensitive="false">
|
||||
<!-- Must iterate on parent directory in case "provision" is missing -->
|
||||
<include name="provision/*"/>
|
||||
<exclude name="provision/*.crt"/>
|
||||
<exclude name="provision/*.txt"/>
|
||||
<exclude name="provision/*.json"/>
|
||||
</fileset>
|
||||
</chmod>
|
||||
|
||||
<!-- Java runtime -->
|
||||
<copy todir="${bundle.dir}/Contents/PlugIns/Java.runtime">
|
||||
<fileset dir="${dist.dir}/Java.runtime" includes="**"/>
|
||||
</copy>
|
||||
<copy todir="${bundle.dir}/Contents/Frameworks">
|
||||
<fileset dir="${dist.dir}/libs" includes="**"/>
|
||||
</copy>
|
||||
|
||||
<copy todir="${bundle.dir}">
|
||||
<fileset dir="${bundle.dir}" includes="**"/>
|
||||
</copy>
|
||||
|
||||
<!-- set payload files executable -->
|
||||
<chmod perm="a+x" type="file">
|
||||
<fileset dir="${bundle.dir}">
|
||||
<include name="**/${project.name}"/>
|
||||
<include name="**/Resources/uninstall"/>
|
||||
<include name="**/bin/*"/>
|
||||
<include name="**/lib/jspawnhelper"/>
|
||||
</fileset>
|
||||
</chmod>
|
||||
|
||||
<copy file="ant/apple/apple-entitlements.plist.in" tofile="${build.dir}/apple-entitlements.plist">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<!-- use xargs to loop over and codesign all files-->
|
||||
<echo level="info" message="Signing ${bundle.dir} using ${codesign.activeid}"/>
|
||||
<!-- Find -X fails on spaces but doesn't failonerror, this may lead to overlooked errors. -->
|
||||
<!-- Currently the only file that may contains a space is the main executable which we omit from signing anyway. -->
|
||||
<exec executable="bash" failonerror="true" dir="${bundle.dir}">
|
||||
<arg value="-c"/>
|
||||
<arg value="find -X "." -type f -not -path "*/Contents/MacOS/*" -exec sh -c 'file -I "{}" |grep -m1 "x-mach-binary"|cut -f 1 -d \:' \; |xargs codesign --force -s "${codesign.activeid}" --timestamp --options runtime"/>
|
||||
</exec>
|
||||
<exec executable="codesign" failonerror="true">
|
||||
<arg value="--force"/>
|
||||
<arg value="-s"/>
|
||||
<arg value="${codesign.activeid}"/>
|
||||
<arg value="--timestamp"/>
|
||||
<arg value="--options"/>
|
||||
<arg value="runtime"/>
|
||||
<arg value="--entitlement"/>
|
||||
<arg value="${build.dir}/apple-entitlements.plist"/>
|
||||
<arg value="${bundle.dir}/Contents/PlugIns/Java.runtime/Contents/Home/bin/java"/>
|
||||
<arg value="${bundle.dir}/Contents/PlugIns/Java.runtime/Contents/Home/bin/jcmd"/>
|
||||
<arg value="${bundle.dir}/Contents/PlugIns/Java.runtime"/>
|
||||
</exec>
|
||||
<exec executable="codesign" failonerror="true">
|
||||
<arg value="-s"/>
|
||||
<arg value="${codesign.activeid}"/>
|
||||
<arg value="--timestamp"/>
|
||||
<arg value="--options"/>
|
||||
<arg value="runtime"/>
|
||||
<arg value="--entitlement"/>
|
||||
<arg value="${build.dir}/apple-entitlements.plist"/>
|
||||
<arg value="${bundle.dir}"/>
|
||||
</exec>
|
||||
|
||||
<!-- Verify Java.runtime -->
|
||||
<antcall target="verify-signature">
|
||||
<param name="signed.bundle.name" value="Java.runtime"/>
|
||||
<param name="signed.bundle.dir" value="${bundle.dir}/Contents/PlugIns/Java.runtime"/>
|
||||
</antcall>
|
||||
<!-- Verify QZ Tray.app -->
|
||||
<antcall target="verify-signature" >
|
||||
<param name="signed.bundle.name" value="${project.name}.app"/>
|
||||
<param name="signed.bundle.dir" value="${bundle.dir}"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<target name="add-certificates" depends="get-identity">
|
||||
<!-- Remove expired certificates -->
|
||||
<exec executable="security">
|
||||
<arg value="delete-certificate"/>
|
||||
<arg value="-Z"/>
|
||||
<arg value="A69020D49B47383064ADD5779911822850235953"/>
|
||||
</exec>
|
||||
<exec executable="security">
|
||||
<arg value="delete-certificate"/>
|
||||
<arg value="-Z"/>
|
||||
<arg value="6FD7892971854384AF40FAD1E0E6C56A992BC5EE"/>
|
||||
</exec>
|
||||
<exec executable="security">
|
||||
<arg value="delete-certificate"/>
|
||||
<arg value="-Z"/>
|
||||
<arg value="F7F10838412D9187042EE1EB018794094AFA189A"/>
|
||||
</exec>
|
||||
|
||||
<exec executable="security">
|
||||
<arg value="add-certificates"/>
|
||||
<arg value="${basedir}/ant/apple/certs/apple-packager.cer"/>
|
||||
<arg value="${basedir}/ant/apple/certs/apple-intermediate.cer"/>
|
||||
<arg value="${basedir}/ant/apple/certs/apple-codesign.cer"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="copy-dylibs" if="target.os.mac">
|
||||
<echo level="info">Copying native library files to libs</echo>
|
||||
|
||||
<mkdir dir="${dist.dir}/libs"/>
|
||||
<copy todir="${dist.dir}/libs" flatten="true" verbose="true">
|
||||
<fileset dir="${out.dir}/libs-temp">
|
||||
<!--x86_64-->
|
||||
<include name="**/darwin-x86-64/*" if="target.arch.x86_64"/> <!-- jna/hid4java -->
|
||||
<include name="**/osx-x86_64/*" if="target.arch.x86_64"/> <!-- usb4java -->
|
||||
<include name="**/osx_64/*" if="target.arch.x86_64"/> <!-- jssc -->
|
||||
<!--aarch64-->
|
||||
<include name="**/darwin-aarch64/*" if="target.arch.aarch64"/> <!-- jna/hid4java -->
|
||||
<include name="**/osx-aarch64/*" if="target.arch.aarch64"/> <!-- usb4java -->
|
||||
<include name="**/osx_arm64/*" if="target.arch.aarch64"/> <!-- jssc -->
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<target name="get-identity">
|
||||
<property file="ant/apple/apple.properties"/>
|
||||
<!-- Ensure ${apple.packager.signid} is in Keychain -->
|
||||
<exec executable="bash" failonerror="false" resultproperty="codesign.qz">
|
||||
<arg value="-c"/>
|
||||
<arg value="security find-identity -v |grep '(${apple.packager.signid})'"/>
|
||||
</exec>
|
||||
<!-- Fallback to "-" (ad-hoc) if ${apple.packager.signid} isn't found -->
|
||||
<condition property="codesign.activeid" value="${apple.packager.signid}" else="-">
|
||||
<equals arg1="${codesign.qz}" arg2="0"/>
|
||||
</condition>
|
||||
|
||||
<!-- Fallback to "-" (ad-hoc) if ${apple.packager.signid} isn't found -->
|
||||
<condition property="codesign.available">
|
||||
<equals arg1="${codesign.qz}" arg2="0"/>
|
||||
</condition>
|
||||
|
||||
<!-- Property to show warning later -->
|
||||
<condition property="codesign.selfsign">
|
||||
<equals arg1="${codesign.activeid}" arg2="-"/>
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<target name="verify-signature">
|
||||
<echo level="info">Verifying ${signed.bundle.name} Signature</echo>
|
||||
<echo level="info">Location: ${signed.bundle.dir}</echo>
|
||||
|
||||
<exec executable="codesign" failifexecutionfails="false" resultproperty="signing.status">
|
||||
<arg value="-v"/>
|
||||
<arg value="--strict"/>
|
||||
<arg value="${signed.bundle.dir}"/>
|
||||
</exec>
|
||||
<condition property="message.severity" value="info" else="warn">
|
||||
<equals arg1="${signing.status}" arg2="0"/>
|
||||
</condition>
|
||||
<condition property="message.description"
|
||||
value="Signing passed: Successfully signed"
|
||||
else="Signing failed:: Signing failed (will prevent app from launching)">
|
||||
<equals arg1="${signing.status}" arg2="0"/>
|
||||
</condition>
|
||||
<echo level="${message.severity}">${message.description}</echo>
|
||||
</target>
|
||||
|
||||
<!-- Stub title/separator workaround for build-pkg/build-dmg -->
|
||||
<target name="packaging"/>
|
||||
</project>
|
||||
BIN
old code/tray/ant/apple/pkg-background-blank.tiff
Executable file
BIN
old code/tray/ant/apple/pkg-background.tiff
Executable file
10
old code/tray/ant/apple/product-def.plist.in
Executable file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>arch</key>
|
||||
<array>
|
||||
<string>${apple.target.arch}</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
221
old code/tray/ant/javafx.xml
Executable file
@@ -0,0 +1,221 @@
|
||||
<project name="javafx" default="download-javafx" basedir="..">
|
||||
<property file="ant/project.properties"/>
|
||||
<import file="${basedir}/ant/platform-detect.xml"/>
|
||||
<import file="${basedir}/ant/version.xml"/>
|
||||
|
||||
<!-- TODO: Short-circuit download if host and target are identical? -->
|
||||
<target name="download-javafx" depends="download-javafx-host,download-javafx-target"/>
|
||||
|
||||
<target name="download-javafx-host" unless="${host.fx.exists}" depends="get-javafx-versions,host-fx-exists">
|
||||
<antcall target="download-extract-javafx">
|
||||
<param name="fx.os" value="${host.os}"/>
|
||||
<param name="fx.arch" value="${host.arch}"/>
|
||||
<param name="fx.id" value="${host.fx.id}"/>
|
||||
<param name="fx.basedir" value="${host.fx.basedir}"/>
|
||||
<param name="fx.dir" value="${host.fx.dir}"/>
|
||||
<param name="fx.ver" value="${host.fx.ver}"/>
|
||||
<param name="fx.majver" value="${host.fx.majver}"/>
|
||||
<param name="fx.urlver" value="${host.fx.urlver}"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<target name="download-javafx-target" unless="${target.fx.exists}" depends="get-javafx-versions,target-fx-exists">
|
||||
<antcall target="download-extract-javafx">
|
||||
<param name="fx.os" value="${target.os}"/>
|
||||
<param name="fx.arch" value="${target.arch}"/>
|
||||
<param name="fx.id" value="${target.fx.id}"/>
|
||||
<param name="fx.basedir" value="${target.fx.basedir}"/>
|
||||
<param name="fx.dir" value="${target.fx.dir}"/>
|
||||
<param name="fx.majver" value="${target.fx.majver}"/>
|
||||
<param name="fx.urlver" value="${target.fx.urlver}"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<target name="host-fx-exists" depends="platform-detect">
|
||||
<!-- Host fx is saved to lib/ -->
|
||||
<property name="host.fx.basedir" value="${basedir}/lib"/>
|
||||
<property name="host.fx.id" value="javafx-${host.os}-${host.arch}-${host.fx.urlver}"/>
|
||||
<property name="host.fx.dir" value="${host.fx.basedir}/${host.fx.id}"/>
|
||||
<mkdir dir="${host.fx.dir}"/>
|
||||
|
||||
<!-- File to look for: "glass.dll", "libglass.dylib" or "libglass.so" -->
|
||||
<property name="host.libglass" value="${host.libprefix}glass.${host.libext}"/>
|
||||
|
||||
<!-- Grab the first file match -->
|
||||
<first id="host.fx.files">
|
||||
<fileset dir="${host.fx.dir}">
|
||||
<include name="**/${host.libglass}"/>
|
||||
</fileset>
|
||||
</first>
|
||||
<!-- Convert the file to a usable string -->
|
||||
<pathconvert property="host.fx.path" refid="host.fx.files"/>
|
||||
|
||||
<!-- Set our flag if found -->
|
||||
<condition property="host.fx.exists">
|
||||
<not><equals arg1="${host.fx.path}" arg2=""/></not>
|
||||
</condition>
|
||||
|
||||
<!-- Human readable message -->
|
||||
<condition property="host.fx.message"
|
||||
value="JavaFX host platform file ${host.libglass} found, skipping download.${line.separator}Location: ${host.fx.path}"
|
||||
else="JavaFX host platform file ${host.libglass} is missing, will download.${line.separator}Searched: ${host.fx.dir}">
|
||||
<isset property="host.fx.exists"/>
|
||||
</condition>
|
||||
|
||||
<echo level="info">${host.fx.message}</echo>
|
||||
</target>
|
||||
|
||||
<target name="target-fx-exists">
|
||||
<!-- Target fx is saved to out/ -->
|
||||
<property name="target.fx.basedir" value="${out.dir}"/>
|
||||
<property name="target.fx.id" value="javafx-${target.os}-${target.arch}-${target.fx.urlver}"/>
|
||||
<property name="target.fx.dir" value="${target.fx.basedir}/${target.fx.id}"/>
|
||||
<mkdir dir="${target.fx.dir}"/>
|
||||
|
||||
<!-- File to look for: "glass.dll", "libglass.dylib" or "libglass.so" -->
|
||||
<property name="target.libglass" value="${target.libprefix}glass.${target.libext}"/>
|
||||
|
||||
<!-- Grab the first file match -->
|
||||
<first id="target.fx.files">
|
||||
<fileset dir="${target.fx.dir}">
|
||||
<!-- look for "glass.dll", "libglass.dylib" or "libglass.so" -->
|
||||
<include name="**/${target.libglass}"/>
|
||||
</fileset>
|
||||
</first>
|
||||
<!-- Convert the file to a usable string -->
|
||||
<pathconvert property="target.fx.path" refid="target.fx.files"/>
|
||||
|
||||
<!-- Set our flag if found -->
|
||||
<condition property="target.fx.exists">
|
||||
<not><equals arg1="${target.fx.path}" arg2=""/></not>
|
||||
</condition>
|
||||
|
||||
<!-- Human readable message -->
|
||||
<condition property="target.fx.message"
|
||||
value="JavaFX target platform file ${target.libglass} found, skipping download.${line.separator}Location: ${target.fx.path}"
|
||||
else="JavaFX target platform file ${target.libglass} is missing, will download.${line.separator}Searched: ${target.fx.dir}">
|
||||
<isset property="target.fx.exists"/>
|
||||
</condition>
|
||||
|
||||
<echo level="info">${target.fx.message}</echo>
|
||||
</target>
|
||||
|
||||
<!--
|
||||
Populates: host.fx.ver, host.fx.urlver, target.fx.ver, target.fx.urlver
|
||||
|
||||
- Converts version to a usable URL format
|
||||
- Leverage older releases for Intel builds until upstream bug report SUPQZ-14 is fixed
|
||||
|
||||
To build: We need javafx to download a javafx which matches "host.os" and "host.arch"
|
||||
To package: We need javafx to download a javafx which matches "target.os" and "target.arch"
|
||||
-->
|
||||
<target name="get-javafx-versions" depends="platform-detect">
|
||||
<!-- Fallback to sane values -->
|
||||
<property name="host.fx.ver" value="${javafx.version}"/>
|
||||
<property name="target.fx.ver" value="${javafx.version}"/>
|
||||
|
||||
<!-- Handle pesky url "." = "-" differences -->
|
||||
<loadresource property="host.fx.urlver">
|
||||
<propertyresource name="host.fx.ver"/>
|
||||
<filterchain>
|
||||
<tokenfilter>
|
||||
<filetokenizer/>
|
||||
<replacestring from="." to="-"/>
|
||||
</tokenfilter>
|
||||
</filterchain>
|
||||
</loadresource>
|
||||
<loadresource property="target.fx.urlver">
|
||||
<propertyresource name="target.fx.ver"/>
|
||||
<filterchain>
|
||||
<tokenfilter>
|
||||
<filetokenizer/>
|
||||
<replacestring from="." to="-"/>
|
||||
</tokenfilter>
|
||||
</filterchain>
|
||||
</loadresource>
|
||||
<property description="suppress property warning" name="target.fx.urlver" value="something went wrong"/>
|
||||
<property description="suppress property warning" name="host.fx.urlver" value="something went wrong"/>
|
||||
|
||||
<!-- Calculate our javafx "major" version -->
|
||||
<loadresource property="host.fx.majver">
|
||||
<propertyresource name="host.fx.ver"/>
|
||||
<filterchain>
|
||||
<replaceregex pattern="[-_.].*" replace="" />
|
||||
</filterchain>
|
||||
</loadresource>
|
||||
<loadresource property="target.fx.majver">
|
||||
<propertyresource name="target.fx.ver"/>
|
||||
<filterchain>
|
||||
<replaceregex pattern="[-_.].*" replace="" />
|
||||
</filterchain>
|
||||
</loadresource>
|
||||
<property description="suppress property warning" name="target.fx.majver" value="something went wrong"/>
|
||||
<property description="suppress property warning" name="host.fx.majver" value="something went wrong"/>
|
||||
|
||||
<echo level="info">
|
||||
JavaFX host platform:
|
||||
Version: ${host.fx.ver} (${host.os}, ${host.arch})
|
||||
Major Version: ${host.fx.majver}
|
||||
URLs: "${host.fx.urlver}"
|
||||
|
||||
JavaFX target platform:
|
||||
Version: ${target.fx.ver} (${target.os}, ${target.arch})
|
||||
Major Version: ${target.fx.majver}
|
||||
URLs: ""${target.fx.urlver}"
|
||||
</echo>
|
||||
</target>
|
||||
|
||||
<!-- Downloads and extracts javafx for the specified platform -->
|
||||
<target name="download-extract-javafx">
|
||||
<!-- Cleanup old versions -->
|
||||
<delete includeemptydirs="true" defaultexcludes="false">
|
||||
<fileset dir="${fx.basedir}">
|
||||
<include name="javafx*/"/>
|
||||
</fileset>
|
||||
</delete>
|
||||
<mkdir dir="${fx.dir}"/>
|
||||
|
||||
<!-- Valid os values: "windows", "linux", "osx" -->
|
||||
<!-- translate "mac" to "osx" -->
|
||||
<condition property="fx.os.fixed" value="osx" else="${fx.os}">
|
||||
<equals arg1="${fx.os}" arg2="mac"/>
|
||||
</condition>
|
||||
|
||||
<!-- Valid arch values: "x64", "aarch64", "x86" -->
|
||||
<!-- translate "x86_64" to "x64" -->
|
||||
<condition property="fx.arch.fixed" value="x64">
|
||||
<or>
|
||||
<equals arg1="${fx.arch}" arg2="x86_64"/>
|
||||
<and>
|
||||
<!-- TODO: Remove "aarch64" to "x64" when windows aarch64 binaries become available -->
|
||||
<equals arg1="${fx.arch}" arg2="aarch64"/>
|
||||
<equals arg1="${fx.os}" arg2="windows"/>
|
||||
</and>
|
||||
<and>
|
||||
<!-- TODO: Remove "riscv" to "x64" when linux riscv64 binaries become available -->
|
||||
<equals arg1="${fx.arch}" arg2="riscv64"/>
|
||||
<equals arg1="${fx.os}" arg2="linux"/>
|
||||
</and>
|
||||
</or>
|
||||
</condition>
|
||||
<property name="fx.arch.fixed" value="${fx.arch}" description="fallback value"/>
|
||||
|
||||
<!-- Fix underscore when "monocle" is missing -->
|
||||
<condition property="fx.url" value="${javafx.mirror}/${fx.majver}/openjfx-${fx.urlver}_${fx.os.fixed}-${fx.arch.fixed}_bin-sdk.zip">
|
||||
<not>
|
||||
<contains string="${fx.urlver}" substring="monocle"/>
|
||||
</not>
|
||||
</condition>
|
||||
|
||||
<property name="fx.url" value="${javafx.mirror}/${fx.majver}/openjfx-${fx.urlver}-${fx.os.fixed}-${fx.arch.fixed}_bin-sdk.zip"/>
|
||||
<property name="fx.zip" value="${out.dir}/${fx.id}.zip"/>
|
||||
|
||||
<echo level="info">Downloading JavaFX from ${fx.url}</echo>
|
||||
<echo level="info">Temporarily saving JavaFX to ${fx.zip}</echo>
|
||||
|
||||
<mkdir dir="${out.dir}"/>
|
||||
<get src="${fx.url}" verbose="true" dest="${fx.zip}"/>
|
||||
<unzip src="${fx.zip}" dest="${fx.dir}" overwrite="true"/>
|
||||
<delete file="${fx.zip}"/>
|
||||
</target>
|
||||
</project>
|
||||
BIN
old code/tray/ant/lib/jsign-7.1.jar
Executable file
109
old code/tray/ant/lib/slim-icu.py
Executable file
@@ -0,0 +1,109 @@
|
||||
# 2018 Yohanes Nugroho <yohanes@gmail.com> (@yohanes)
|
||||
#
|
||||
# 1. Download icu4j source code, build using ant.
|
||||
# It will generate icu4j.jar and icu4j-charset.jar
|
||||
#
|
||||
# 2. Run slim-icu.py to generate slim version.
|
||||
#
|
||||
# To invoke from ant, add python to $PATH
|
||||
# and add the following to build.xml:
|
||||
#
|
||||
# <target name="distill-icu" depends="init">
|
||||
# <exec executable="python">
|
||||
# <arg line="ant/lib/slim-icu.py lib/charsets"/>
|
||||
# </exec>
|
||||
# </target>
|
||||
#
|
||||
# ... then call: ant distill-icu
|
||||
#
|
||||
# 3. Overwrite files in lib/charsets/
|
||||
|
||||
# slim ICU
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
import zipfile
|
||||
from zipfile import ZipFile
|
||||
|
||||
directory = str(Path(__file__).resolve().parent)
|
||||
if len(sys.argv) > 1:
|
||||
directory = sys.argv[1]
|
||||
|
||||
mode = zipfile.ZIP_DEFLATED
|
||||
|
||||
|
||||
def keep_file(filename):
|
||||
# skip all break iterators
|
||||
if filename.endswith(".brk") \
|
||||
or filename.endswith(".dict") \
|
||||
or filename.endswith("unames.icu") \
|
||||
or filename.endswith("ucadata.icu") \
|
||||
or filename.endswith(".spp"):
|
||||
return False
|
||||
|
||||
# keep english and arabic
|
||||
if filename.startswith("en") \
|
||||
or filename.startswith("ar") \
|
||||
or not filename.endswith(".res"):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
zin = ZipFile(os.path.join(directory, 'icu4j.jar'), 'r')
|
||||
zout = ZipFile(os.path.join(directory, 'icu4j-slim.jar'), 'w', mode)
|
||||
|
||||
for item in zin.infolist():
|
||||
buff = zin.read(item.filename)
|
||||
print(item.filename)
|
||||
|
||||
if keep_file(item.filename):
|
||||
print("Keep")
|
||||
zout.writestr(item, buff)
|
||||
else:
|
||||
print("Remove")
|
||||
|
||||
zout.close()
|
||||
zin.close()
|
||||
|
||||
|
||||
def keep_charset_file(filename):
|
||||
to_remove = [
|
||||
"cns-11643-1992.cnv",
|
||||
"ebcdic-xml-us.cnv",
|
||||
"euc-jp-2007.cnv",
|
||||
"euc-tw-2014.cnv",
|
||||
"gb18030.cnv",
|
||||
"ibm-1363_P11B-1998.cnv",
|
||||
"ibm-1364_P110-2007.cnv",
|
||||
"ibm-1371_P100-1999.cnv",
|
||||
"ibm-1373_P100-2002.cnv",
|
||||
"ibm-1375_P100-2008.cnv",
|
||||
"ibm-1383_P110-1999.cnv",
|
||||
"ibm-1386_P100-2001.cnv",
|
||||
"ibm-1388_P103-2001.cnv",
|
||||
"ibm-1390_P110-2003.cnv"
|
||||
]
|
||||
|
||||
for i in to_remove:
|
||||
if i in filename:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
zin = ZipFile(os.path.join(directory, 'icu4j-charset.jar'), 'r')
|
||||
zout = ZipFile(os.path.join(directory, 'icu4j-charset-slim.jar'), 'w', mode)
|
||||
|
||||
for item in zin.infolist():
|
||||
buff = zin.read(item.filename)
|
||||
print(item.filename, end=' ')
|
||||
|
||||
if keep_charset_file(item.filename):
|
||||
print("Keep")
|
||||
zout.writestr(item, buff)
|
||||
else:
|
||||
print("Remove")
|
||||
|
||||
zout.close()
|
||||
zin.close()
|
||||
69
old code/tray/ant/linux/installer.xml
Executable file
@@ -0,0 +1,69 @@
|
||||
<project name="linux-installer" basedir="../../">
|
||||
<property file="ant/project.properties"/>
|
||||
<property file="ant/linux/linux.properties"/>
|
||||
<import file="${basedir}/ant/version.xml"/>
|
||||
<import file="${basedir}/ant/platform-detect.xml"/>
|
||||
|
||||
<target name="build-run" depends="get-version,platform-detect">
|
||||
<echo level="info">Creating installer using makeself</echo>
|
||||
|
||||
<!-- Get the os-preferred name for the target architecture -->
|
||||
<condition property="linux.target.arch" value="arm64">
|
||||
<isset property="target.arch.aarch64"/>
|
||||
</condition>
|
||||
<property name="linux.target.arch" value="${target.arch}" description="fallback value"/>
|
||||
|
||||
<copy file="assets/branding/linux-icon.svg" tofile="${dist.dir}/${project.filename}.svg"/>
|
||||
|
||||
<mkdir dir="${build.dir}/scripts"/>
|
||||
<copy file="ant/linux/linux-installer.sh.in" tofile="${dist.dir}/install">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<copy file="ant/unix/unix-launcher.sh.in" tofile="${dist.dir}/${project.filename}">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<copy file="ant/unix/unix-uninstall.sh.in" tofile="${dist.dir}/uninstall">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<chmod perm="a+x" type="file">
|
||||
<fileset dir="${dist.dir}">
|
||||
<include name="**/${project.filename}"/>
|
||||
<include name="**/install"/>
|
||||
<include name="**/uninstall"/>
|
||||
</fileset>
|
||||
</chmod>
|
||||
|
||||
<exec executable="makeself" failonerror="true">
|
||||
<arg value="${dist.dir}"/>
|
||||
<arg value="${out.dir}/${project.filename}${build.type}-${build.version}-${linux.target.arch}.run"/>
|
||||
<arg value="${project.name} Installer"/>
|
||||
<arg value="./install"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
<target name="copy-solibs" if="target.os.linux">
|
||||
<echo level="info">Copying native library files to libs</echo>
|
||||
|
||||
<mkdir dir="${dist.dir}/libs"/>
|
||||
<copy todir="${dist.dir}/libs" flatten="true" verbose="true">
|
||||
<fileset dir="${out.dir}/libs-temp">
|
||||
<!--x86_64-->
|
||||
<include name="**/linux-x86-64/*" if="target.arch.x86_64"/> <!-- jna/hid4java -->
|
||||
<include name="**/linux-x86_64/*" if="target.arch.x86_64"/> <!-- usb4java -->
|
||||
<include name="**/linux_64/*" if="target.arch.x86_64"/> <!-- jssc -->
|
||||
<!--aarch64-->
|
||||
<include name="**/linux-aarch64/*" if="target.arch.aarch64"/> <!-- jna/hid4java/usb4java -->
|
||||
<include name="**/linux_arm64/*" if="target.arch.aarch64"/> <!-- jssc -->
|
||||
<!--arm32-->
|
||||
<include name="**/linux-arm/*" if="target.arch.arm32"/> <!-- jna/hid4java/usb4java -->
|
||||
<include name="**/linux_arm/*" if="target.arch.arm32"/> <!-- jssc -->
|
||||
<!--riscv64-->
|
||||
<include name="**/linux-riscv64/*" if="target.arch.riscv64"/> <!-- jna/hid4java -->
|
||||
<include name="**/linux_riscv64/*" if="target.arch.riscv64"/> <!-- jssc -->
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
</project>
|
||||
68
old code/tray/ant/linux/linux-installer.sh.in
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Halt on first error
|
||||
set -e
|
||||
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "This script must be run with root (sudo) privileges" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Console colors
|
||||
RED="\\x1B[1;31m";GREEN="\\x1B[1;32m";YELLOW="\\x1B[1;33m";PLAIN="\\x1B[0m"
|
||||
|
||||
# Statuses
|
||||
SUCCESS=" [${GREEN}success${PLAIN}]"
|
||||
FAILURE=" [${RED}failure${PLAIN}]"
|
||||
WARNING=" [${YELLOW}warning${PLAIN}]"
|
||||
|
||||
mask=755
|
||||
|
||||
echo -e "Starting install...\n"
|
||||
|
||||
# Clear the log for writing
|
||||
> "${install.log}"
|
||||
|
||||
run_task () {
|
||||
echo -e "Running $1 task..."
|
||||
if [ -n "$DEBUG" ]; then
|
||||
"./${project.filename}" $@ && ret_val=$? || ret_val=$?
|
||||
else
|
||||
"./${project.filename}" $@ &>> "${install.log}" && ret_val=$? || ret_val=$?
|
||||
fi
|
||||
|
||||
if [ $ret_val -eq 0 ]; then
|
||||
echo -e " $SUCCESS Task $1 was successful"
|
||||
else
|
||||
if [ "$1" == "spawn" ]; then
|
||||
echo -e " $WARNING Task $1 skipped. You'll have to start ${project.name} manually."
|
||||
return
|
||||
fi
|
||||
echo -e " $FAILURE Task $1 failed.\n\nRe-run with DEBUG=true for more information."
|
||||
false # throw error
|
||||
fi
|
||||
}
|
||||
|
||||
# Ensure java is installed and working before starting
|
||||
"./${project.filename}" --version
|
||||
|
||||
# Make a temporary jar for preliminary installation steps
|
||||
run_task preinstall
|
||||
|
||||
run_task install --dest "/opt/${project.filename}"
|
||||
|
||||
# We should be installed now, generate the certificate
|
||||
pushd "/opt/${project.filename}" &> /dev/null
|
||||
run_task certgen
|
||||
|
||||
# Tell the desktop to look for new mimetypes in the background
|
||||
umask_bak="$(umask)"
|
||||
umask 0002 # more permissive umask for mimetype registration
|
||||
update-desktop-database &> /dev/null &
|
||||
umask "$umask_bak"
|
||||
|
||||
echo "Installation complete... Starting ${project.name}..."
|
||||
# spawn itself as a regular user, inheriting environment
|
||||
run_task spawn "/opt/${project.filename}/${project.filename}"
|
||||
|
||||
popd &> /dev/null
|
||||
2
old code/tray/ant/linux/linux.properties
Executable file
@@ -0,0 +1,2 @@
|
||||
# Expose UNIXToolkit.getGtkVersion
|
||||
linux.launch.jigsaw=--add-opens java.desktop/sun.awt=ALL-UNNAMED
|
||||
254
old code/tray/ant/platform-detect.xml
Executable file
@@ -0,0 +1,254 @@
|
||||
<project name="host-info" default="platform-detect" basedir="..">
|
||||
<property file="ant/project.properties"/>
|
||||
<!--
|
||||
Detects and echos host and target information
|
||||
|
||||
String:
|
||||
- host.os, host.arch, host.libext, host.libprefix
|
||||
- target.os, target.arch, target.libext, target.libprefix
|
||||
|
||||
Booleans:
|
||||
- host.${host.arch}=true, host.${host.os}=true
|
||||
- target.${target.arch}=true, target.${target.os}=true
|
||||
-->
|
||||
<target name="platform-detect" depends="get-target-os,get-target-arch,get-libext">
|
||||
<!-- Echo host information -->
|
||||
<antcall target="echo-platform">
|
||||
<param name="title" value="Host"/>
|
||||
<param name="prefix" value="host"/>
|
||||
<param name="prefix.os" value="${host.os}"/>
|
||||
<param name="prefix.arch" value="${host.arch}"/>
|
||||
<param name="prefix.libext" value="${host.libext}"/>
|
||||
</antcall>
|
||||
<!-- Echo target information -->
|
||||
<antcall target="echo-platform">
|
||||
<param name="title" value="Target"/>
|
||||
<param name="prefix" value="target"/>
|
||||
<param name="prefix.os" value="${target.os}"/>
|
||||
<param name="prefix.arch" value="${target.arch}"/>
|
||||
<param name="prefix.libext" value="${target.libext}"/>
|
||||
</antcall>
|
||||
</target>
|
||||
<target name="echo-platform">
|
||||
<!-- Make output more readable -->
|
||||
|
||||
<!-- Boolean platform.os.foo value -->
|
||||
<condition property="os.echo" value="${prefix}.os.windows">
|
||||
<isset property="${prefix}.os.windows"/>
|
||||
</condition>
|
||||
<condition property="os.echo" value="${prefix}.os.mac">
|
||||
<isset property="${prefix}.os.mac"/>
|
||||
</condition>
|
||||
<property name="os.echo" value="${prefix}.os.linux" description="fallback value"/>
|
||||
|
||||
<!-- Boolean target.arch.foo value -->
|
||||
<condition property="arch.echo" value="${prefix}.arch.aarch64">
|
||||
<isset property="${prefix}.arch.aarch64"/>
|
||||
</condition>
|
||||
<property name="arch.echo" value="${prefix}.arch.x86_64" description="fallback value"/>
|
||||
|
||||
<echo level="info">
|
||||
${title} platform:
|
||||
${prefix}.os: "${prefix.os}"
|
||||
${prefix}.arch: "${prefix.arch}"
|
||||
${prefix}.libext: "${prefix.libext}"
|
||||
${os.echo}: true
|
||||
${arch.echo}: true
|
||||
</echo>
|
||||
|
||||
</target>
|
||||
|
||||
<!-- Force Linux runtime. Set by "makeself" target -->
|
||||
<target name="target-os-linux">
|
||||
<!-- String value -->
|
||||
<property name="target.os" value ="linux"/>
|
||||
<!-- Boolean value -->
|
||||
<property name="target.os.linux" value="true"/>
|
||||
</target>
|
||||
|
||||
<!-- Force Linux runtime. Set by "nsis" target -->
|
||||
<target name="target-os-windows">
|
||||
<!-- String value -->
|
||||
<property name="target.os" value ="windows"/>
|
||||
<!-- Boolean value -->
|
||||
<property name="target.os.windows" value="true"/>
|
||||
</target>
|
||||
|
||||
<!-- Force Linux runtime. Set by "pkgbuild", "dmg" targets -->
|
||||
<target name="target-os-mac">
|
||||
<!-- String value -->
|
||||
<property name="target.os" value ="mac"/>
|
||||
<!-- Boolean value -->
|
||||
<property name="target.os.mac" value="true"/>
|
||||
</target>
|
||||
|
||||
<target name="get-target-os" depends="get-host-os">
|
||||
<!-- Suppress property warning :) -->
|
||||
<condition description="suppress property warning (no-op)"
|
||||
property="target.os" value="${target.os}">
|
||||
<isset property="target.os"/>
|
||||
</condition>
|
||||
<!-- Set Boolean if only the String was set -->
|
||||
<condition property="target.os.windows">
|
||||
<and>
|
||||
<isset property="target.os"/>
|
||||
<equals arg1="${target.os}" arg2="windows"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="target.os.mac">
|
||||
<and>
|
||||
<isset property="target.os"/>
|
||||
<equals arg1="${target.os}" arg2="mac"/>
|
||||
</and>
|
||||
</condition>
|
||||
<condition property="target.os.linux">
|
||||
<and>
|
||||
<isset property="target.os"/>
|
||||
<equals arg1="${target.os}" arg2="linux"/>
|
||||
</and>
|
||||
</condition>
|
||||
|
||||
<!-- Fallback to host boolean values if target values aren't specified -->
|
||||
<property name="target.os" value="${host.os}" description="fallback value"/>
|
||||
<condition property="target.os.windows" description="fallback value">
|
||||
<equals arg1="${target.os}" arg2="windows"/>
|
||||
</condition>
|
||||
<condition property="target.os.mac" description="fallback value">
|
||||
<equals arg1="${target.os}" arg2="mac"/>
|
||||
</condition>
|
||||
<condition property="target.os.linux" description="fallback value">
|
||||
<equals arg1="${target.os}" arg2="linux"/>
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<!-- Calculate target architecture based on ${target.arch} value -->
|
||||
<target name="get-target-arch" depends="get-host-arch">
|
||||
<!-- Fallback to ${host.arch} if not specified -->
|
||||
<property name="target.arch" value="${host.arch}" description="fallback value"/>
|
||||
<condition property="target.arch.x86_64">
|
||||
<equals arg1="amd64" arg2="${target.arch}"/>
|
||||
</condition>
|
||||
<condition property="target.arch.x86_64">
|
||||
<equals arg1="x86_64" arg2="${target.arch}"/>
|
||||
</condition>
|
||||
<condition property="target.arch.aarch64">
|
||||
<equals arg1="aarch64" arg2="${target.arch}"/>
|
||||
</condition>
|
||||
<condition property="target.arch.riscv64">
|
||||
<equals arg1="riscv64" arg2="${target.arch}"/>
|
||||
</condition>
|
||||
<!-- Warning: Placeholder only! 32-bit builds are not supported -->
|
||||
<condition property="target.arch.arm32">
|
||||
<equals arg1="arm32" arg2="${target.arch}"/>
|
||||
</condition>
|
||||
<condition property="target.arch.x86">
|
||||
<equals arg1="x86" arg2="${target.arch}"/>
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<!-- Calculate native file extension -->
|
||||
<target name="get-libext" depends="get-host-os">
|
||||
<!-- Some constants -->
|
||||
<property name="windows.libext" value="dll"/>
|
||||
<property name="mac.libext" value="dylib"/>
|
||||
<property name="linux.libext" value="so"/>
|
||||
<!-- Host uses "dll" -->
|
||||
<condition property="host.libext" value="${windows.libext}">
|
||||
<isset property="host.os.windows"/>
|
||||
</condition>
|
||||
<!-- Host uses "dylib" -->
|
||||
<condition property="host.libext" value="${mac.libext}">
|
||||
<isset property="host.os.mac"/>
|
||||
</condition>
|
||||
<!-- Host uses "so" -->
|
||||
<condition property="host.libext" value="${linux.libext}">
|
||||
<isset property="host.os.linux"/>
|
||||
</condition>
|
||||
<!-- Target uses "dll" -->
|
||||
<condition property="target.libext" value="${windows.libext}">
|
||||
<isset property="target.os.windows"/>
|
||||
</condition>
|
||||
<!-- Target uses "dylib" -->
|
||||
<condition property="target.libext" value="${mac.libext}">
|
||||
<isset property="target.os.mac"/>
|
||||
</condition>
|
||||
<!-- Target uses "so" -->
|
||||
<condition property="target.libext" value="${linux.libext}">
|
||||
<isset property="target.os.linux"/>
|
||||
</condition>
|
||||
|
||||
<!-- Target uses "" or "lib" prefix for native files -->
|
||||
<condition property="host.libprefix" value="" else="lib">
|
||||
<isset property="host.os.windows"/>
|
||||
</condition>
|
||||
|
||||
<!-- Host uses "" or "lib" prefix for native files -->
|
||||
<condition property="target.libprefix" value="" else="lib">
|
||||
<isset property="target.os.windows"/>
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<!-- Calculate and standardize host architecture based on ${os.arch} value -->
|
||||
<target name="get-host-arch">
|
||||
<!-- Boolean value (x86_64) -->
|
||||
<condition property="host.arch.x86_64">
|
||||
<equals arg1="amd64" arg2="${os.arch}"/>
|
||||
</condition>
|
||||
<condition property="host.arch.x86_64">
|
||||
<equals arg1="x86_64" arg2="${os.arch}"/>
|
||||
</condition>
|
||||
|
||||
<!-- Boolean value (aarch64) -->
|
||||
<condition property="host.arch.aarch64">
|
||||
<equals arg1="aarch64" arg2="${os.arch}"/>
|
||||
</condition>
|
||||
|
||||
<!-- Boolean value (x86 - unsupported) -->
|
||||
<condition property="host.arch.x86">
|
||||
<equals arg1="x86" arg2="${os.arch}"/>
|
||||
</condition>
|
||||
|
||||
<!-- String value (aarch64) -->
|
||||
<condition property="host.arch" value="aarch64">
|
||||
<equals arg1="aarch64" arg2="${os.arch}"/>
|
||||
</condition>
|
||||
<!-- String value (x86) -->
|
||||
<condition property="host.arch" value="x86">
|
||||
<equals arg1="x86" arg2="${os.arch}"/>
|
||||
</condition>
|
||||
<condition property="host.arch" value="x86">
|
||||
<equals arg1="i386" arg2="${os.arch}"/>
|
||||
</condition>
|
||||
|
||||
<!-- String value (x86_64 - fallback, most common) -->
|
||||
<property name="host.arch" value="x86_64" description="fallback value"/>
|
||||
</target>
|
||||
|
||||
<!-- Calculate the host os -->
|
||||
<target name="get-host-os">
|
||||
<!-- Boolean value -->
|
||||
<condition property="host.os.windows" value="true">
|
||||
<os family="windows"/>
|
||||
</condition>
|
||||
<condition property="host.os.mac" value="true">
|
||||
<os family="mac"/>
|
||||
</condition>
|
||||
<condition property="host.os.linux" value="true">
|
||||
<and>
|
||||
<os family="unix"/>
|
||||
<not>
|
||||
<os family="mac"/>
|
||||
</not>
|
||||
</and>
|
||||
</condition>
|
||||
|
||||
<!-- String value -->
|
||||
<condition property="host.os" value="windows">
|
||||
<os family="windows"/>
|
||||
</condition>
|
||||
<condition property="host.os" value="mac">
|
||||
<os family="mac"/>
|
||||
</condition>
|
||||
<property name="host.os" value="linux" description="fallback value"/>
|
||||
</target>
|
||||
</project>
|
||||
5
old code/tray/ant/private/private.properties
Executable file
@@ -0,0 +1,5 @@
|
||||
signing.alias=self-signed
|
||||
signing.keystore=ant/private/qz.ks
|
||||
signing.keypass=jzebraonfire
|
||||
signing.storepass=jzebraonfire
|
||||
signing.algorithm=SHA-256
|
||||
62
old code/tray/ant/project.properties
Executable file
@@ -0,0 +1,62 @@
|
||||
vendor.name=qz
|
||||
vendor.company=QZ Industries, LLC
|
||||
vendor.website=https://qz.io
|
||||
vendor.email=support@qz.io
|
||||
|
||||
project.name=QZ Tray
|
||||
project.filename=qz-tray
|
||||
project.datadir=qz
|
||||
|
||||
install.opts=-Djna.nosys=true
|
||||
launch.opts=-Xms512m ${install.opts}
|
||||
install.log=/tmp/${project.datadir}-install.log
|
||||
# jdk9+ flags
|
||||
# - Dark theme requires workaround https://github.com/bobbylight/Darcula/issues/8
|
||||
launch.jigsaw=--add-exports java.desktop/sun.swing=ALL-UNNAMED
|
||||
launch.overrides=QZ_OPTS
|
||||
|
||||
src.dir=${basedir}/src
|
||||
out.dir=${basedir}/out
|
||||
build.dir=${out.dir}/build
|
||||
dist.dir=${out.dir}/dist
|
||||
|
||||
sign.lib.dir=${out.dir}/jar-signed
|
||||
|
||||
jar.compress=true
|
||||
jar.index=true
|
||||
|
||||
# Separate native lib resources from jars
|
||||
separate.static.libs=true
|
||||
|
||||
# See also qz.common.Constants.java
|
||||
javac.source=11
|
||||
javac.target=11
|
||||
java.download=https://bell-sw.com/pages/downloads/#/java-11-lts
|
||||
|
||||
# Java vendor to bundle into software (e.g. "*BellSoft|Adoptium|Microsoft|Amazon|IBM")
|
||||
jlink.java.vendor="BellSoft"
|
||||
# Java vendor to bundle into software (e.g. "11.0.17+7")
|
||||
jlink.java.version="11.0.27+9"
|
||||
# Java garbage collector flavor to use (e.g. "hotspot|openj9")
|
||||
jlink.java.gc="hotspot"
|
||||
# Java garbage collector version to use (e.g. openj9: "0.35.0", zulu: "11.62.17")
|
||||
jlink.java.gc.version="gc-ver-is-empty"
|
||||
# Bundle a locally built copy of Java instead
|
||||
jlink.java.target=/home/ske087/quality_recticel/jdk-11.0.20-full
|
||||
|
||||
# Skip bundling the java runtime
|
||||
jre.skip=false
|
||||
|
||||
# JavaFX version
|
||||
javafx.version=19_monocle
|
||||
javafx.mirror=https://download2.gluonhq.com/openjfx
|
||||
|
||||
# Provisioning
|
||||
# provision.file=${basedir}/provision.json
|
||||
provision.dir=${dist.dir}/provision
|
||||
|
||||
# Mask tray toggle (Apple only)
|
||||
java.mask.tray=true
|
||||
|
||||
# Workaround to delay expansion of $${foo} (e.g. shell scripts)
|
||||
dollar=$
|
||||
196
old code/tray/ant/signing.xml
Executable file
@@ -0,0 +1,196 @@
|
||||
<project name="signing-helpers" basedir="../">
|
||||
<property file="ant/project.properties"/>
|
||||
|
||||
<!-- Custom code-signing properties -->
|
||||
<property file="${basedir}/../private/private.properties"/>
|
||||
|
||||
<!-- Fallback code-signing properties -->
|
||||
<property file="ant/private/private.properties"/>
|
||||
|
||||
<!-- Locate first jsign-x.x.x.jar sorted name desc -->
|
||||
<target name="find-jsign">
|
||||
<sort id="jsign.sorted">
|
||||
<fileset dir="${basedir}/ant/lib/">
|
||||
<include name="jsign*.jar"/>
|
||||
</fileset>
|
||||
<reverse xmlns="antlib:org.apache.tools.ant.types.resources.comparators"/>
|
||||
</sort>
|
||||
<first id="jsign.first">
|
||||
<resources refid="jsign.sorted"/>
|
||||
</first>
|
||||
<pathconvert property="jsign.path" refid="jsign.first">
|
||||
<identitymapper/>
|
||||
</pathconvert>
|
||||
|
||||
<echo message="Found jsign: ${jsign.path}"/>
|
||||
</target>
|
||||
|
||||
<!-- File signing -->
|
||||
<target name="sign-file">
|
||||
<!-- Self-sign -->
|
||||
<antcall target="sign-file-self">
|
||||
<param name="sign.file" value="${sign.file}"/>
|
||||
</antcall>
|
||||
|
||||
<!-- EV-sign using HSM -->
|
||||
<antcall target="sign-file-hsm">
|
||||
<param name="sign.file" value="${sign.file}"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<!-- Jar signing -->
|
||||
<target name="sign-jar">
|
||||
<!-- Self-sign -->
|
||||
<antcall target="sign-jar-self">
|
||||
<param name="sign.file" value="${sign.file}"/>
|
||||
</antcall>
|
||||
|
||||
<!-- EV-sign using HSM -->
|
||||
<antcall target="sign-jar-hsm">
|
||||
<param name="sign.file" value="${sign.file}"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<!-- File signing via hsm with timestamp -->
|
||||
<target name="sign-file-hsm" if="hsm.storetype" depends="find-jsign">
|
||||
<echo level="info">Signing with hsm: ${hsm.keystore}</echo>
|
||||
<java jar="${jsign.path}" fork="true" failonerror="true">
|
||||
<arg value="--name"/>
|
||||
<arg value="${project.name}"/>
|
||||
<arg value="--url"/>
|
||||
<arg value="${vendor.website}"/>
|
||||
<arg value="--replace"/>
|
||||
<arg value="--alg"/>
|
||||
<arg value="${hsm.algorithm}"/>
|
||||
<arg value="--storetype"/>
|
||||
<arg value="${hsm.storetype}"/>
|
||||
<arg value="--keystore"/>
|
||||
<arg value="${hsm.keystore}"/>
|
||||
<arg value="--alias"/>
|
||||
<arg value="${hsm.alias}"/>
|
||||
<arg value="--storepass"/>
|
||||
<arg value="${hsm.storepass}"/>
|
||||
<arg value="--tsaurl"/>
|
||||
<arg value="${hsm.tsaurl}"/>
|
||||
<arg value="--certfile"/>
|
||||
<arg value="${hsm.certfile}"/>
|
||||
<arg line="${sign.file}"/>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Jar signing via hsm with timestamp -->
|
||||
<target name="sign-jar-hsm" if="hsm.storetype" depends="find-jsign,get-jar-alg">
|
||||
<signjar providerclass="net.jsign.jca.JsignJcaProvider"
|
||||
providerarg="${hsm.keystore}"
|
||||
alias="${hsm.alias}"
|
||||
storepass="${hsm.storepass}"
|
||||
storetype="${hsm.storetype}"
|
||||
keystore="NONE"
|
||||
sigalg="${jar.sigalg}"
|
||||
digestalg="${jar.digestalg}"
|
||||
tsaurl="${hsm.tsaurl}"
|
||||
jar="${sign.file}"
|
||||
signedjar="${sign.file}">
|
||||
<!-- special args needed by jsign -->
|
||||
<arg value="-J-cp"/><arg value="-J${jsign.path}"/>
|
||||
<arg value="-J--add-modules"/><arg value="-Jjava.sql"/>
|
||||
<arg value="-certchain"/><arg file="${hsm.certfile}"/>
|
||||
</signjar>
|
||||
</target>
|
||||
|
||||
<!-- File signing via arbitrary key without timestamp -->
|
||||
<target name="sign-file-self" unless="hsm.storetype" depends="find-jsign,find-keystore-self">
|
||||
<echo level="info">Signing without timestamp:</echo>
|
||||
<tsa-warning/>
|
||||
<java jar="${jsign.path}" fork="true" failonerror="true">
|
||||
<arg value="--name"/>
|
||||
<arg value="${project.name}"/>
|
||||
<arg value="--url"/>
|
||||
<arg value="${vendor.website}"/>
|
||||
<arg value="--replace"/>
|
||||
<arg value="--alg"/>
|
||||
<arg value="${signing.algorithm}"/>
|
||||
<arg value="--keystore"/>
|
||||
<arg value="${signing.keystore}"/>
|
||||
<arg value="--alias"/>
|
||||
<arg value="${signing.alias}"/>
|
||||
<arg value="--storepass"/>
|
||||
<arg value="${signing.storepass}"/>
|
||||
<arg value="--keypass"/>
|
||||
<arg value="${signing.keypass}"/>
|
||||
<arg line="${sign.file}"/>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
<!-- Jar signing via arbitrary key without timestamp -->
|
||||
<target name="sign-jar-self" unless="hsm.storetype" depends="find-jsign,find-keystore-self,get-jar-alg">
|
||||
<signjar alias="${signing.alias}"
|
||||
storepass="${signing.storepass}"
|
||||
keystore="${signing.keystore}"
|
||||
keypass="${signing.keypass}"
|
||||
sigalg="${jar.sigalg}"
|
||||
digestalg="${jar.digestalg}"
|
||||
jar="${sign.file}"
|
||||
signedjar="${sign.file}"
|
||||
/>
|
||||
</target>
|
||||
|
||||
<!-- Maps jsign algorithm to jarsigner algorithm -->
|
||||
<target name="get-jar-alg">
|
||||
<!-- Populate from hsm.algorithm or signing.algorithm -->
|
||||
<condition property="jar.algorithm" value="${hsm.algorithm}">
|
||||
<isset property="${hsm.algorithm}"/>
|
||||
</condition>
|
||||
<property name="jar.algorithm" value="${signing.algorithm}" description="fallback value"/>
|
||||
|
||||
<!-- Convert "SHA-256" to "SHA256", etc -->
|
||||
<loadresource property="convert.algorithm">
|
||||
<propertyresource name="jar.algorithm"/>
|
||||
<filterchain>
|
||||
<tokenfilter>
|
||||
<filetokenizer/>
|
||||
<replacestring from="-" to=""/>
|
||||
</tokenfilter>
|
||||
</filterchain>
|
||||
</loadresource>
|
||||
<property name="convert.algorithm" value="something went wrong" description="fallback value"/>
|
||||
|
||||
<!-- e.g. "SHA256withRSA" -->
|
||||
<property description="Signature Algorithm" name="jar.sigalg" value="${convert.algorithm}withRSA"/>
|
||||
|
||||
<!-- e.g. "SHA256" -->
|
||||
<property description="Digest Algorithm" name="jar.digestalg" value="${convert.algorithm}"/>
|
||||
</target>
|
||||
|
||||
<target name="find-keystore-self">
|
||||
<available file="${signing.keystore}" property="keystore.exists"/>
|
||||
<antcall target="generate-keystore-self"/>
|
||||
</target>
|
||||
|
||||
<target name="generate-keystore-self" unless="keystore.exists">
|
||||
<genkey
|
||||
alias="${signing.alias}"
|
||||
keyalg="RSA"
|
||||
keysize="2048"
|
||||
keystore="${signing.keystore}"
|
||||
storepass="${signing.storepass}"
|
||||
validity="3650"
|
||||
verbose="true">
|
||||
<dname>
|
||||
<param name="CN" value="${vendor.company} (self-signed)"/>
|
||||
<param name="OU" value="${project.name}"/>
|
||||
<param name="O" value="${vendor.website}"/>
|
||||
<param name="C" value="US"/>
|
||||
</dname>
|
||||
</genkey>
|
||||
</target>
|
||||
|
||||
<macrodef name="tsa-warning">
|
||||
<sequential>
|
||||
<echo level="warn">
|
||||
No tsaurl was provided so the file was not timestamped. Users will not be able to validate
|
||||
this file after the signer certificate's expiration date or after any future revocation date.
|
||||
</echo>
|
||||
</sequential>
|
||||
</macrodef>
|
||||
</project>
|
||||
138
old code/tray/ant/unix/unix-launcher.sh.in
Executable file
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env bash
|
||||
# Shared launcher for MacOS and Linux
|
||||
# Parameters -- if any -- are passed on to the app
|
||||
|
||||
# Halt on first error
|
||||
set -e
|
||||
|
||||
# Configured by ant at build time
|
||||
JAVA_MIN="${javac.target}"
|
||||
LAUNCH_OPTS="${launch.opts}"
|
||||
ABOUT_TITLE="${project.name}"
|
||||
PROPS_FILE="${project.filename}"
|
||||
|
||||
# Get working directory
|
||||
DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
pushd "$DIR" &> /dev/null
|
||||
|
||||
# Console colors
|
||||
RED="\\x1B[1;31m";GREEN="\\x1B[1;32m";YELLOW="\\x1B[1;33m";PLAIN="\\x1B[0m"
|
||||
|
||||
# Statuses
|
||||
SUCCESS=" [${GREEN}success${PLAIN}]"
|
||||
FAILURE=" [${RED}failure${PLAIN}]"
|
||||
WARNING=" [${YELLOW}warning${PLAIN}]"
|
||||
MESSAGE=" [${YELLOW}message${PLAIN}]"
|
||||
|
||||
echo "Looking for Java..."
|
||||
|
||||
# Honor JAVA_HOME
|
||||
if [ -n "$JAVA_HOME" ]; then
|
||||
echo -e "$WARNING JAVA_HOME was detected, using $JAVA_HOME..."
|
||||
PATH="$JAVA_HOME/bin:$PATH"
|
||||
fi
|
||||
|
||||
# Always prefer relative runtime/jre
|
||||
if [[ "$DIR" == *"/Contents/MacOS"* ]]; then
|
||||
PATH="$DIR/../PlugIns/Java.runtime/Contents/Home/bin:$PATH"
|
||||
else
|
||||
PATH="$DIR/runtime/bin:$DIR/jre/bin:$PATH"
|
||||
fi
|
||||
|
||||
# Check for user overridable launch options
|
||||
if [ -n "${dollar}${launch.overrides}" ]; then
|
||||
echo -e "$MESSAGE Picked up additional launch options: ${dollar}${launch.overrides}"
|
||||
LAUNCH_OPTS="$LAUNCH_OPTS ${dollar}${launch.overrides}"
|
||||
fi
|
||||
|
||||
# Fallback on some known locations
|
||||
if ! command -v java > /dev/null ; then
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# Apple: Fallback on system-wide install
|
||||
DEFAULTS_READ=$(defaults read ${apple.bundleid} ${launch.overrides} 2>/dev/null) || true
|
||||
if [ -n "$DEFAULTS_READ" ]; then
|
||||
echo -e "$MESSAGE Picked up additional launch options: $DEFAULTS_READ"
|
||||
LAUNCH_OPTS="$LAUNCH_OPTS $DEFAULTS_READ"
|
||||
fi
|
||||
MAC_PRIMARY="/usr/libexec/java_home"
|
||||
MAC_FALLBACK="/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin"
|
||||
echo "Trying $MAC_PRIMARY..."
|
||||
if "$MAC_PRIMARY" -v $JAVA_MIN+ &>/dev/null; then
|
||||
echo -e "$SUCCESS Using \"$MAC_PRIMARY -v $JAVA_MIN+ --exec\" to launch $ABOUT_TITLE"
|
||||
java() {
|
||||
"$MAC_PRIMARY" -v $JAVA_MIN+ --exec java "$@"
|
||||
}
|
||||
elif [ -d "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin" ]; then
|
||||
echo -e "$WARNING No luck using $MAC_PRIMARY"
|
||||
echo "Trying $MAC_FALLBACK..."
|
||||
java() {
|
||||
"$MAC_FALLBACK/java" "$@"
|
||||
}
|
||||
fi
|
||||
else
|
||||
# Linux/Unix: Fallback on known install location(s)
|
||||
PATH="$PATH:/usr/java/latest/bin/"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v java > /dev/null ; then
|
||||
echo -e "$SUCCESS Java was found: $(command -v java)"
|
||||
else
|
||||
echo -e "$FAILURE Please install Java $JAVA_MIN or higher to continue"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify the bundled Java version actually works
|
||||
if test -f "$DIR/runtime/bin/java" ; then
|
||||
echo "Verifying the bundled Java version can run on this platform..."
|
||||
if "$DIR/runtime/bin/java" -version &> /dev/null ; then
|
||||
echo -e "$SUCCESS Bundled Java version is OK"
|
||||
else
|
||||
echo -e "$FAILURE Sorry, this version of $ABOUT_TITLE cannot be installed on this system:\n"
|
||||
file "$DIR/runtime/bin/java"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make sure Java version is sufficient
|
||||
echo "Verifying the Java version is $JAVA_MIN+..."
|
||||
curver=$(java -version 2>&1 | grep -i version | awk -F"\"" '{ print $2 }' | awk -F"." '{ print $1 "." $2 }')
|
||||
minver="$JAVA_MIN"
|
||||
if [ -z "$curver" ]; then
|
||||
curver="0.0"
|
||||
fi
|
||||
desired=$(echo -e "$minver\n$curver")
|
||||
actual=$(echo "$desired" |sort -t '.' -k 1,1 -k 2,2 -n)
|
||||
if [ "$desired" != "$actual" ]; then
|
||||
echo -e "$FAILURE Please install Java $JAVA_MIN or higher to continue"
|
||||
exit 1
|
||||
else
|
||||
echo -e "$SUCCESS Java $curver was detected"
|
||||
fi
|
||||
|
||||
jigsaw=$(echo -e "9.0\n$curver")
|
||||
actual=$(echo "$jigsaw" |sort -t '.' -k 1,1 -k 2,2 -n)
|
||||
if [ "$jigsaw" != "$actual" ]; then
|
||||
echo -e "$SUCCESS Java < 9.0, skipping jigsaw options"
|
||||
else
|
||||
echo -e "$SUCCESS Java >= 9.0, adding jigsaw options"
|
||||
LAUNCH_OPTS="$LAUNCH_OPTS ${launch.jigsaw}"
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
LAUNCH_OPTS="$LAUNCH_OPTS ${apple.launch.jigsaw}"
|
||||
else
|
||||
LAUNCH_OPTS="$LAUNCH_OPTS ${linux.launch.jigsaw}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v java &>/dev/null; then
|
||||
echo -e "$ABOUT_TITLE is starting..."
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
java $LAUNCH_OPTS -Xdock:name="$ABOUT_TITLE" -Xdock:icon="$DIR/../Resources/$PROPS_FILE.icns" -jar -Dapple.awt.UIElement="true" -Dapple.awt.enableTemplateImages="${java.mask.tray}" -Dapple.awt.application.appearance="system" "$DIR/../Resources/${prefix}$PROPS_FILE.jar" -NSRequiresAquaSystemAppearance False "$@"
|
||||
else
|
||||
java $LAUNCH_OPTS -jar "$PROPS_FILE.jar" "$@"
|
||||
fi
|
||||
else
|
||||
echo -e "$FAILURE Java $JAVA_MIN+ was not found"
|
||||
fi
|
||||
|
||||
popd &>/dev/null
|
||||
38
old code/tray/ant/unix/unix-uninstall.sh.in
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Halt on first error
|
||||
set -e
|
||||
|
||||
if [ "$(id -u)" != "0" ]; then
|
||||
echo "This script must be run with root (sudo) privileges" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get working directory
|
||||
DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
pushd "$DIR"
|
||||
|
||||
echo "Running uninstall tasks..."
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# Uninstall script is in "QZ Tray.app/Contents/Resources/uninstall"
|
||||
# Calculate the path to "QZ Tray.app"
|
||||
APP_DIR=$(cd "$(dirname "$0")/../.." && pwd)
|
||||
|
||||
if [[ "$APP_DIR" != *".app" ]]; then
|
||||
echo -e "\nMalformed app directory. Uninstallation of ${project.name} failed.\n"
|
||||
exit 1
|
||||
fi
|
||||
# Launcher script is in "QZ Tray.app/Contents/MacOS"
|
||||
"$APP_DIR/Contents/MacOS/${project.name}" uninstall
|
||||
else
|
||||
# Uninstall script is in root of app (e.g. "/opt/qz-tray")
|
||||
APP_DIR="$DIR"
|
||||
# Launcher script is adjacent to uninstall script
|
||||
"$APP_DIR/${project.filename}" uninstall
|
||||
fi
|
||||
|
||||
echo "Deleting files..."
|
||||
rm -rf "$APP_DIR"
|
||||
echo -e "\nUninstall of ${project.name} complete.\n"
|
||||
|
||||
popd &>/dev/null
|
||||
23
old code/tray/ant/version.xml
Executable file
@@ -0,0 +1,23 @@
|
||||
<project name="version" basedir="../">
|
||||
<!-- Get version information from JAR -->
|
||||
<target name="get-version">
|
||||
<!-- build.version -->
|
||||
<property file="${basedir}/ant/project.properties"/>
|
||||
<java jar="${dist.dir}/${project.filename}.jar" fork="true" outputproperty="build.version" errorproperty="build.version.error" timeout="60000" failonerror="true">
|
||||
<arg value="--version"/>
|
||||
</java>
|
||||
|
||||
<!-- apple.bundleid -->
|
||||
<java jar="${dist.dir}/${project.filename}.jar" fork="true" outputproperty="apple.bundleid" errorproperty="apple.bundleid.error" timeout="60000" failonerror="true">
|
||||
<arg value="--bundleid"/>
|
||||
</java>
|
||||
<property description="fallback value" name="build.type" value=""/>
|
||||
<property description="fallback value" name="build.version" value=""/>
|
||||
<property description="fallback value" name="apple.bundleid" value=""/>
|
||||
|
||||
<echo level="info">
|
||||
Version : ${build.version}${build.type}
|
||||
Bundle Id : ${apple.bundleid}
|
||||
</echo>
|
||||
</target>
|
||||
</project>
|
||||
110
old code/tray/ant/windows/installer.xml
Executable file
@@ -0,0 +1,110 @@
|
||||
<project name="windows-installer" basedir="../../">
|
||||
<property file="ant/project.properties"/>
|
||||
<import file="${basedir}/ant/version.xml"/>
|
||||
<import file="${basedir}/ant/platform-detect.xml"/>
|
||||
<import file="${basedir}/ant/signing.xml"/>
|
||||
<property environment="env"/>
|
||||
|
||||
<target name="build-exe" depends="get-version,platform-detect">
|
||||
<!-- Get the os-preferred name for the target architecture -->
|
||||
<condition property="windows.target.arch" value="arm64">
|
||||
<isset property="target.arch.aarch64"/>
|
||||
</condition>
|
||||
<property name="windows.target.arch" value="x86_64" description="fallback value"/>
|
||||
|
||||
<!-- Sign Libs and Runtime -->
|
||||
<fileset dir="${dist.dir}/" id="win.sign.found">
|
||||
<include name="**/*.dll"/>
|
||||
<include name="**/*.exe"/>
|
||||
</fileset>
|
||||
<!-- Pass all files at once, wrapped in quotes -->
|
||||
<pathconvert pathsep="" "" property="win.sign.separated" refid="win.sign.found"/>
|
||||
<antcall target="sign-file">
|
||||
<param name="sign.file" value=""${win.sign.separated}""/>
|
||||
</antcall>
|
||||
|
||||
<!-- Launcher -->
|
||||
<antcall target="config-compile-sign">
|
||||
<param name="nsis.script.in" value="windows-launcher.nsi.in"/>
|
||||
<param name="nsis.outfile" value="${dist.dir}/${project.filename}.exe"/>
|
||||
</antcall>
|
||||
|
||||
<!-- Debug Launcher -->
|
||||
<copy file="ant/windows/windows-launcher.nsi.in" tofile="ant/windows/windows-debug-launcher.nsi.in" overwrite="true"/>
|
||||
<replace file="ant/windows/windows-debug-launcher.nsi.in" token="$javaw" value="$java"/>
|
||||
<replace file="ant/windows/windows-debug-launcher.nsi.in" token="/assets/branding/windows-icon.ico" value="/ant/windows/nsis/console.ico"/>
|
||||
<antcall target="config-compile-sign">
|
||||
<param name="nsis.script.in" value="windows-debug-launcher.nsi.in"/>
|
||||
<param name="nsis.outfile" value="${dist.dir}/${project.filename}-console.exe"/>
|
||||
</antcall>
|
||||
|
||||
<!-- Uninstaller -->
|
||||
<antcall target="config-compile-sign">
|
||||
<param name="nsis.script.in" value="windows-uninstaller.nsi.in"/>
|
||||
<param name="nsis.outfile" value="${dist.dir}/uninstall.exe"/>
|
||||
</antcall>
|
||||
|
||||
<!-- Installer (bundles dist/ payload) -->
|
||||
<antcall target="config-compile-sign">
|
||||
<param name="nsis.script.in" value="windows-installer.nsi.in"/>
|
||||
<param name="nsis.outfile" value="${out.dir}/${project.filename}${build.type}-${build.version}-${windows.target.arch}.exe"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<target name="config-compile-sign" depends="find-nsisbin">
|
||||
<echo level="info">Creating ${nsis.outfile} using ${nsisbin}</echo>
|
||||
|
||||
<!-- Calculate file name without suffix -->
|
||||
<basename property="nsis.script.out" file="${nsis.script.in}" suffix=".in"/>
|
||||
|
||||
<!-- Configure the nsi script with ant parameters -->
|
||||
<copy file="ant/windows/${nsis.script.in}" tofile="${build.dir}/${nsis.script.out}" overwrite="true">
|
||||
<filterchain><expandproperties/></filterchain>
|
||||
</copy>
|
||||
|
||||
<!-- Create the exe -->
|
||||
<exec executable="${nsisbin}" failonerror="true">
|
||||
<arg value="${build.dir}/${nsis.script.out}"/>
|
||||
</exec>
|
||||
|
||||
<!-- Sign the exe -->
|
||||
<antcall target="sign-file">
|
||||
<param name="sign.file" value="${nsis.outfile}"/>
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
<target name="find-nsisbin" depends="nsisbin-from-unix,nsisbin-from-32,nsisbin-from-64"/>
|
||||
|
||||
<!-- Linux makensis -->
|
||||
<target name="nsisbin-from-unix" unless="env.windir">
|
||||
<property name="nsisbin" value="makensis"/>
|
||||
</target>
|
||||
|
||||
<!-- Win32 makensis -->
|
||||
<target name="nsisbin-from-32" unless="env.ProgramFiles(x86)">
|
||||
<property description="suppress property warning" name="env.ProgramFiles" value="C:/Program Files"/>
|
||||
<property name="nsisbin" value="${env.ProgramFiles}/NSIS/makensis.exe"/>
|
||||
</target>
|
||||
|
||||
<!-- Win64 makensis -->
|
||||
<target name="nsisbin-from-64" if="env.ProgramFiles(x86)">
|
||||
<property description="suppress property warning" name="env.ProgramFiles(x86)" value="C:/Program Files (x86)"/>
|
||||
<property name="nsisbin" value="${env.ProgramFiles(x86)}/NSIS/makensis.exe"/>
|
||||
</target>
|
||||
|
||||
<target name="copy-dlls" if="target.os.windows">
|
||||
<echo level="info">Copying native library files to libs</echo>
|
||||
<copy todir="${dist.dir}/libs" flatten="true" verbose="true">
|
||||
<fileset dir="${out.dir}/libs-temp">
|
||||
<!--x86_64-->
|
||||
<include name="**/win32-x86-64/*" if="target.arch.x86_64"/> <!-- jna/hid4java -->
|
||||
<include name="**/windows-x86_64/*" if="target.arch.x86_64"/> <!-- usb4java -->
|
||||
<include name="**/windows_64/*" if="target.arch.x86_64"/> <!-- jssc -->
|
||||
<!--aarch64-->
|
||||
<include name="**/win32-aarch64/*" if="target.arch.aarch64"/> <!-- jna/hid4java -->
|
||||
<include name="**/windows-aarch64/*" if="target.arch.aarch64"/> <!-- usb4java -->
|
||||
<include name="**/windows_arm64/*" if="target.arch.aarch64"/> <!-- jssc -->
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
</project>
|
||||
143
old code/tray/ant/windows/nsis/Include/FindJava.nsh
Executable file
@@ -0,0 +1,143 @@
|
||||
!include FileFunc.nsh
|
||||
!include LogicLib.nsh
|
||||
!include x64.nsh
|
||||
|
||||
!include StrRep.nsh
|
||||
!include IndexOf.nsh
|
||||
!include StrTok.nsh
|
||||
|
||||
; Resulting variable
|
||||
Var /GLOBAL java
|
||||
Var /GLOBAL javaw
|
||||
Var /GLOBAL java_major
|
||||
|
||||
; Constants
|
||||
!define EXE "java.exe"
|
||||
|
||||
!define ADOPT "SOFTWARE\Classes\AdoptOpenJDK.jarfile\shell\open\command"
|
||||
!define ECLIPSE "SOFTWARE\Classes\Eclipse Adoptium.jarfile\shell\open\command"
|
||||
!define ECLIPSE_OLD "SOFTWARE\Classes\Eclipse Foundation.jarfile\shell\open\command"
|
||||
|
||||
!define JRE "Software\JavaSoft\Java Runtime Environment"
|
||||
!define JRE32 "Software\Wow6432Node\JavaSoft\Java Runtime Environment"
|
||||
!define JDK "Software\JavaSoft\JDK"
|
||||
!define JDK32 "Software\Wow6432Node\JavaSoft\JDK"
|
||||
|
||||
; Macros
|
||||
!macro _ReadEclipseKey
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKLM "${ECLIPSE}" ""
|
||||
StrCpy $0 "$0" "" 1 ; Remove first double-quote
|
||||
${IndexOf} $1 $0 "$\"" ; Find the index of second double-quote
|
||||
StrCpy $0 "$0" $1 ; Get the string section up to the index
|
||||
IfFileExists "$0" Found
|
||||
!macroend
|
||||
|
||||
!macro _ReadEclipseOldKey
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKLM "${ECLIPSE_OLD}" ""
|
||||
StrCpy $0 "$0" "" 1 ; Remove first double-quote
|
||||
${IndexOf} $1 $0 "$\"" ; Find the index of second double-quote
|
||||
StrCpy $0 "$0" $1 ; Get the string section up to the index
|
||||
IfFileExists "$0" Found
|
||||
!macroend
|
||||
|
||||
!macro _ReadAdoptKey
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKLM "${ADOPT}" ""
|
||||
StrCpy $0 "$0" "" 1 ; Remove first double-quote
|
||||
${IndexOf} $1 $0 "$\"" ; Find the index of second double-quote
|
||||
StrCpy $0 "$0" $1 ; Get the string section up to the index
|
||||
IfFileExists "$0" Found
|
||||
!macroend
|
||||
|
||||
!macro _ReadReg key
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKLM "${key}" "CurrentVersion"
|
||||
ReadRegStr $0 HKLM "${key}\$0" "JavaHome"
|
||||
IfErrors +2 0
|
||||
StrCpy $0 "$0\bin\${EXE}"
|
||||
IfFileExists "$0" Found
|
||||
!macroend
|
||||
|
||||
!macro _ReadPayload root path
|
||||
ClearErrors
|
||||
StrCpy $0 "${root}\${path}\bin\${EXE}"
|
||||
IfFileExists $0 Found
|
||||
!macroend
|
||||
|
||||
!macro _ReadWorking path
|
||||
ClearErrors
|
||||
StrCpy $0 "$EXEDIR\${path}\bin\${EXE}"
|
||||
IfFileExists $0 Found
|
||||
!macroend
|
||||
|
||||
!macro _ReadEnv var
|
||||
ClearErrors
|
||||
ReadEnvStr $0 "${var}"
|
||||
StrCpy $0 "$0\bin\${EXE}"
|
||||
IfFileExists "$0" Found
|
||||
!macroend
|
||||
|
||||
; Create the shared function.
|
||||
!macro _FindJava un
|
||||
Function ${un}FindJava
|
||||
; Snag payload directory off the stack
|
||||
exch $R0
|
||||
|
||||
${If} ${RunningX64}
|
||||
SetRegView 64
|
||||
${EndIf}
|
||||
|
||||
; Check payload directories
|
||||
!insertmacro _ReadPayload "$R0" "runtime"
|
||||
|
||||
; Check relative directories
|
||||
!insertmacro _ReadWorking "runtime"
|
||||
!insertmacro _ReadWorking "jre"
|
||||
|
||||
; Check common env vars
|
||||
!insertmacro _ReadEnv "JAVA_HOME"
|
||||
|
||||
; Check registry
|
||||
!insertmacro _ReadEclipseKey
|
||||
!insertmacro _ReadEclipseOldKey
|
||||
!insertmacro _ReadAdoptKey
|
||||
!insertmacro _ReadReg "${JRE}"
|
||||
!insertmacro _ReadReg "${JRE32}"
|
||||
!insertmacro _ReadReg "${JDK}"
|
||||
!insertmacro _ReadReg "${JDK32}"
|
||||
|
||||
; Give up. Use java.exe and hope it works
|
||||
StrCpy $0 "${EXE}"
|
||||
|
||||
; Set global var
|
||||
Found:
|
||||
StrCpy $java $0
|
||||
${StrRep} '$java' '$java' 'javaw.exe' '${EXE}' ; AdoptOpenJDK returns "javaw.exe"
|
||||
${StrRep} '$javaw' '$java' '${EXE}' 'javaw.exe'
|
||||
|
||||
; Discard payload directory
|
||||
pop $R0
|
||||
|
||||
; Detect java version
|
||||
nsExec::ExecToStack '"$java" -version'
|
||||
Pop $0
|
||||
Pop $1
|
||||
; Isolate version number, e.g. "1.8.0"
|
||||
${StrTok} $0 "$1" "$\"" "1" "1"
|
||||
; Isolate major version
|
||||
${StrTok} $R0 "$0" "." "0" "1"
|
||||
; Handle old 1.x.x version format
|
||||
${If} "$R0" == "1"
|
||||
${StrTok} $R0 "$0" "." "1" "1"
|
||||
${EndIf}
|
||||
|
||||
; Convert to integer
|
||||
IntOp $java_major $R0 + 0
|
||||
FunctionEnd
|
||||
!macroend
|
||||
|
||||
; Allows registering identical functions for install and uninstall
|
||||
!insertmacro _FindJava ""
|
||||
;!insertmacro _FindJava "un."
|
||||
28
old code/tray/ant/windows/nsis/Include/IndexOf.nsh
Executable file
@@ -0,0 +1,28 @@
|
||||
!define IndexOf "!insertmacro IndexOf"
|
||||
|
||||
!macro IndexOf Var Str Char
|
||||
Push "${Char}"
|
||||
Push "${Str}"
|
||||
|
||||
Exch $R0
|
||||
Exch
|
||||
Exch $R1
|
||||
Push $R2
|
||||
Push $R3
|
||||
|
||||
StrCpy $R3 $R0
|
||||
StrCpy $R0 -1
|
||||
IntOp $R0 $R0 + 1
|
||||
StrCpy $R2 $R3 1 $R0
|
||||
StrCmp $R2 "" +2
|
||||
StrCmp $R2 $R1 +2 -3
|
||||
|
||||
StrCpy $R0 -1
|
||||
|
||||
Pop $R3
|
||||
Pop $R2
|
||||
Pop $R1
|
||||
Exch $R0
|
||||
|
||||
Pop "${Var}"
|
||||
!macroend
|
||||
5
old code/tray/ant/windows/nsis/Include/SetTitleBar.nsh
Executable file
@@ -0,0 +1,5 @@
|
||||
; Allow title masquerading
|
||||
!define SetTitleBar "!insertmacro SetTitleBar"
|
||||
!macro SetTitlebar title
|
||||
SendMessage $HWNDPARENT ${WM_SETTEXT} 0 "STR:${title}"
|
||||
!macroend
|
||||
501
old code/tray/ant/windows/nsis/Include/StdUtils.nsh
Executable file
@@ -0,0 +1,501 @@
|
||||
#################################################################################
|
||||
# StdUtils plug-in for NSIS
|
||||
# Copyright (C) 2004-2018 LoRd_MuldeR <MuldeR2@GMX.de>
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# http://www.gnu.org/licenses/lgpl-2.1.txt
|
||||
#################################################################################
|
||||
|
||||
# DEVELOPER NOTES:
|
||||
# - Please see "https://github.com/lordmulder/stdutils/" for news and updates!
|
||||
# - Please see "Docs\StdUtils\StdUtils.html" for detailed function descriptions!
|
||||
# - Please see "Examples\StdUtils\StdUtilsTest.nsi" for usage examples!
|
||||
|
||||
#################################################################################
|
||||
# FUNCTION DECLARTIONS
|
||||
#################################################################################
|
||||
|
||||
!ifndef ___STDUTILS__NSH___
|
||||
!define ___STDUTILS__NSH___
|
||||
|
||||
!define StdUtils.Time '!insertmacro _StdU_Time' #time(), as in C standard library
|
||||
!define StdUtils.GetMinutes '!insertmacro _StdU_GetMinutes' #GetSystemTimeAsFileTime(), returns the number of minutes
|
||||
!define StdUtils.GetHours '!insertmacro _StdU_GetHours' #GetSystemTimeAsFileTime(), returns the number of hours
|
||||
!define StdUtils.GetDays '!insertmacro _StdU_GetDays' #GetSystemTimeAsFileTime(), returns the number of days
|
||||
!define StdUtils.Rand '!insertmacro _StdU_Rand' #rand(), as in C standard library
|
||||
!define StdUtils.RandMax '!insertmacro _StdU_RandMax' #rand(), as in C standard library, with maximum value
|
||||
!define StdUtils.RandMinMax '!insertmacro _StdU_RandMinMax' #rand(), as in C standard library, with minimum/maximum value
|
||||
!define StdUtils.RandList '!insertmacro _StdU_RandList' #rand(), as in C standard library, with list support
|
||||
!define StdUtils.RandBytes '!insertmacro _StdU_RandBytes' #Generates random bytes, returned as Base64-encoded string
|
||||
!define StdUtils.FormatStr '!insertmacro _StdU_FormatStr' #sprintf(), as in C standard library, one '%d' placeholder
|
||||
!define StdUtils.FormatStr2 '!insertmacro _StdU_FormatStr2' #sprintf(), as in C standard library, two '%d' placeholders
|
||||
!define StdUtils.FormatStr3 '!insertmacro _StdU_FormatStr3' #sprintf(), as in C standard library, three '%d' placeholders
|
||||
!define StdUtils.ScanStr '!insertmacro _StdU_ScanStr' #sscanf(), as in C standard library, one '%d' placeholder
|
||||
!define StdUtils.ScanStr2 '!insertmacro _StdU_ScanStr2' #sscanf(), as in C standard library, two '%d' placeholders
|
||||
!define StdUtils.ScanStr3 '!insertmacro _StdU_ScanStr3' #sscanf(), as in C standard library, three '%d' placeholders
|
||||
!define StdUtils.TrimStr '!insertmacro _StdU_TrimStr' #Remove whitspaces from string, left and right
|
||||
!define StdUtils.TrimStrLeft '!insertmacro _StdU_TrimStrLeft' #Remove whitspaces from string, left side only
|
||||
!define StdUtils.TrimStrRight '!insertmacro _StdU_TrimStrRight' #Remove whitspaces from string, right side only
|
||||
!define StdUtils.RevStr '!insertmacro _StdU_RevStr' #Reverse a string, e.g. "reverse me" <-> "em esrever"
|
||||
!define StdUtils.ValidFileName '!insertmacro _StdU_ValidFileName' #Test whether string is a valid file name - no paths allowed
|
||||
!define StdUtils.ValidPathSpec '!insertmacro _StdU_ValidPathSpec' #Test whether string is a valid full(!) path specification
|
||||
!define StdUtils.ValidDomainName '!insertmacro _StdU_ValidDomain' #Test whether string is a valid host name or domain name
|
||||
!define StdUtils.StrToUtf8 '!insertmacro _StdU_StrToUtf8' #Convert string from Unicode (UTF-16) or ANSI to UTF-8 bytes
|
||||
!define StdUtils.StrFromUtf8 '!insertmacro _StdU_StrFromUtf8' #Convert string from UTF-8 bytes to Unicode (UTF-16) or ANSI
|
||||
!define StdUtils.SHFileMove '!insertmacro _StdU_SHFileMove' #SHFileOperation(), using the FO_MOVE operation
|
||||
!define StdUtils.SHFileCopy '!insertmacro _StdU_SHFileCopy' #SHFileOperation(), using the FO_COPY operation
|
||||
!define StdUtils.AppendToFile '!insertmacro _StdU_AppendToFile' #Append contents of an existing file to another file
|
||||
!define StdUtils.ExecShellAsUser '!insertmacro _StdU_ExecShlUser' #ShellExecute() as NON-elevated user from elevated installer
|
||||
!define StdUtils.InvokeShellVerb '!insertmacro _StdU_InvkeShlVrb' #Invokes a "shell verb", e.g. for pinning items to the taskbar
|
||||
!define StdUtils.ExecShellWaitEx '!insertmacro _StdU_ExecShlWaitEx' #ShellExecuteEx(), returns the handle of the new process
|
||||
!define StdUtils.WaitForProcEx '!insertmacro _StdU_WaitForProcEx' #WaitForSingleObject(), e.g. to wait for a running process
|
||||
!define StdUtils.GetParameter '!insertmacro _StdU_GetParameter' #Get the value of a specific command-line option
|
||||
!define StdUtils.TestParameter '!insertmacro _StdU_TestParameter' #Test whether a specific command-line option has been set
|
||||
!define StdUtils.ParameterCnt '!insertmacro _StdU_ParameterCnt' #Get number of command-line tokens, similar to argc in main()
|
||||
!define StdUtils.ParameterStr '!insertmacro _StdU_ParameterStr' #Get the n-th command-line token, similar to argv[i] in main()
|
||||
!define StdUtils.GetAllParameters '!insertmacro _StdU_GetAllParams' #Get complete command-line, but without executable name
|
||||
!define StdUtils.GetRealOSVersion '!insertmacro _StdU_GetRealOSVer' #Get the *real* Windows version number, even on Windows 8.1+
|
||||
!define StdUtils.GetRealOSBuildNo '!insertmacro _StdU_GetRealOSBld' #Get the *real* Windows build number, even on Windows 8.1+
|
||||
!define StdUtils.GetRealOSName '!insertmacro _StdU_GetRealOSStr' #Get the *real* Windows version, as a "friendly" name
|
||||
!define StdUtils.GetOSEdition '!insertmacro _StdU_GetOSEdition' #Get the Windows edition, i.e. "workstation" or "server"
|
||||
!define StdUtils.GetOSReleaseId '!insertmacro _StdU_GetOSRelIdNo' #Get the Windows release identifier (on Windows 10)
|
||||
!define StdUtils.GetOSReleaseName '!insertmacro _StdU_GetOSRelIdStr' #Get the Windows release (on Windows 10), as a "friendly" name
|
||||
!define StdUtils.VerifyOSVersion '!insertmacro _StdU_VrfyRealOSVer' #Compare *real* operating system to an expected version number
|
||||
!define StdUtils.VerifyOSBuildNo '!insertmacro _StdU_VrfyRealOSBld' #Compare *real* operating system to an expected build number
|
||||
!define StdUtils.HashText '!insertmacro _StdU_HashText' #Compute hash from text string (CRC32, MD5, SHA1/2/3, BLAKE2)
|
||||
!define StdUtils.HashFile '!insertmacro _StdU_HashFile' #Compute hash from file (CRC32, MD5, SHA1/2/3, BLAKE2)
|
||||
!define StdUtils.NormalizePath '!insertmacro _StdU_NormalizePath' #Simplifies the path to produce a direct, well-formed path
|
||||
!define StdUtils.GetParentPath '!insertmacro _StdU_GetParentPath' #Get parent path by removing the last component from the path
|
||||
!define StdUtils.SplitPath '!insertmacro _StdU_SplitPath' #Split the components of the given path
|
||||
!define StdUtils.GetDrivePart '!insertmacro _StdU_GetDrivePart' #Get drive component of path
|
||||
!define StdUtils.GetDirectoryPart '!insertmacro _StdU_GetDirPart' #Get directory component of path
|
||||
!define StdUtils.GetFileNamePart '!insertmacro _StdU_GetFNamePart' #Get file name component of path
|
||||
!define StdUtils.GetExtensionPart '!insertmacro _StdU_GetExtnPart' #Get file extension component of path
|
||||
!define StdUtils.TimerCreate '!insertmacro _StdU_TimerCreate' #Create a new event-timer that will be triggered periodically
|
||||
!define StdUtils.TimerDestroy '!insertmacro _StdU_TimerDestroy' #Destroy a running timer created with TimerCreate()
|
||||
!define StdUtils.ProtectStr '!insertmacro _StdU_PrtctStr' #Protect a given String using Windows' DPAPI
|
||||
!define StdUtils.UnprotectStr '!insertmacro _StdU_UnprtctStr' #Unprotect a string that was protected via ProtectStr()
|
||||
!define StdUtils.GetLibVersion '!insertmacro _StdU_GetLibVersion' #Get the current StdUtils library version (for debugging)
|
||||
!define StdUtils.SetVerbose '!insertmacro _StdU_SetVerbose' #Enable or disable "verbose" mode (for debugging)
|
||||
|
||||
|
||||
#################################################################################
|
||||
# MACRO DEFINITIONS
|
||||
#################################################################################
|
||||
|
||||
!macro _StdU_Time out
|
||||
StdUtils::Time /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetMinutes out
|
||||
StdUtils::GetMinutes /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetHours out
|
||||
StdUtils::GetHours /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetDays out
|
||||
StdUtils::GetDays /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_Rand out
|
||||
StdUtils::Rand /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_RandMax out max
|
||||
push ${max}
|
||||
StdUtils::RandMax /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_RandMinMax out min max
|
||||
push ${min}
|
||||
push ${max}
|
||||
StdUtils::RandMinMax /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_RandList count max
|
||||
push ${max}
|
||||
push ${count}
|
||||
StdUtils::RandList /NOUNLOAD
|
||||
!macroend
|
||||
|
||||
!macro _StdU_RandBytes out count
|
||||
push ${count}
|
||||
StdUtils::RandBytes /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_FormatStr out format val
|
||||
push `${format}`
|
||||
push ${val}
|
||||
StdUtils::FormatStr /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_FormatStr2 out format val1 val2
|
||||
push `${format}`
|
||||
push ${val1}
|
||||
push ${val2}
|
||||
StdUtils::FormatStr2 /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_FormatStr3 out format val1 val2 val3
|
||||
push `${format}`
|
||||
push ${val1}
|
||||
push ${val2}
|
||||
push ${val3}
|
||||
StdUtils::FormatStr3 /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ScanStr out format input default
|
||||
push `${format}`
|
||||
push `${input}`
|
||||
push ${default}
|
||||
StdUtils::ScanStr /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ScanStr2 out1 out2 format input default1 default2
|
||||
push `${format}`
|
||||
push `${input}`
|
||||
push ${default1}
|
||||
push ${default2}
|
||||
StdUtils::ScanStr2 /NOUNLOAD
|
||||
pop ${out1}
|
||||
pop ${out2}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ScanStr3 out1 out2 out3 format input default1 default2 default3
|
||||
push `${format}`
|
||||
push `${input}`
|
||||
push ${default1}
|
||||
push ${default2}
|
||||
push ${default3}
|
||||
StdUtils::ScanStr3 /NOUNLOAD
|
||||
pop ${out1}
|
||||
pop ${out2}
|
||||
pop ${out3}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_TrimStr var
|
||||
push ${var}
|
||||
StdUtils::TrimStr /NOUNLOAD
|
||||
pop ${var}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_TrimStrLeft var
|
||||
push ${var}
|
||||
StdUtils::TrimStrLeft /NOUNLOAD
|
||||
pop ${var}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_TrimStrRight var
|
||||
push ${var}
|
||||
StdUtils::TrimStrRight /NOUNLOAD
|
||||
pop ${var}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_RevStr var
|
||||
push ${var}
|
||||
StdUtils::RevStr /NOUNLOAD
|
||||
pop ${var}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ValidFileName out test
|
||||
push `${test}`
|
||||
StdUtils::ValidFileName /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ValidPathSpec out test
|
||||
push `${test}`
|
||||
StdUtils::ValidPathSpec /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ValidDomain out test
|
||||
push `${test}`
|
||||
StdUtils::ValidDomainName /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
|
||||
!macro _StdU_StrToUtf8 out str
|
||||
push `${str}`
|
||||
StdUtils::StrToUtf8 /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_StrFromUtf8 out trnc str
|
||||
push ${trnc}
|
||||
push `${str}`
|
||||
StdUtils::StrFromUtf8 /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_SHFileMove out from to hwnd
|
||||
push `${from}`
|
||||
push `${to}`
|
||||
push ${hwnd}
|
||||
StdUtils::SHFileMove /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_SHFileCopy out from to hwnd
|
||||
push `${from}`
|
||||
push `${to}`
|
||||
push ${hwnd}
|
||||
StdUtils::SHFileCopy /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_AppendToFile out from dest offset maxlen
|
||||
push `${from}`
|
||||
push `${dest}`
|
||||
push ${offset}
|
||||
push ${maxlen}
|
||||
StdUtils::AppendToFile /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ExecShlUser out file verb args
|
||||
push `${file}`
|
||||
push `${verb}`
|
||||
push `${args}`
|
||||
StdUtils::ExecShellAsUser /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_InvkeShlVrb out path file verb_id
|
||||
push "${path}"
|
||||
push "${file}"
|
||||
push ${verb_id}
|
||||
StdUtils::InvokeShellVerb /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ExecShlWaitEx out_res out_val file verb args
|
||||
push `${file}`
|
||||
push `${verb}`
|
||||
push `${args}`
|
||||
StdUtils::ExecShellWaitEx /NOUNLOAD
|
||||
pop ${out_res}
|
||||
pop ${out_val}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_WaitForProcEx out handle
|
||||
push `${handle}`
|
||||
StdUtils::WaitForProcEx /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetParameter out name default
|
||||
push `${name}`
|
||||
push `${default}`
|
||||
StdUtils::GetParameter /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_TestParameter out name
|
||||
push `${name}`
|
||||
StdUtils::TestParameter /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ParameterCnt out
|
||||
StdUtils::ParameterCnt /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_ParameterStr out index
|
||||
push ${index}
|
||||
StdUtils::ParameterStr /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetAllParams out truncate
|
||||
push `${truncate}`
|
||||
StdUtils::GetAllParameters /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetRealOSVer out_major out_minor out_spack
|
||||
StdUtils::GetRealOsVersion /NOUNLOAD
|
||||
pop ${out_major}
|
||||
pop ${out_minor}
|
||||
pop ${out_spack}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetRealOSBld out
|
||||
StdUtils::GetRealOsBuildNo /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetRealOSStr out
|
||||
StdUtils::GetRealOsName /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_VrfyRealOSVer out major minor spack
|
||||
push `${major}`
|
||||
push `${minor}`
|
||||
push `${spack}`
|
||||
StdUtils::VerifyRealOsVersion /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_VrfyRealOSBld out build
|
||||
push `${build}`
|
||||
StdUtils::VerifyRealOsBuildNo /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetOSEdition out
|
||||
StdUtils::GetOsEdition /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetOSRelIdNo out
|
||||
StdUtils::GetOsReleaseId /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetOSRelIdStr out
|
||||
StdUtils::GetOsReleaseName /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_HashText out type text
|
||||
push `${type}`
|
||||
push `${text}`
|
||||
StdUtils::HashText /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_HashFile out type file
|
||||
push `${type}`
|
||||
push `${file}`
|
||||
StdUtils::HashFile /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_NormalizePath out path
|
||||
push `${path}`
|
||||
StdUtils::NormalizePath /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetParentPath out path
|
||||
push `${path}`
|
||||
StdUtils::GetParentPath /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_SplitPath out_drive out_dir out_fname out_ext path
|
||||
push `${path}`
|
||||
StdUtils::SplitPath /NOUNLOAD
|
||||
pop ${out_drive}
|
||||
pop ${out_dir}
|
||||
pop ${out_fname}
|
||||
pop ${out_ext}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetDrivePart out path
|
||||
push `${path}`
|
||||
StdUtils::GetDrivePart /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetDirPart out path
|
||||
push `${path}`
|
||||
StdUtils::GetDirectoryPart /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetFNamePart out path
|
||||
push `${path}`
|
||||
StdUtils::GetFileNamePart /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetExtnPart out path
|
||||
push `${path}`
|
||||
StdUtils::GetExtensionPart /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_TimerCreate out callback interval
|
||||
GetFunctionAddress ${out} ${callback}
|
||||
push ${out}
|
||||
push ${interval}
|
||||
StdUtils::TimerCreate /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_TimerDestroy out timer_id
|
||||
push ${timer_id}
|
||||
StdUtils::TimerDestroy /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_PrtctStr out dpsc salt text
|
||||
push `${dpsc}`
|
||||
push `${salt}`
|
||||
push `${text}`
|
||||
StdUtils::ProtectStr /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_UnprtctStr out trnc salt data
|
||||
push `${trnc}`
|
||||
push `${salt}`
|
||||
push `${data}`
|
||||
StdUtils::UnprotectStr /NOUNLOAD
|
||||
pop ${out}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_GetLibVersion out_ver out_tst
|
||||
StdUtils::GetLibVersion /NOUNLOAD
|
||||
pop ${out_ver}
|
||||
pop ${out_tst}
|
||||
!macroend
|
||||
|
||||
!macro _StdU_SetVerbose enable
|
||||
Push ${enable}
|
||||
StdUtils::SetVerboseMode /NOUNLOAD
|
||||
!macroend
|
||||
|
||||
|
||||
#################################################################################
|
||||
# MAGIC NUMBERS
|
||||
#################################################################################
|
||||
|
||||
!define StdUtils.Const.ShellVerb.PinToTaskbar 0
|
||||
!define StdUtils.Const.ShellVerb.UnpinFromTaskbar 1
|
||||
!define StdUtils.Const.ShellVerb.PinToStart 2
|
||||
!define StdUtils.Const.ShellVerb.UnpinFromStart 3
|
||||
|
||||
!endif # !___STDUTILS__NSH___
|
||||
72
old code/tray/ant/windows/nsis/Include/StrLoc.nsh
Executable file
@@ -0,0 +1,72 @@
|
||||
!define StrLoc "!insertmacro StrLoc"
|
||||
|
||||
!macro StrLoc ResultVar String SubString StartPoint
|
||||
Push "${String}"
|
||||
Push "${SubString}"
|
||||
Push "${StartPoint}"
|
||||
Call StrLoc
|
||||
Pop "${ResultVar}"
|
||||
!macroend
|
||||
|
||||
Function StrLoc
|
||||
/*After this point:
|
||||
------------------------------------------
|
||||
$R0 = StartPoint (input)
|
||||
$R1 = SubString (input)
|
||||
$R2 = String (input)
|
||||
$R3 = SubStringLen (temp)
|
||||
$R4 = StrLen (temp)
|
||||
$R5 = StartCharPos (temp)
|
||||
$R6 = TempStr (temp)*/
|
||||
|
||||
;Get input from user
|
||||
Exch $R0
|
||||
Exch
|
||||
Exch $R1
|
||||
Exch 2
|
||||
Exch $R2
|
||||
Push $R3
|
||||
Push $R4
|
||||
Push $R5
|
||||
Push $R6
|
||||
|
||||
;Get "String" and "SubString" length
|
||||
StrLen $R3 $R1
|
||||
StrLen $R4 $R2
|
||||
;Start "StartCharPos" counter
|
||||
StrCpy $R5 0
|
||||
|
||||
;Loop until "SubString" is found or "String" reaches its end
|
||||
${Do}
|
||||
;Remove everything before and after the searched part ("TempStr")
|
||||
StrCpy $R6 $R2 $R3 $R5
|
||||
|
||||
;Compare "TempStr" with "SubString"
|
||||
${If} $R6 == $R1
|
||||
${If} $R0 == `<`
|
||||
IntOp $R6 $R3 + $R5
|
||||
IntOp $R0 $R4 - $R6
|
||||
${Else}
|
||||
StrCpy $R0 $R5
|
||||
${EndIf}
|
||||
${ExitDo}
|
||||
${EndIf}
|
||||
;If not "SubString", this could be "String"'s end
|
||||
${If} $R5 >= $R4
|
||||
StrCpy $R0 ``
|
||||
${ExitDo}
|
||||
${EndIf}
|
||||
;If not, continue the loop
|
||||
IntOp $R5 $R5 + 1
|
||||
${Loop}
|
||||
|
||||
;Return output to user
|
||||
Pop $R6
|
||||
Pop $R5
|
||||
Pop $R4
|
||||
Pop $R3
|
||||
Pop $R2
|
||||
Exch
|
||||
Pop $R1
|
||||
Exch $R0
|
||||
FunctionEnd
|
||||
66
old code/tray/ant/windows/nsis/Include/StrRep.nsh
Executable file
@@ -0,0 +1,66 @@
|
||||
!define StrRep "!insertmacro StrRep"
|
||||
!macro StrRep output string old new
|
||||
Push `${string}`
|
||||
Push `${old}`
|
||||
Push `${new}`
|
||||
;!ifdef __UNINSTALL__
|
||||
; Call un.StrRep
|
||||
;!else
|
||||
Call StrRep
|
||||
;!endif
|
||||
Pop ${output}
|
||||
!macroend
|
||||
|
||||
!macro Func_StrRep un
|
||||
Function ${un}StrRep
|
||||
Exch $R2 ;new
|
||||
Exch 1
|
||||
Exch $R1 ;old
|
||||
Exch 2
|
||||
Exch $R0 ;string
|
||||
Push $R3
|
||||
Push $R4
|
||||
Push $R5
|
||||
Push $R6
|
||||
Push $R7
|
||||
Push $R8
|
||||
Push $R9
|
||||
|
||||
StrCpy $R3 0
|
||||
StrLen $R4 $R1
|
||||
StrLen $R6 $R0
|
||||
StrLen $R9 $R2
|
||||
loop:
|
||||
StrCpy $R5 $R0 $R4 $R3
|
||||
StrCmp $R5 $R1 found
|
||||
StrCmp $R3 $R6 done
|
||||
IntOp $R3 $R3 + 1 ;move offset by 1 to check the next character
|
||||
Goto loop
|
||||
found:
|
||||
StrCpy $R5 $R0 $R3
|
||||
IntOp $R8 $R3 + $R4
|
||||
StrCpy $R7 $R0 "" $R8
|
||||
StrCpy $R0 $R5$R2$R7
|
||||
StrLen $R6 $R0
|
||||
IntOp $R3 $R3 + $R9 ;move offset by length of the replacement string
|
||||
Goto loop
|
||||
done:
|
||||
|
||||
Pop $R9
|
||||
Pop $R8
|
||||
Pop $R7
|
||||
Pop $R6
|
||||
Pop $R5
|
||||
Pop $R4
|
||||
Pop $R3
|
||||
Push $R0
|
||||
Push $R1
|
||||
Pop $R0
|
||||
Pop $R1
|
||||
Pop $R0
|
||||
Pop $R2
|
||||
Exch $R1
|
||||
FunctionEnd
|
||||
!macroend
|
||||
!insertmacro Func_StrRep ""
|
||||
;!insertmacro Func_StrRep "un."
|
||||
150
old code/tray/ant/windows/nsis/Include/StrTok.nsh
Executable file
@@ -0,0 +1,150 @@
|
||||
!define StrTok "!insertmacro StrTok"
|
||||
|
||||
!macro StrTok ResultVar String Separators ResultPart SkipEmptyParts
|
||||
Push "${String}"
|
||||
Push "${Separators}"
|
||||
Push "${ResultPart}"
|
||||
Push "${SkipEmptyParts}"
|
||||
Call StrTok
|
||||
Pop "${ResultVar}"
|
||||
!macroend
|
||||
|
||||
Function StrTok
|
||||
/*After this point:
|
||||
------------------------------------------
|
||||
$0 = SkipEmptyParts (input)
|
||||
$1 = ResultPart (input)
|
||||
$2 = Separators (input)
|
||||
$3 = String (input)
|
||||
$4 = SeparatorsLen (temp)
|
||||
$5 = StrLen (temp)
|
||||
$6 = StartCharPos (temp)
|
||||
$7 = TempStr (temp)
|
||||
$8 = CurrentLoop
|
||||
$9 = CurrentSepChar
|
||||
$R0 = CurrentSepCharNum
|
||||
*/
|
||||
|
||||
;Get input from user
|
||||
Exch $0
|
||||
Exch
|
||||
Exch $1
|
||||
Exch
|
||||
Exch 2
|
||||
Exch $2
|
||||
Exch 2
|
||||
Exch 3
|
||||
Exch $3
|
||||
Exch 3
|
||||
Push $4
|
||||
Push $5
|
||||
Push $6
|
||||
Push $7
|
||||
Push $8
|
||||
Push $9
|
||||
Push $R0
|
||||
|
||||
;Parameter defaults
|
||||
${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}
|
||||
${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}
|
||||
${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}
|
||||
|
||||
;Get "String" and "Separators" length
|
||||
StrLen $4 $2
|
||||
StrLen $5 $3
|
||||
;Start "StartCharPos" and "ResultPart" counters
|
||||
StrCpy $6 0
|
||||
StrCpy $8 -1
|
||||
|
||||
;Loop until "ResultPart" is met, "Separators" is found or
|
||||
;"String" reaches its end
|
||||
ResultPartLoop: ;"CurrentLoop" Loop
|
||||
|
||||
;Increase "CurrentLoop" counter
|
||||
IntOp $8 $8 + 1
|
||||
|
||||
StrSearchLoop:
|
||||
${Do} ;"String" Loop
|
||||
;Remove everything before and after the searched part ("TempStr")
|
||||
StrCpy $7 $3 1 $6
|
||||
|
||||
;Verify if it's the "String" end
|
||||
${If} $6 >= $5
|
||||
;If "CurrentLoop" is what the user wants, remove the part
|
||||
;after "TempStr" and itself and get out of here
|
||||
${If} $8 == $1
|
||||
${OrIf} $1 == `L`
|
||||
StrCpy $3 $3 $6
|
||||
${Else} ;If not, empty "String" and get out of here
|
||||
StrCpy $3 ``
|
||||
${EndIf}
|
||||
StrCpy $R0 `End`
|
||||
${ExitDo}
|
||||
${EndIf}
|
||||
|
||||
;Start "CurrentSepCharNum" counter (for "Separators" Loop)
|
||||
StrCpy $R0 0
|
||||
|
||||
${Do} ;"Separators" Loop
|
||||
;Use one "Separators" character at a time
|
||||
${If} $R0 <> 0
|
||||
StrCpy $9 $2 1 $R0
|
||||
${Else}
|
||||
StrCpy $9 $2 1
|
||||
${EndIf}
|
||||
|
||||
;Go to the next "String" char if it's "Separators" end
|
||||
${IfThen} $R0 >= $4 ${|} ${ExitDo} ${|}
|
||||
|
||||
;Or, if "TempStr" equals "CurrentSepChar", then...
|
||||
${If} $7 == $9
|
||||
StrCpy $7 $3 $6
|
||||
|
||||
;If "String" is empty because this result part doesn't
|
||||
;contain data, verify if "SkipEmptyParts" is activated,
|
||||
;so we don't return the output to user yet
|
||||
|
||||
${If} $7 == ``
|
||||
${AndIf} $0 = 1 ;${TRUE}
|
||||
IntOp $6 $6 + 1
|
||||
StrCpy $3 $3 `` $6
|
||||
StrCpy $6 0
|
||||
Goto StrSearchLoop
|
||||
${ElseIf} $8 == $1
|
||||
StrCpy $3 $3 $6
|
||||
StrCpy $R0 "End"
|
||||
${ExitDo}
|
||||
${EndIf} ;If not, go to the next result part
|
||||
IntOp $6 $6 + 1
|
||||
StrCpy $3 $3 `` $6
|
||||
StrCpy $6 0
|
||||
Goto ResultPartLoop
|
||||
${EndIf}
|
||||
|
||||
;Increase "CurrentSepCharNum" counter
|
||||
IntOp $R0 $R0 + 1
|
||||
${Loop}
|
||||
${IfThen} $R0 == "End" ${|} ${ExitDo} ${|}
|
||||
|
||||
;Increase "StartCharPos" counter
|
||||
IntOp $6 $6 + 1
|
||||
${Loop}
|
||||
|
||||
/*After this point:
|
||||
------------------------------------------
|
||||
$3 = ResultVar (output)*/
|
||||
|
||||
;Return output to user
|
||||
|
||||
Pop $R0
|
||||
Pop $9
|
||||
Pop $8
|
||||
Pop $7
|
||||
Pop $6
|
||||
Pop $5
|
||||
Pop $4
|
||||
Pop $0
|
||||
Pop $1
|
||||
Pop $2
|
||||
Exch $3
|
||||
FunctionEnd
|
||||
BIN
old code/tray/ant/windows/nsis/Plugins/Release_ANSI/AccessControl.dll
Executable file
BIN
old code/tray/ant/windows/nsis/Plugins/Release_ANSI/StdUtils.dll
Executable file
BIN
old code/tray/ant/windows/nsis/Plugins/Release_Unicode/AccessControl.dll
Executable file
BIN
old code/tray/ant/windows/nsis/Plugins/Release_Unicode/StdUtils.dll
Executable file
BIN
old code/tray/ant/windows/nsis/console.ico
Executable file
|
After Width: | Height: | Size: 420 KiB |
BIN
old code/tray/ant/windows/nsis/uninstall.ico
Executable file
|
After Width: | Height: | Size: 144 KiB |
BIN
old code/tray/ant/windows/nsis/welcome.bmp
Executable file
|
After Width: | Height: | Size: 201 KiB |
132
old code/tray/ant/windows/windows-installer.nsi.in
Executable file
@@ -0,0 +1,132 @@
|
||||
!define MUI_BGCOLOR "SYSCLR:Window"
|
||||
!define MUI_TEXTCOLOR "SYSCLR:WindowText"
|
||||
!include MUI2.nsh
|
||||
!include x64.nsh
|
||||
!include LogicLib.nsh
|
||||
|
||||
!ifdef NSIS_UNICODE
|
||||
!addplugindir "${basedir}/ant/windows/nsis/Plugins/Release_Unicode"
|
||||
!else
|
||||
!addplugindir "${basedir}/ant/windows/nsis/Plugins/Release_ANSI"
|
||||
!endif
|
||||
!addincludedir "${basedir}/ant/windows/nsis/Include"
|
||||
!include FindJava.nsh
|
||||
!include StdUtils.nsh
|
||||
!include StrLoc.nsh
|
||||
|
||||
Name "${project.name}"
|
||||
OutFile "${nsis.outfile}"
|
||||
RequestExecutionLevel admin
|
||||
|
||||
!define MUI_ICON "${basedir}/assets/branding/windows-icon.ico"
|
||||
|
||||
; Branding for qz only
|
||||
!if "${project.filename}" == "qz-tray"
|
||||
!define MUI_WELCOMEFINISHPAGE_BITMAP "${basedir}\ant\windows\nsis\welcome.bmp"
|
||||
!endif
|
||||
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
|
||||
!macro QzInstaller step option value
|
||||
SetDetailsPrint textonly
|
||||
DetailPrint "Running ${step}..."
|
||||
SetDetailsPrint listonly
|
||||
DetailPrint 'Running ${step}: "$java" ${install.opts} -jar "$OUTDIR\${project.filename}.jar" "${step}" "${option}" "${value}"'
|
||||
SetDetailsPrint both
|
||||
ClearErrors
|
||||
nsExec::ExecToLog '"$java" ${install.opts} -jar "$OUTDIR\${project.filename}.jar" "${step}" "${option}" "${value}"'
|
||||
Pop $0
|
||||
${If} "$0" != "0"
|
||||
Abort "Installation failed during ${step} step. Please check log for details."
|
||||
${EndIf}
|
||||
!macroend
|
||||
|
||||
!macro VerifyJava jumpto
|
||||
; Test java executable
|
||||
nsExec::ExecToLog '"$java" -version"'
|
||||
Pop $0
|
||||
${If} "$0" == "0"
|
||||
Goto Resume
|
||||
${EndIf}
|
||||
|
||||
; Handle scenario where Java is bundled but broken
|
||||
${StrLoc} $R1 "$java" "runtime\bin" ">" ; e.g. "nss1234.tmp\payload\runtime\bin\java.exe"
|
||||
${If} $R1 != ""
|
||||
SetDetailsPrint both
|
||||
Abort "Sorry, this version of ${project.name} cannot be installed on this system."
|
||||
${EndIf}
|
||||
|
||||
; Offer to download Java if missing and non-silent install
|
||||
${IfNot} ${Silent}
|
||||
MessageBox MB_YESNO "Java is required. Download now?" IDYES Website IDNO Resume
|
||||
|
||||
; Visit Java website
|
||||
Website:
|
||||
ExecShell "open" "${java.download}"
|
||||
MessageBox MB_OK "Click OK after Java is installed"
|
||||
|
||||
; Check again for Java
|
||||
Goto ${jumpto}
|
||||
${EndIf}
|
||||
Resume:
|
||||
!macroend
|
||||
|
||||
Section
|
||||
; Set environmental variable for silent install to be picked up by Java
|
||||
${If} ${Silent}
|
||||
System::Call 'Kernel32::SetEnvironmentVariable(t, t)i ("${vendor.name}_silent", "1").r0'
|
||||
${EndIf}
|
||||
|
||||
; Echo final destination to logs
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
; Copy files to a temporary location
|
||||
SetOutPath "$PLUGINSDIR\payload"
|
||||
DetailPrint "Extracting..."
|
||||
SetDetailsPrint none ; Temporarily suppress details
|
||||
File /r "${dist.dir}\*"
|
||||
|
||||
; Set the $java variable
|
||||
TryAgain:
|
||||
Push "$OUTDIR"
|
||||
Call FindJava
|
||||
!insertmacro VerifyJava "TryAgain"
|
||||
|
||||
; Run preinstall tasks
|
||||
SetDetailsPrint both
|
||||
!insertmacro QzInstaller "preinstall" "" ""
|
||||
|
||||
; Run install tasks
|
||||
!insertmacro QzInstaller "install" "--dest" $INSTDIR
|
||||
|
||||
; Run certgen tasks
|
||||
SetOutPath $INSTDIR
|
||||
!insertmacro QzInstaller "certgen" "" ""
|
||||
|
||||
; Launch a non-elevated instance of ${project.name}
|
||||
${StdUtils.ExecShellAsUser} $0 "$INSTDIR\${project.filename}.exe" "open" ""
|
||||
SectionEnd
|
||||
|
||||
!macro Init
|
||||
${If} ${RunningX64}
|
||||
SetRegView 64
|
||||
${DisableX64FSRedirection}
|
||||
${EndIf}
|
||||
${If} $INSTDIR == ""
|
||||
${If} ${RunningX64}
|
||||
StrCpy $INSTDIR "$PROGRAMFILES64\${project.name}"
|
||||
${Else}
|
||||
StrCpy $INSTDIR "$PROGRAMFILES\${project.name}"
|
||||
${EndIf}
|
||||
${EndIf}
|
||||
!macroend
|
||||
|
||||
; Runs for installs
|
||||
Function .onInit
|
||||
!insertmacro Init
|
||||
FunctionEnd
|
||||
91
old code/tray/ant/windows/windows-launcher.nsi.in
Executable file
@@ -0,0 +1,91 @@
|
||||
!include x64.nsh
|
||||
!include LogicLib.nsh
|
||||
|
||||
!ifdef NSIS_UNICODE
|
||||
!addplugindir "${basedir}/ant/windows/nsis/Plugins/Release_Unicode"
|
||||
!else
|
||||
!addplugindir "${basedir}/ant/windows/nsis/Plugins/Release_ANSI"
|
||||
!endif
|
||||
!addincludedir "${basedir}/ant/windows/nsis/Include"
|
||||
!include StdUtils.nsh
|
||||
!include StrLoc.nsh
|
||||
!include FindJava.nsh
|
||||
|
||||
!insertmacro GetParameters
|
||||
|
||||
; Run this exe as non-admin
|
||||
RequestExecutionLevel user
|
||||
|
||||
; Application information
|
||||
Name "${project.name}"
|
||||
Caption "${project.name}"
|
||||
Icon "${basedir}/assets/branding/windows-icon.ico"
|
||||
OutFile "${nsis.outfile}"
|
||||
|
||||
SilentInstall silent
|
||||
AutoCloseWindow true
|
||||
ShowInstDetails nevershow
|
||||
|
||||
; Full path to jar
|
||||
!define JAR "$EXEDIR/${project.filename}.jar"
|
||||
|
||||
Section
|
||||
${If} ${RunningX64}
|
||||
${DisableX64FSRedirection}
|
||||
${EndIf}
|
||||
SetOutPath $EXEDIR
|
||||
|
||||
; Get params to pass to jar
|
||||
Var /GLOBAL params
|
||||
${GetParameters} $params
|
||||
|
||||
; Sets the $java variable
|
||||
Push "$EXEDIR"
|
||||
Call FindJava
|
||||
|
||||
Var /GLOBAL opts
|
||||
StrCpy $opts "${launch.opts}"
|
||||
; Handle jdk9+ flags
|
||||
${If} $java_major >= 9
|
||||
StrCpy $opts "${launch.opts} ${launch.jigsaw}"
|
||||
${EndIf}
|
||||
|
||||
; Check for user overridable launch options
|
||||
ClearErrors
|
||||
ReadEnvStr $R0 ${launch.overrides}
|
||||
IfErrors +2 0
|
||||
StrCpy $opts "$opts $R0"
|
||||
|
||||
Var /GLOBAL command
|
||||
StrCpy $command '"$javaw" $opts -jar "${JAR}" $params'
|
||||
|
||||
; If ends in "-console.exe", use "cmd /s /k" to launch
|
||||
${StrLoc} $R1 "${nsis.outfile}" "-console.exe" "<"
|
||||
${If} $R1 == "0"
|
||||
ExpandEnvStrings $R2 %COMSPEC%
|
||||
StrCpy $command '"$R2" /s /k "$command"'
|
||||
${EndIf}
|
||||
|
||||
; Allow return of exit code
|
||||
${StrLoc} $R2 $params "--wait" "<"
|
||||
${If} $R2 != ""
|
||||
; Switch from /k to /c to capture exit code from -console.exe
|
||||
${StrRep} $command "$command" " /k " " /c "
|
||||
ExecWait $command $R3
|
||||
; Set error-level
|
||||
SetErrorLevel $R3
|
||||
${Else}
|
||||
Exec $command
|
||||
${EndIf}
|
||||
|
||||
${If} ${RunningX64}
|
||||
${EnableX64FSRedirection}
|
||||
${EndIf}
|
||||
SectionEnd
|
||||
|
||||
Function .onInit
|
||||
${If} ${RunningX64}
|
||||
SetRegView 64
|
||||
${DisableX64FSRedirection}
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
117
old code/tray/ant/windows/windows-uninstaller.nsi.in
Executable file
@@ -0,0 +1,117 @@
|
||||
!define MUI_BGCOLOR "SYSCLR:Window"
|
||||
!define MUI_TEXTCOLOR "SYSCLR:WindowText"
|
||||
!include MUI2.nsh
|
||||
!include x64.nsh
|
||||
!include LogicLib.nsh
|
||||
!include FileFunc.nsh
|
||||
!include WinMessages.nsh
|
||||
|
||||
!ifdef NSIS_UNICODE
|
||||
!addplugindir "${basedir}/ant/windows/nsis/Plugins/Release_Unicode"
|
||||
!else
|
||||
!addplugindir "${basedir}/ant/windows/nsis/Plugins/Release_ANSI"
|
||||
!endif
|
||||
!addincludedir "${basedir}/ant/windows/nsis/Include"
|
||||
!include StdUtils.nsh
|
||||
!include SetTitleBar.nsh
|
||||
!include FindJava.nsh
|
||||
|
||||
!define MUI_PRODUCT "${project.name}"
|
||||
!define MUI_VERSION "${build.version}"
|
||||
; Branding for qz only
|
||||
!if "${project.filename}" == "qz-tray"
|
||||
!define MUI_ICON "${basedir}/ant/windows/nsis/uninstall.ico"
|
||||
!else
|
||||
!define MUI_ICON "${basedir}/assets/branding/windows-icon.ico"
|
||||
!endif
|
||||
|
||||
!define MUI_PAGE_HEADER_TEXT "Uninstall ${project.name}"
|
||||
!define MUI_PAGE_HEADER_SUBTEXT "Remove ${project.name} from your computer"
|
||||
!define MUI_INSTFILESPAGE_FINISHHEADER_TEXT "Uninstallation Complete"
|
||||
!define MUI_INSTFILESPAGE_FINISHHEADER_SUBTEXT "Uninstall was completed successfully."
|
||||
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro GetParameters
|
||||
|
||||
RequestExecutionLevel admin
|
||||
CRCCheck On
|
||||
|
||||
Name "Uninstall ${project.name}"
|
||||
Caption "Uninstall ${project.name}"
|
||||
Icon "${basedir}/ant/windows/nsis/uninstall.ico"
|
||||
OutFile "${nsis.outfile}"
|
||||
|
||||
Var /GLOBAL RESPAWN
|
||||
Var /GLOBAL DELETE_DIR
|
||||
Var /GLOBAL DELETE_EXE
|
||||
|
||||
Section
|
||||
${SetTitlebar} "Uninstall"
|
||||
SetDetailsPrint textonly
|
||||
DetailPrint "Uninstalling"
|
||||
SetDetailsPrint listonly
|
||||
|
||||
${GetParameters} $0
|
||||
${GetOptions} "$0" "/RESPAWN=" $RESPAWN
|
||||
${GetOptions} "$0" "/DELETE_DIR=" $DELETE_DIR
|
||||
${GetOptions} "$0" "/DELETE_EXE=" $DELETE_EXE
|
||||
|
||||
${If} $RESPAWN != ""
|
||||
; We're running from $TEMP; Perform the uninstall
|
||||
|
||||
; Set environmental variable for silent uninstall to be picked up by Java
|
||||
${If} ${Silent}
|
||||
System::Call 'Kernel32::SetEnvironmentVariable(t, t)i ("${vendor.name}_silent", "1").r0'
|
||||
${EndIf}
|
||||
|
||||
; Set $javaw variable
|
||||
Push "$DELETE_DIR"
|
||||
Call FindJava
|
||||
|
||||
; Run uninstall step using jar
|
||||
SetDetailsPrint textonly
|
||||
DetailPrint "Running uninstall..."
|
||||
SetDetailsPrint none ; Temporarily suppress details
|
||||
SetOutPath $DELETE_DIR
|
||||
SetDetailsPrint listonly
|
||||
DetailPrint 'Running uninstall: "$java" ${install.opts} -jar "$DELETE_DIR\${project.filename}.jar" uninstall'
|
||||
ClearErrors
|
||||
nsExec::ExecToLog '"$java" ${install.opts} -jar "$DELETE_DIR\${project.filename}.jar" uninstall'
|
||||
Pop $0
|
||||
${If} "$0" != "0"
|
||||
Abort "Uninstall failed."
|
||||
${EndIf}
|
||||
|
||||
; Remove all files
|
||||
DetailPrint "Removing remaining files..."
|
||||
SetDetailsPrint none ; Temporarily suppress details
|
||||
SetOutPath $TEMP
|
||||
RMDir /r "$DELETE_DIR"
|
||||
|
||||
; Remove self from $TEMP after reboot
|
||||
Delete /REBOOTOK $EXEPATH
|
||||
|
||||
${If} ${RunningX64}
|
||||
${EnableX64FSRedirection}
|
||||
${EndIf}
|
||||
SetDetailsPrint both
|
||||
${Else}
|
||||
; We're NOT running from $TEMP, copy to temp and respawn ourself
|
||||
GetTempFileName $0
|
||||
CopyFiles "$EXEPATH" "$0"
|
||||
${If} ${Silent}
|
||||
Exec '"$0" /S /RESPAWN=1 /DELETE_DIR="$EXEDIR" /DELETE_EXE="$EXEPATH"'
|
||||
${Else}
|
||||
Exec '"$0" /RESPAWN=1 /DELETE_DIR="$EXEDIR" /DELETE_EXE="$EXEPATH"'
|
||||
${EndIf}
|
||||
Quit
|
||||
${EndIf}
|
||||
SectionEnd
|
||||
|
||||
Function .onInit
|
||||
${If} ${RunningX64}
|
||||
SetRegView 64
|
||||
${DisableX64FSRedirection}
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
BIN
old code/tray/assets/branding/apple-icon.icns
Executable file
23
old code/tray/assets/branding/linux-icon.svg
Executable file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg id="svg4208" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="128" width="128" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 128.00001 128.00001">
|
||||
<metadata id="metadata4213">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
||||
<dc:title/>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g id="layer1" transform="translate(-125.25 -253.66)">
|
||||
<path id="XMLID_48_" d="m253.07 310.83v2.3662l-0.78875 3.9437-5.5211 32.338-65.465 30.761v-41.014c0-5.5212-2.3662-11.042-5.5212-14.197l-0.78873-0.78874-49.69-46.535 73.352-22.085 48.113 40.226 0.78875 0.78875c3.1549 3.1549 5.5211 7.8874 5.5211 14.197z" fill="#44aa53"/>
|
||||
<path id="rect3864" d="m172.93 304.22 46.535-15.775 11.042 8.6761-46.535 17.352-11.042-10.254z" fill="#2a6831"/>
|
||||
<path id="path3860" d="m161.58 270.6" fill="none"/>
|
||||
<path id="XMLID_47_" d="m182.08 308.46 37.071-13.408s0-22.085-22.085-34.704l-36.282 11.042c0.78873 0 22.873 14.197 21.296 37.071z" fill="#fff"/>
|
||||
<path id="XMLID_45_" d="m156.84 339.22" fill="#597239"/>
|
||||
<path id="XMLID_37_" d="m181.29 338.92v41.32l-43.977-34.169-11.994-68.337 50.373 46.882 0.79958 0.79461c2.3987 2.3839 4.7974 7.9462 4.7974 13.508z" fill="#2a6831"/>
|
||||
<path id="XMLID_35_" d="m181.29 380.24z" fill="#597239"/>
|
||||
<polygon id="XMLID_5_" points="425.9 74 425.9 74" fill="#597239" transform="matrix(7.8874 0 0 7.8874 -3177.9 -203.43)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
old code/tray/assets/branding/windows-icon.ico
Executable file
|
After Width: | Height: | Size: 361 KiB |
33
old code/tray/assets/epl_multiples.txt
Executable file
@@ -0,0 +1,33 @@
|
||||
|
||||
N
|
||||
q812;four inch width for 203dpi printer
|
||||
Q1218,26;six inch height for 203dpi printer
|
||||
B5,26,0,1A,3,7,152,B,"0001"
|
||||
A310,26,0,3,1,1,N,"SKU 00001 MFG 0001"
|
||||
A310,56,0,3,1,1,N,"QZ-Tray Java Application"
|
||||
A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"
|
||||
A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"
|
||||
A310,146,0,3,1,1,N,"EDIT EPL_MULTIPLES.TXT"
|
||||
P1,1
|
||||
|
||||
N
|
||||
q812
|
||||
Q1218,26
|
||||
B5,26,0,1A,3,7,152,B,"0002"
|
||||
A310,26,0,3,1,1,N,"SKU 00002 MFG 0002"
|
||||
A310,56,0,3,1,1,N,"QZ-Tray Java Application"
|
||||
A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"
|
||||
A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"
|
||||
A310,146,0,3,1,1,N,"EDIT EPL_MULTIPLES.TXT"
|
||||
P1,1
|
||||
|
||||
N
|
||||
q812
|
||||
Q1218,26
|
||||
B5,26,0,1A,3,7,152,B,"0003"
|
||||
A310,26,0,3,1,1,N,"SKU 00003 MFG 0003"
|
||||
A310,56,0,3,1,1,N,"QZ-Tray Java Application"
|
||||
A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"
|
||||
A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"
|
||||
A310,146,0,3,1,1,N,"EDIT EPL_MULTIPLES.TXT"
|
||||
P1,1
|
||||
11
old code/tray/assets/epl_sample.txt
Executable file
@@ -0,0 +1,11 @@
|
||||
|
||||
N
|
||||
q812
|
||||
Q1218,26; q and Q values edited to reflect 4x6 inch size at 203 dpi
|
||||
B5,26,0,1A,3,7,152,B,"1234"
|
||||
A310,26,0,3,1,1,N,"SKU 00000 MFG 0000"
|
||||
A310,56,0,3,1,1,N,"QZ-Tray Java Application"
|
||||
A310,86,0,3,1,1,N,"TEST PRINT SUCCESSFUL"
|
||||
A310,116,0,3,1,1,N,"FROM SAMPLE.HTML"
|
||||
A310,146,0,3,1,1,N,"EDIT EPL_SAMPLE.TXT"
|
||||
P1,1
|
||||
BIN
old code/tray/assets/escpos_sample.bin
Executable file
25
old code/tray/assets/fgl_sample.txt
Executable file
@@ -0,0 +1,25 @@
|
||||
<n><DA><RL><RC300,20><F12>BOCA <F6><RC100,40>
|
||||
<NR><RC290,110><RL><F6><HW1,1>PROM=
|
||||
<RC300,160><RL><HW1,1><VA7><RC370,740><RU>GHOSTWRITER
|
||||
<RC48,880><RR><F2>FRIENDLY GHOST LANGUAGE
|
||||
<RC52,862>PLACE LETTERS ANYWHERE
|
||||
<RC80,1170><F6><RR>VOID
|
||||
<RC15,1100><F3>TEST TICKET ONLY
|
||||
<RC8,1010><X2><NXL10>*GHOST 123*<RR>
|
||||
<RC78,915> CODE 39
|
||||
<RU><RC320,740><BS17,30>TICKET & LABEL PRINTER
|
||||
<NR><F3><RC0,300>EXCELLENT PRINT QUALITY
|
||||
<NR><RC30,300> Print any bar code
|
||||
<RC70,300><X2><OL6>^CODE 128^
|
||||
<RC90,250><RR>CODE 128
|
||||
<RC96,340><X3><NXP10>*MONKEY*
|
||||
<RC206,340><X2><NP6>*MONKEY*
|
||||
<F2><HW1,1><NR><F1><SP180,640><LO1>
|
||||
<RC371,385><F2><NR>SW1= SW2= SW3=<RC371,824>LEFT = 1 RIGHT = 0
|
||||
<RC385,150><F11>Script printing is now standard.
|
||||
<RC430,150><F9>High density printing is clear and readable
|
||||
<RC450,150><F2>High density printing is clear and readable
|
||||
<RC470,150><F1>Legal size printing
|
||||
<RC0,100><LT4><VX1200>
|
||||
<p>
|
||||
|
||||
BIN
old code/tray/assets/img/fade-test.png
Executable file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
old code/tray/assets/img/image_sample.png
Executable file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
old code/tray/assets/img/image_sample_bw.png
Executable file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
old code/tray/assets/pdf_sample.pdf
Executable file
12
old code/tray/assets/pgl_sample.txt
Executable file
@@ -0,0 +1,12 @@
|
||||
~CREATE;DATAMATRIX;144
|
||||
SCALE;DOT;300;300
|
||||
ALPHA
|
||||
POINT;50;100;16;9;*Printed using QZ Tray*
|
||||
STOP
|
||||
BARCODE
|
||||
DATAMATRIX;XD16;C20;R20;ECC200;ID5;150;150
|
||||
*0100000123000017*
|
||||
STOP
|
||||
END
|
||||
~EXECUTE;DATAMATRIX;1
|
||||
~NORMAL
|
||||
23
old code/tray/assets/sbpl_sample.txt
Executable file
@@ -0,0 +1,23 @@
|
||||
AA1V01678H0812
|
||||
PS%0H0040V01510FW02H0735
|
||||
%2H200V1590P02RDB@1,057,056,SATO
|
||||
%0H0040V01076FW02H0735
|
||||
%2H0353V01215P02RDB@0,026,025,BEST BEFORE
|
||||
%2H0761V01215P02RDB@0,026,025,BATCH/LOT
|
||||
%2H0761V01370P02RDB@0,026,025,CONTENT
|
||||
%2H0761V01489P02RDB@0,026,025,SSCC
|
||||
%2H0758V01590P02RDB@1,057,056,Product
|
||||
%2H0777V01669P02RDB@0,057,056,
|
||||
%2H0761V01183P02RDB@0,061,062,223344
|
||||
%2H0589V00109P02RDB@1,038,037,(00)038312345600000018
|
||||
%2H0741V01052BG04256>I>F0203831234560087370001
|
||||
%2H0719V00374BG04256>I>F00038312345600000018
|
||||
%2H0617V00786P02RDB@1,038,037,(02)03831234560087(37)0001
|
||||
%2H0139V01370P02RDB@0,026,025,COUNT
|
||||
%2H0139V01344P02RDB@0,061,062,0001
|
||||
%2H0761V01344P02RDB@0,061,062,03831234560087
|
||||
%2H0761V01463P02RDB@1,061,062,038312345600000018
|
||||
%2H0675V00697BG04240>I>F1525052010223344
|
||||
%2H0559V00443P02RDB@1,038,037,(15)250520(10)223344
|
||||
%2H0355V01182P02RDB@0,061,062,20.05.25
|
||||
Q1Z
|
||||
38
old code/tray/assets/signing/sign-message.R
Executable file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# Echoes the signed message and exits
|
||||
# usage: R sign-message.R "test"
|
||||
#
|
||||
|
||||
#########################################################
|
||||
# WARNING WARNING WARNING #
|
||||
#########################################################
|
||||
# #
|
||||
# This file is intended for demonstration purposes #
|
||||
# only. #
|
||||
# #
|
||||
# It is the SOLE responsibility of YOU, the programmer #
|
||||
# to prevent against unauthorized access to any signing #
|
||||
# functions. #
|
||||
# #
|
||||
# Organizations that do not protect against un- #
|
||||
# authorized signing will be black-listed to prevent #
|
||||
# software piracy. #
|
||||
# #
|
||||
# -QZ Industries, LLC #
|
||||
# #
|
||||
#########################################################
|
||||
|
||||
library(openssl)
|
||||
|
||||
mykey <- "private-key.pem"
|
||||
|
||||
# Treat command line argument as message to be signed
|
||||
message <- enc2utf8(commandArgs(trailingOnly = TRUE))
|
||||
|
||||
# Load the private key
|
||||
key <- read_key(file = mykey, password = mypass)
|
||||
|
||||
# Create the signature
|
||||
sig <- signature_create(serialize(message, NULL), hash = sha512, key = key) # Use hash = sha1 for QZ Tray 2.0 and older
|
||||
|
||||
print(sig)
|
||||
50
old code/tray/assets/signing/sign-message.asp
Executable file
@@ -0,0 +1,50 @@
|
||||
<%
|
||||
'#########################################################
|
||||
'# WARNING WARNING WARNING #
|
||||
'#########################################################
|
||||
'# #
|
||||
'# This file is intended for demonstration purposes #
|
||||
'# only. #
|
||||
'# #
|
||||
'# It is the SOLE responsibility of YOU, the programmer #
|
||||
'# to prevent against unauthorized access to any signing #
|
||||
'# functions. #
|
||||
'# #
|
||||
'# Organizations that do not protect against un- #
|
||||
'# authorized signing will be black-listed to prevent #
|
||||
'# software piracy. #
|
||||
'# #
|
||||
'# -QZ Industries, LLC #
|
||||
'# #
|
||||
'#########################################################
|
||||
Option Explicit
|
||||
Dim rsa, pem, sig, data, glob, success, password
|
||||
' New unlock method for Chilkat - Unregistered version, only good for 30 days
|
||||
Set glob = Server.CreateObject("Chilkat_9_5_0.Global")
|
||||
success = glob.UnlockBundle("Anything for 30-day trial")
|
||||
If (success <> 1) Then
|
||||
Response.Write "<pre>" & Server.HTMLEncode(glob.LastErrorText) & "</pre>"
|
||||
Response.End
|
||||
End If
|
||||
|
||||
' ActiveX library http://www.chilkatsoft.com/
|
||||
Set pem = CreateObject("Chilkat_9_5_0.Pem")
|
||||
Set rsa = CreateObject("Chilkat_9_5_0.Rsa")
|
||||
|
||||
data = request("request")
|
||||
|
||||
password = ""
|
||||
success = pem.LoadPemFile("private-key.pem", password)
|
||||
If (success <> 1) Then
|
||||
Response.Write "<pre>" & Server.HTMLEncode(pem.LastErrorText) & "</pre>"
|
||||
Response.End
|
||||
End If
|
||||
|
||||
rsa.ImportPrivateKey(pem.GetPrivateKey(0).getXml())
|
||||
rsa.EncodingMode = "base64"
|
||||
sig = rsa.SignStringENC(data, "SHA-512") ' Use "SHA-1" for QZ Tray 2.0 and older
|
||||
|
||||
Response.ContentType = "text/plain"
|
||||
Response.Write Server.HTMLEncode(sig)
|
||||
|
||||
%>
|
||||
67
old code/tray/assets/signing/sign-message.bouncycastle.cs
Executable file
@@ -0,0 +1,67 @@
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
|
||||
// Public method for signing the input string with the private key
|
||||
// ===============================================================
|
||||
|
||||
string privateKey = "private-key.pem"; // PKCS#8 PEM file
|
||||
|
||||
string SignMessage(string msg)
|
||||
{
|
||||
// Convert the input string to a byte array
|
||||
byte[] input = Encoding.ASCII.GetBytes(msg);
|
||||
|
||||
// Initialize the signer with the algorithm and the private key
|
||||
ISigner sig = SignerUtilities.GetSigner("SHA512withRSA");
|
||||
sig.Init(true, getPrivateKey());
|
||||
|
||||
// Generate signature and return it as a base64 string
|
||||
sig.BlockUpdate(input, 0, input.Length);
|
||||
return Convert.ToBase64String(sig.GenerateSignature());
|
||||
}
|
||||
|
||||
AsymmetricKeyParameter getPrivateKey()
|
||||
{
|
||||
using (var reader = System.IO.File.OpenText(privateKey))
|
||||
{
|
||||
var pem = new PemReader(reader).ReadObject();
|
||||
return pem as AsymmetricKeyParameter ?? (pem as AsymmetricCipherKeyPair).Private;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Public method for returning the certificate
|
||||
// ===========================================
|
||||
|
||||
string certificate = "digital-certificate.txt";
|
||||
|
||||
string GetCertificate()
|
||||
{
|
||||
using (var reader = System.IO.File.OpenText(certificate))
|
||||
{
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
73
old code/tray/assets/signing/sign-message.cfm
Executable file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* ColdFusion signing example
|
||||
* Echoes the signed message and exits
|
||||
*/
|
||||
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
<cfset signature = sign("private-key.pem", url.request)>
|
||||
<cfcontent type="text/plain">
|
||||
<cfoutput>#signature#</cfoutput>
|
||||
<cfscript>
|
||||
|
||||
/**
|
||||
* Sign the given string
|
||||
* @keyPath Path to PEM formatted private key
|
||||
* @message message to be signed
|
||||
* @encoding I am the encoding used when returning the signature (base64 by default).
|
||||
* @output false
|
||||
*/
|
||||
public any function sign(required string keyPath, required string message, string algorithm = "SHA512withRSA", string encoding = "base64") {
|
||||
// Note: change algorithm to "SHA1withRSA" for QZ Tray 2.0 and older
|
||||
createObject("java", "java.security.Security")
|
||||
.addProvider(createObject("java", "org.bouncycastle.jce.provider.BouncyCastleProvider").init());
|
||||
privateKey = createPrivateKey(fileRead(expandPath(keyPath)));
|
||||
var signer = createObject("java", "java.security.Signature").getInstance(javaCast( "string", algorithm ));
|
||||
signer.initSign(privateKey);
|
||||
signer.update(charsetDecode(message, "utf-8"));
|
||||
var signedBytes = signer.sign();
|
||||
return encoding == "binary" ? signedBytes : binaryEncode(signedBytes, encoding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the private key using the provided pem formatted content.
|
||||
*
|
||||
* @contents PEM key contents
|
||||
* @output false
|
||||
*/
|
||||
private any function createPrivateKey(required string contents) {
|
||||
var pkcs8 = createObject("java", "java.security.spec.PKCS8EncodedKeySpec").init(
|
||||
binaryDecode(stripKeyDelimiters(contents), "base64")
|
||||
);
|
||||
|
||||
return createObject("java", "java.security.KeyFactory")
|
||||
.getInstance(javaCast( "string", "RSA" )).generatePrivate(pkcs8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip X509 cert delimiters
|
||||
*
|
||||
* @keyText PEM formatted key data
|
||||
* @output false
|
||||
*/
|
||||
private string function stripKeyDelimiters(required string keyText) {
|
||||
return trim(reReplace(keyText, "-----(BEGIN|END)[^\r\n]+", "", "all" ));
|
||||
}
|
||||
</cfscript>
|
||||
54
old code/tray/assets/signing/sign-message.cls
Executable file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Salesforce APEX Signing Example
|
||||
* Returns the signed message to a wired controller
|
||||
*/
|
||||
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
public with sharing class SignMessage {
|
||||
@AuraEnabled(cacheable = true)
|
||||
public static String signMessage(String toSign){
|
||||
String privateKeyBase64 = '<private-key.pem content without header or footer>';
|
||||
|
||||
Blob sig = Crypto.sign('RSA-SHA512',
|
||||
Blob.valueOf(toSign),
|
||||
EncodingUtil.base64Decode(privateKeyBase64));
|
||||
|
||||
return EncodingUtil.base64Encode(sig);
|
||||
}
|
||||
}
|
||||
|
||||
/** JavaScript - Adjust as needed
|
||||
|
||||
import signMessage from '@salesforce/apex/SignMessage.signMessage';
|
||||
@wire(signMessage)
|
||||
|
||||
qz.security.setSignatureAlgorithm("SHA512");
|
||||
qz.security.setSignaturePromise(function(toSign) {
|
||||
return function (resolve, reject) {
|
||||
try {
|
||||
resolve(signMessage({toSign : toSign}));
|
||||
} catch(err) {
|
||||
reject(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
**/
|
||||
53
old code/tray/assets/signing/sign-message.core.cs
Executable file
@@ -0,0 +1,53 @@
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Web.Services;
|
||||
|
||||
// To convert a .PEM PrivateKey:
|
||||
// openssl pkcs12 -export -inkey private-key.pem -in digital-certificate.txt -out private-key.pfx
|
||||
private static X509KeyStorageFlags STORAGE_FLAGS = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable;
|
||||
|
||||
public IActionResult Index(string request)
|
||||
{
|
||||
var KEY = "/path/to/private-key.pfx";
|
||||
var PASS = "";
|
||||
|
||||
try
|
||||
{
|
||||
byte[] data = new ASCIIEncoding().GetBytes(request);
|
||||
var cert = new X509Certificate2(KEY, PASS, STORAGE_FLAGS);
|
||||
RSA rsa = (RSA)cert.GetRSAPrivateKey();
|
||||
var signed = rsa.SignData(data, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
|
||||
string base64 = Convert.ToBase64String(signed);
|
||||
return Content(base64);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if((STORAGE_FLAGS & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
|
||||
{
|
||||
// IISExpress may fail with "Invalid provider type specified"; remove MachineKeySet flag, try again
|
||||
STORAGE_FLAGS = STORAGE_FLAGS & ~X509KeyStorageFlags.MachineKeySet;
|
||||
return Index(request);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
80
old code/tray/assets/signing/sign-message.cs
Executable file
@@ -0,0 +1,80 @@
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Web.Services;
|
||||
|
||||
// To convert a .PEM PrivateKey:
|
||||
// openssl pkcs12 -export -inkey private-key.pem -in digital-certificate.txt -out private-key.pfx
|
||||
private static X509KeyStorageFlags STORAGE_FLAGS = X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable;
|
||||
|
||||
/**
|
||||
* Note, this example is for .NET Forms/PageMethods
|
||||
* For MVC, change the following:
|
||||
*
|
||||
* public ActionResult SignMessage() {
|
||||
* string request = Request.QueryString["request"];
|
||||
* ...
|
||||
* return Content(base64, "text/plain");
|
||||
* ...
|
||||
* return SignMessage();
|
||||
*
|
||||
* ... and replace PageMethods calls with fetch("@Url.Content("./SignMessage/?request=")" + toSign
|
||||
*/
|
||||
[WebMethod]
|
||||
public static string SignMessage(string request)
|
||||
{
|
||||
//var WEBROOT_PATH = HttpContext.Current.Server.MapPath("/");
|
||||
//var CURRENT_PATH = HttpContext.Current.Server.MapPath("~");
|
||||
//var PARENT_PATH = System.IO.Directory.GetParent(WEBROOT).Parent.FullName;
|
||||
var KEY = "/path/to/private-key.pfx";
|
||||
var PASS = "";
|
||||
|
||||
try
|
||||
{
|
||||
var cert = new X509Certificate2(KEY, PASS, STORAGE_FLAGS);
|
||||
RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PrivateKey; // PFX defaults to the weaker "SHA1"
|
||||
byte[] data = new ASCIIEncoding().GetBytes(request);
|
||||
RSACryptoServiceProvider cspStrong = new RSACryptoServiceProvider(); // 2.1 and higher: Make RSACryptoServiceProvider that can handle SHA256, SHA512
|
||||
cspStrong.ImportParameters(csp.ExportParameters(true)); // Copy to stronger RSACryptoServiceProvider
|
||||
byte[] hash = new SHA512CryptoServiceProvider().ComputeHash(data); // Use SHA1CryptoServiceProvider for QZ Tray 2.0 and older
|
||||
string base64 = Convert.ToBase64String(cspStrong.SignHash(hash, CryptoConfig.MapNameToOID("SHA512"))); // Use "SHA1" for QZ Tray 2.0 and older
|
||||
return base64;
|
||||
|
||||
/*
|
||||
* // Or per https://stackoverflow.com/a/50104158/3196753
|
||||
* var cert = new X509Certificate2(KEY, PASS, STORAGE_FLAGS);
|
||||
* var csp = cert.GetRSAPrivateKey();
|
||||
* byte[] data = new ASCIIEncoding().GetBytes(request);
|
||||
* return Convert.ToBase64String(csp.SignData(data, HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1)); // Use "SHA1" for QZ Tray 2.0 and older
|
||||
*/
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
if((STORAGE_FLAGS & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet)
|
||||
{
|
||||
// IISExpress may fail with "Invalid provider type specified"; remove MachineKeySet flag, try again
|
||||
STORAGE_FLAGS = STORAGE_FLAGS & ~X509KeyStorageFlags.MachineKeySet;
|
||||
return SignMessage(request);
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
99
old code/tray/assets/signing/sign-message.go
Executable file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Echos the signed message
|
||||
*/
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
/* Steps:
|
||||
* 1. Convert private key to golang compatible format:
|
||||
* openssl rsa -in private-key.pem -out private-key-updated.pem
|
||||
*/
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var privateKey = "C:\\path\\to\\private-key-updated.pem"
|
||||
var password = "S3cur3P@ssw0rd"
|
||||
var listenPort = ":8080"
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", handler)
|
||||
http.ListenAndServe(listenPort, nil)
|
||||
}
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Add("Content-Type", "text/plain")
|
||||
|
||||
rsaPrivateKey, err := decodeKey(privateKey)
|
||||
|
||||
if err != nil {
|
||||
displayError(w, "Error reading key", err)
|
||||
return
|
||||
}
|
||||
|
||||
data := r.URL.Query().Get("request")
|
||||
|
||||
if len(data) < 1 {
|
||||
displayError(w, "Request cannot be blank", err)
|
||||
return
|
||||
}
|
||||
|
||||
hash := sha1.Sum([]byte(data))
|
||||
rng := rand.Reader
|
||||
signature, err := rsa.SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA512, hash[:]) // Use crypto.SHA1 for QZ Tray 2.0 and older
|
||||
if err != nil {
|
||||
displayError(w, "Error from signing: %s\n", err)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, base64.StdEncoding.EncodeToString(signature))
|
||||
}
|
||||
|
||||
func displayError(w http.ResponseWriter, msg string, err error) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, "500 - Internal Server Error\n\n"+msg+"\n\nDetails:\n", err)
|
||||
}
|
||||
|
||||
func decodeKey(path string) (*rsa.PrivateKey, error) {
|
||||
b, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(b)
|
||||
if x509.IsEncryptedPEMBlock(block) {
|
||||
der, err := x509.DecryptPEMBlock(block, []byte(password))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return x509.ParsePKCS1PrivateKey(der)
|
||||
}
|
||||
|
||||
return x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
}
|
||||
143
old code/tray/assets/signing/sign-message.java
Executable file
@@ -0,0 +1,143 @@
|
||||
// package foo.bar;
|
||||
|
||||
/*
|
||||
* Java signing example
|
||||
* Echoes the signed message and exits
|
||||
*/
|
||||
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
import java.io.*;
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Base64;
|
||||
import java.util.logging.*;
|
||||
|
||||
/**
|
||||
* Utility for creating an RSA SHA1 signature based on a supplied PEM formatted private key
|
||||
*/
|
||||
public class MessageSigner {
|
||||
private static Logger logger = Logger.getLogger(MessageSigner.class.getName());
|
||||
private Signature sig;
|
||||
|
||||
/**
|
||||
* Standard Java usage example, safe to remove
|
||||
*/
|
||||
public static void main(String args[]) throws Exception {
|
||||
if (args.length < 2) {
|
||||
logger.severe("Usage:\nMessageSigner.class [path to private key] [data to sign]\n");
|
||||
System.exit(1);
|
||||
}
|
||||
byte[] key = MessageSigner.readFile(args[0]);
|
||||
String toSign = args[1];
|
||||
MessageSigner ms = new MessageSigner(key);
|
||||
String signature = ms.sign(toSign);
|
||||
|
||||
logger.log(Level.INFO, "Request: {0}", toSign);
|
||||
logger.log(Level.INFO, "Response: {0}", signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Servlet usage example, safe to remove
|
||||
*
|
||||
protected void doProcessRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
// Get request from URL
|
||||
String data = request.getParameter("request");
|
||||
|
||||
String signature = new MessageSigner("private-key.pem").sign(data);
|
||||
|
||||
// Send signed message back
|
||||
response.setContentType("text/plain");
|
||||
PrintWriter out = response.getWriter();
|
||||
out.write(signature);
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an RSA SHA1 signature object for signing
|
||||
* @param keyData
|
||||
* @throws Exception
|
||||
*/
|
||||
public MessageSigner(byte[] keyData) throws Exception {
|
||||
// Warning: PKCS#8 required. If PKCS#1 (RSA) key is provided convert using:
|
||||
// $ openssl pkcs8 -topk8 -inform PEM -outform PEM -in private-key.pem -out private-key-pkcs8.pem -nocrypt
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(parseKeyData(keyData));
|
||||
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||
PrivateKey key = kf.generatePrivate(keySpec);
|
||||
sig = Signature.getInstance("SHA512withRSA"); // Use "SHA1withRSA" for QZ Tray 2.0 and older
|
||||
sig.initSign(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs the specified data with the provided private key, returning the
|
||||
* RSA SHA1 signature
|
||||
* @param data Message to sign
|
||||
* @return Base64 encoded signature
|
||||
* @throws Exception
|
||||
*/
|
||||
public String sign(String data) throws Exception {
|
||||
sig.update(data.getBytes());
|
||||
return Base64.getEncoder().encodeToString(sig.sign());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the raw byte[] data from a file resource
|
||||
* @param path File path to read
|
||||
* @return the raw byte data from file
|
||||
* @throws IOException
|
||||
*/
|
||||
public static byte[] readFile(String path) throws IOException {
|
||||
InputStream is = MessageSigner.class.getResourceAsStream(path);
|
||||
if (is == null) {
|
||||
throw new IOException(String.format("Can't open resource \"%s\"", path));
|
||||
}
|
||||
DataInputStream dis = new DataInputStream(is);
|
||||
byte[] data = new byte[dis.available()];
|
||||
dis.readFully(data);
|
||||
dis.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a base64 encoded private key by stripping the header and footer lines
|
||||
* @param keyData PEM file contents
|
||||
* @return Raw key byes
|
||||
* @throws IOException
|
||||
*/
|
||||
private static byte[] parseKeyData(byte[] keyData) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String[] lines = new String(keyData).split("[\r?\n]+");
|
||||
String[] skips = new String[]{"-----BEGIN", "-----END", ": "};
|
||||
for (String line : lines) {
|
||||
boolean skipLine = false;
|
||||
for (String skip : skips) {
|
||||
if (line.contains(skip)) {
|
||||
skipLine = true;
|
||||
}
|
||||
}
|
||||
if (!skipLine) {
|
||||
sb.append(line.trim());
|
||||
}
|
||||
}
|
||||
return Base64.getDecoder().decode(sb.toString());
|
||||
}
|
||||
|
||||
}
|
||||
89
old code/tray/assets/signing/sign-message.js
Executable file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* JavaScript client-side example using jsrsasign
|
||||
*/
|
||||
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
/**
|
||||
* Depends:
|
||||
* - jsrsasign-latest-all-min.js
|
||||
* - qz-tray.js
|
||||
*
|
||||
* Steps:
|
||||
*
|
||||
* 1. Include jsrsasign 10.9.0 into your web page
|
||||
* <script src="https://cdnjs.cloudflare.com/ajax/libs/jsrsasign/11.1.0/jsrsasign-all-min.js"></script>
|
||||
*
|
||||
* 2. Update the privateKey below with contents from private-key.pem
|
||||
*
|
||||
* 3. Include this script into your web page
|
||||
* <script src="path/to/sign-message.js"></script>
|
||||
*
|
||||
* 4. Remove or comment out any other references to "setSignaturePromise"
|
||||
*
|
||||
* 5. IMPORTANT: Before deploying to production, copy "jsrsasign-all-min.js"
|
||||
* to the web server. Don't trust the CDN above to be available.
|
||||
*/
|
||||
var privateKey = "-----BEGIN PRIVATE KEY-----\n" +
|
||||
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC0z9FeMynsC8+u\n" +
|
||||
"dvX+LciZxnh5uRj4C9S6tNeeAlIGCfQYk0zUcNFCoCkTknNQd/YEiawDLNbxBqut\n" +
|
||||
"bMDZ1aarys1a0lYmUeVLCIqvzBkPJTSQsCopQQ9V8WuT252zzNzs68dVGNdCJd5J\n" +
|
||||
"NRQykpwexmnjPPv0mvj7i8XgG379TyW6P+WWV5okeUkXJ9eJS2ouDYdR2SM9BoVW\n" +
|
||||
"+FgxDu6BmXhozW5EfsnajFp7HL8kQClI0QOc79yuKl3492rH6bzFsFn2lfwWy9ic\n" +
|
||||
"7cP8EpCTeFp1tFaD+vxBhPZkeTQ1HKx6hQ5zeHIB5ySJJZ7af2W8r4eTGYzbdRW2\n" +
|
||||
"4DDHCPhZAgMBAAECggEATvofR3gtrY8TLe+ET3wMDS8l3HU/NMlmKA9pxvjYfw7F\n" +
|
||||
"8h4VBw4oOWPfzU7A07syWJUR72kckbcKMfw42G18GbnBrRQG0UIgV3/ppBQQNg9Y\n" +
|
||||
"QILSR6bFXhLPnIvm/GxVa58pOEBbdec4it2Gbvie/MpJ4hn3K8atTqKk0djwxQ+b\n" +
|
||||
"QNBWtVgTkyIqMpUTFDi5ECiVXaGWZ5AOVK2TzlLRNQ5Y7US8lmGxVWzt0GONjXSE\n" +
|
||||
"iO/eBk8A7wI3zknMx5o1uZa/hFCPQH33uKeuqU5rmphi3zS0BY7iGY9EoKu/o+BO\n" +
|
||||
"HPwLQJ3wCDA3O9APZ3gmmbHFPMFPr/mVGeAeGP/BAQKBgQDaPELRriUaanWrZpgT\n" +
|
||||
"VnKKrRSqPED3anAVgmDfzTQwuR/3oD506F3AMBzloAo3y9BXmDfe8qLn6kgdZQKy\n" +
|
||||
"SFNLz888at96oi+2mEKPpvssqiwE6F3OtEM6yv4DP9KJHaHmXaWv+/sjwjzpFNjs\n" +
|
||||
"wGThBxFvrTWRJqBYsM1XNJJ2EQKBgQDUGbTSwHKqRCYWhQ1GPCZKE98l5UtMKvUb\n" +
|
||||
"hyWWOXoyoeYbJEMfG1ynX4JeXIkl6YtBjYCqszv9PjHa1rowTZaAPJ0V70zyhTcF\n" +
|
||||
"t581ii9LpiejIGrELHvJnW87QmjjStkjwGIqgKLp7Qe6CDjHI9HP1NM0uav/IQLW\n" +
|
||||
"pB6wyEz1yQKBgQCuxPut+Ax2rzM05KB9PAnWzO1zt3U/rtm8IAF8uVVGf7r+EDJ0\n" +
|
||||
"ZXJO6zj5G8WTEYHz5E86GI4ltBW0lKQoKouqdu27sMrv5trXG/CSImOcTVubQot9\n" +
|
||||
"chc1CkOKTp5IeJajafO6j817wZ4N+0gNsbYYEBUCnm/7ojdfT5ficpOoQQKBgQDB\n" +
|
||||
"PgKPmaNfGeQR1Ht5qEfCakR/RF/ML79Nq15FdmytQPBjfjBhYQ6Tt+MRkgGqtxOX\n" +
|
||||
"UBMQc2iOnGHT3puYcrhScec1GufidhjhbqDxqMrag7HNYDWmMlk+IeA7/4+Mtp8L\n" +
|
||||
"gbZuvvCvbLQDfIYueaYpUuBzQ08/jZYGdVU4/+WOcQKBgAGUN0kIB6EM1K/iZ0TN\n" +
|
||||
"jlt8P5UEV3ZCyATWFiGZRhhE2WAh8gv1jx4J26pcUs1n8sd2a1h6ZuBSqsyIlNSp\n" +
|
||||
"xtKsm3bqQFDHRrPcsBX4nanrw9DzkpH1k/I3WMSdGqkDAR3DtL7yXTJXJo2Sbrp5\n" +
|
||||
"EjzSn7DcDE1tL2En/tSVXeUY\n" +
|
||||
"-----END PRIVATE KEY-----";
|
||||
|
||||
qz.security.setSignatureAlgorithm("SHA512"); // Since 2.1
|
||||
qz.security.setSignaturePromise(function(toSign) {
|
||||
return function(resolve, reject) {
|
||||
try {
|
||||
var pk = KEYUTIL.getKey(privateKey);
|
||||
var sig = new KJUR.crypto.Signature({"alg": "SHA512withRSA"}); // Use "SHA1withRSA" for QZ Tray 2.0 and older
|
||||
sig.init(pk);
|
||||
sig.updateString(toSign);
|
||||
var hex = sig.sign();
|
||||
console.log("DEBUG: \n\n" + stob64(hextorstr(hex)));
|
||||
resolve(stob64(hextorstr(hex)));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
reject(err);
|
||||
}
|
||||
};
|
||||
});
|
||||
48
old code/tray/assets/signing/sign-message.jsl
Executable file
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// J# Signing Example
|
||||
// Echoes the signed message and exits
|
||||
//
|
||||
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
module sample
|
||||
|
||||
open System
|
||||
open System.Security.Cryptography
|
||||
open System.Security.Cryptography.X509Certificates
|
||||
open System.IO
|
||||
open System.Text
|
||||
|
||||
let request = "test data"
|
||||
|
||||
// How to associate a private key with the X509Certificate2 class in .net
|
||||
// openssl pkcs12 -export -in private-key.pem -inkey digital-certificate.txt -out private-key.pfx
|
||||
let cert = new X509Certificate2("private-key.pfx")
|
||||
|
||||
let sha1 = new SHA512CryptoServiceProvider() // Use "SHA1CryptoServiceProvider" for QZ Tray 2.0 and older
|
||||
|
||||
let csp = cert.PrivateKey :?> RSACryptoServiceProvider
|
||||
let encoder = new ASCIIEncoding()
|
||||
|
||||
let data = encoder.GetBytes(request)
|
||||
let binaryData = csp.SignData(data, sha1)
|
||||
let output = Convert.ToBase64String(binaryData)
|
||||
|
||||
Console.WriteLine output
|
||||
120
old code/tray/assets/signing/sign-message.jsp
Executable file
@@ -0,0 +1,120 @@
|
||||
<%
|
||||
/*
|
||||
* JSP signing example
|
||||
* Echoes the signed message and exits
|
||||
*/
|
||||
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
%>
|
||||
|
||||
<%@ page import="java.io.*" %>
|
||||
<%@ page import="java.util.*" %>
|
||||
<%@ page import="java.lang.*" %>
|
||||
<%@ page import="java.security.*" %>
|
||||
<%@ page import="java.security.spec.*" %>
|
||||
<%@ page import="java.util.logging.*" %>
|
||||
<%@ page import="javax.xml.bind.DatatypeConverter" %>
|
||||
<%@ page trimDirectiveWhitespaces="true" %>
|
||||
<%@ page language="java" contentType="text/plain charset=UTF-8" pageEncoding="UTF-8"%>
|
||||
|
||||
<%= getSignature(request.getParameter("request")) %>
|
||||
|
||||
|
||||
<%!
|
||||
/**
|
||||
* Creates a signature using the provided private key and the provided (String) data inside Object o.
|
||||
*/
|
||||
private String getSignature(Object o) {
|
||||
// Private key path if placed in CATALINA_HOME/private/ **AND** if JSP is
|
||||
// placed in CATALINA_HOME/webapps/examples/. Adjust as needed.
|
||||
String keyPath = "../../private/private-key.pem";
|
||||
|
||||
// Prepend servlet context path
|
||||
keyPath = getServletContext().getRealPath("/") + keyPath;
|
||||
String req = o == null ? "" : (String)o;
|
||||
|
||||
try {
|
||||
byte[] keyData = cleanseKeyData(readData(keyPath));
|
||||
// Warning: PKCS#8 required. If PKCS#1 (RSA) key is provided convert using:
|
||||
// $ openssl pkcs8 -topk8 -inform PEM -outform PEM -in private-key.pem -out private-key-pkcs8.pem -nocrypt
|
||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyData);
|
||||
KeyFactory kf = KeyFactory.getInstance("RSA");
|
||||
PrivateKey key = kf.generatePrivate(keySpec);
|
||||
Signature sig = Signature.getInstance("SHA512withRSA"); // Use "SHA1withRSA" for QZ Tray 2.0 and older
|
||||
sig.initSign(key);
|
||||
sig.update(req.getBytes());
|
||||
String output = DatatypeConverter.printBase64Binary(sig.sign());
|
||||
return output;
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return "Something went wrong while signing the message.\n" +
|
||||
"Please check server console for sign-message.jsp";
|
||||
}
|
||||
}
|
||||
%>
|
||||
|
||||
<%!
|
||||
/**
|
||||
* Reads the raw byte[] data from a file resource
|
||||
* @param resourcePath
|
||||
* @return the raw byte data from a resource file
|
||||
* @throws IOException
|
||||
*/
|
||||
public byte[] readData(String resourcePath) throws IOException {
|
||||
FileInputStream is = new FileInputStream(resourcePath);
|
||||
|
||||
//InputStream is = getServletContext().getResourceAsStream(resourcePath);
|
||||
if (is == null) {
|
||||
throw new IOException(String.format("Can't open resource \"%s\"", resourcePath));
|
||||
}
|
||||
DataInputStream dis = new DataInputStream(is);
|
||||
byte[] data = new byte[dis.available()];
|
||||
dis.readFully(data);
|
||||
dis.close();
|
||||
return data;
|
||||
}
|
||||
%>
|
||||
|
||||
<%!
|
||||
/**
|
||||
* Parses an X509 PEM formatted base64 encoded private key, returns the decoded
|
||||
* private key byte data
|
||||
* @param keyData PEM file contents, a X509 base64 encoded private key
|
||||
* @return Private key data
|
||||
* @throws IOException
|
||||
*/
|
||||
private byte[] cleanseKeyData(byte[] keyData) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String[] lines = new String(keyData).split("\n");
|
||||
String[] skips = new String[]{"-----BEGIN", "-----END", ": "};
|
||||
for (String line : lines) {
|
||||
boolean skipLine = false;
|
||||
for (String skip : skips) {
|
||||
if (line.contains(skip)) {
|
||||
skipLine = true;
|
||||
}
|
||||
}
|
||||
if (!skipLine) {
|
||||
sb.append(line.trim());
|
||||
}
|
||||
}
|
||||
return DatatypeConverter.parseBase64Binary(sb.toString());
|
||||
}
|
||||
%>
|
||||
43
old code/tray/assets/signing/sign-message.node.js
Executable file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Node.js signing example
|
||||
* Echoes the signed message and exits
|
||||
*/
|
||||
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
var key = "private-key.pem";
|
||||
//var pass = "S3cur3P@ssw0rd";
|
||||
|
||||
app.get('/sign', function(req, res) {
|
||||
var crypto = require('crypto');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var toSign = req.query.requestToSign;
|
||||
|
||||
fs.readFile(path.join(__dirname, '\\' + key), 'utf-8', function(err, privateKey) {
|
||||
var sign = crypto.createSign('SHA512'); // Use "SHA1" for QZ Tray 2.0 and older
|
||||
|
||||
sign.update(toSign);
|
||||
var signature = sign.sign({ key: privateKey/*, passphrase: pass */ }, 'base64');
|
||||
|
||||
res.set('Content-Type', 'text/plain');
|
||||
res.send(signature);
|
||||
});
|
||||
});
|
||||
43
old code/tray/assets/signing/sign-message.odoo.py
Executable file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Python Odoo example for controller.py
|
||||
# Echoes the signed message and exits
|
||||
#
|
||||
|
||||
#########################################################
|
||||
# WARNING WARNING WARNING #
|
||||
#########################################################
|
||||
# #
|
||||
# This file is intended for demonstration purposes #
|
||||
# only. #
|
||||
# #
|
||||
# It is the SOLE responsibility of YOU, the programmer #
|
||||
# to prevent against unauthorized access to any signing #
|
||||
# functions. #
|
||||
# #
|
||||
# Organizations that do not protect against un- #
|
||||
# authorized signing will be black-listed to prevent #
|
||||
# software piracy. #
|
||||
# #
|
||||
# -QZ Industries, LLC #
|
||||
# #
|
||||
#########################################################
|
||||
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
from OpenSSL import crypto
|
||||
import base64
|
||||
|
||||
|
||||
class SignMessage(http.Controller):
|
||||
|
||||
@http.route('/sign-message/', auth='public')
|
||||
def index(self, **kwargs):
|
||||
mypass = None
|
||||
key_file = open('path/to/private-key.pem', 'r')
|
||||
key = key_file.read()
|
||||
key_file.close()
|
||||
password = None
|
||||
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, key, password)
|
||||
sign = crypto.sign(pkey, kwargs.get('request', ''), 'sha512') # Use 'sha1' for QZ Tray 2.0 and older
|
||||
data_base64 = base64.b64encode(sign)
|
||||
return request.make_response(data_base64, [('Content-Type', 'text/plain')])
|
||||
55
old code/tray/assets/signing/sign-message.php
Executable file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* Echoes the signed message and exits
|
||||
*/
|
||||
|
||||
// #########################################################
|
||||
// # WARNING WARNING WARNING #
|
||||
// #########################################################
|
||||
// # #
|
||||
// # This file is intended for demonstration purposes #
|
||||
// # only. #
|
||||
// # #
|
||||
// # It is the SOLE responsibility of YOU, the programmer #
|
||||
// # to prevent against unauthorized access to any signing #
|
||||
// # functions. #
|
||||
// # #
|
||||
// # Organizations that do not protect against un- #
|
||||
// # authorized signing will be black-listed to prevent #
|
||||
// # software piracy. #
|
||||
// # #
|
||||
// # -QZ Industries, LLC #
|
||||
// # #
|
||||
// #########################################################
|
||||
|
||||
// Sample key. Replace with one used for CSR generation
|
||||
$KEY = 'private-key.pem';
|
||||
//$PASS = 'S3cur3P@ssw0rd';
|
||||
|
||||
$req = $_GET['request'];
|
||||
$privateKey = openssl_get_privatekey(file_get_contents($KEY) /*, $PASS */);
|
||||
|
||||
$signature = null;
|
||||
openssl_sign($req, $signature, $privateKey, "sha512"); // Use "sha1" for QZ Tray 2.0 and older
|
||||
|
||||
/*
|
||||
// Or alternately, via phpseclib
|
||||
include('Crypt/RSA.php');
|
||||
$rsa = new Crypt_RSA();
|
||||
$rsa.setHash('sha512'); // Use 'sha1' for QZ Tray 2.0 and older
|
||||
$rsa->loadKey(file_get_contents($KEY));
|
||||
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
|
||||
$signature = $rsa->sign($req);
|
||||
*/
|
||||
|
||||
if ($signature) {
|
||||
header("Content-type: text/plain");
|
||||
echo base64_encode($signature);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
echo '<h1>Error signing message</h1>';
|
||||
http_response_code(500);
|
||||
exit(1);
|
||||
|
||||
?>
|
||||
52
old code/tray/assets/signing/sign-message.pl
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Echoes the signed message and exits
|
||||
# usage: ./sign-message.pl "test"
|
||||
#
|
||||
#########################################################
|
||||
# WARNING WARNING WARNING #
|
||||
#########################################################
|
||||
# #
|
||||
# This file is intended for demonstration purposes #
|
||||
# only. #
|
||||
# #
|
||||
# It is the SOLE responsibility of YOU, the programmer #
|
||||
# to prevent against unauthorized access to any signing #
|
||||
# functions. #
|
||||
# #
|
||||
# Organizations that do not protect against un- #
|
||||
# authorized signing will be black-listed to prevent #
|
||||
# software piracy. #
|
||||
# #
|
||||
# -QZ Industries, LLC #
|
||||
# #
|
||||
#########################################################
|
||||
|
||||
# RSA Crypto libs provided by:
|
||||
# Debian: libcrypt-openssl-rsa-perl
|
||||
# RedHat: perl-Crypt-OpenSSL-RSA
|
||||
use Crypt::OpenSSL::RSA;
|
||||
use MIME::Base64 qw(encode_base64);
|
||||
|
||||
# Get first argument passed to script
|
||||
my $request = $ARGV[0];
|
||||
|
||||
# Path to the private key
|
||||
my $pem_file = "private-key.pem";
|
||||
|
||||
# Read private key
|
||||
my $private_key = do {
|
||||
local $/ = undef;
|
||||
open my $fh, "<", $pem_file
|
||||
or die "could not open $file: $!";
|
||||
<$fh>;
|
||||
};
|
||||
|
||||
# Load private key
|
||||
my $rsa = Crypt::OpenSSL::RSA->new_private_key($private_key);
|
||||
|
||||
# Create signature
|
||||
$rsa->use_sha512_hash(); # use_sha1_hash for QZ Tray 2.0 and older
|
||||
my $sig = encode_base64($rsa->sign($request));
|
||||
|
||||
print $sig;
|
||||
39
old code/tray/assets/signing/sign-message.py
Executable file
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# Python Django example for views.py
|
||||
# Echoes the signed message and exits
|
||||
#
|
||||
|
||||
#########################################################
|
||||
# WARNING WARNING WARNING #
|
||||
#########################################################
|
||||
# #
|
||||
# This file is intended for demonstration purposes #
|
||||
# only. #
|
||||
# #
|
||||
# It is the SOLE responsibility of YOU, the programmer #
|
||||
# to prevent against unauthorized access to any signing #
|
||||
# functions. #
|
||||
# #
|
||||
# Organizations that do not protect against un- #
|
||||
# authorized signing will be black-listed to prevent #
|
||||
# software piracy. #
|
||||
# #
|
||||
# -QZ Industries, LLC #
|
||||
# #
|
||||
#########################################################
|
||||
|
||||
import base64
|
||||
import os
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from django.http import HttpResponse, HttpResponseBadRequest
|
||||
|
||||
def get(self, request, message):
|
||||
# Load signature
|
||||
key = serialization.load_pem_private_key(open("private-key.pem","rb").read(), None, backend=default_backend())
|
||||
# Create the signature
|
||||
signature = key.sign(message.encode('utf-8'), padding.PKCS1v15(), hashes.SHA512()) # Use hashes.SHA1() for QZ Tray 2.0 and older
|
||||
# Echo the signature
|
||||
return HttpResponse(base64.b64encode(signature), content_type="text/plain")
|
||||
|
||||
36
old code/tray/assets/signing/sign-message.rb
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env ruby
|
||||
#
|
||||
# Echoes the signed message and exits
|
||||
# usage: ./sign-message.rb "request=test"
|
||||
#
|
||||
#########################################################
|
||||
# WARNING WARNING WARNING #
|
||||
#########################################################
|
||||
# #
|
||||
# This file is intended for demonstration purposes #
|
||||
# only. #
|
||||
# #
|
||||
# It is the SOLE responsibility of YOU, the programmer #
|
||||
# to prevent against unauthorized access to any signing #
|
||||
# functions. #
|
||||
# #
|
||||
# Organizations that do not protect against un- #
|
||||
# authorized signing will be black-listed to prevent #
|
||||
# software piracy. #
|
||||
# #
|
||||
# -QZ Industries, LLC #
|
||||
# #
|
||||
#########################################################
|
||||
|
||||
# Typical rails controller
|
||||
class PrintingController < ActionController::Base
|
||||
def sign
|
||||
digest = OpenSSL::Digest.new('sha512') # Use 'sha1' for QZ Tray 2.0 and older
|
||||
pkey = OpenSSL::PKey::read(File.read(Rails.root.join('lib', 'certs', 'private-key.pem')))
|
||||
|
||||
signed = pkey.sign(digest, params[:request])
|
||||
encoded = Base64.encode64(signed)
|
||||
|
||||
render text: encoded
|
||||
end
|
||||
end
|
||||