Add modern Raspberry Pi OS compatibility

This commit is contained in:
v3d 2026-06-29 09:42:14 +02:00
parent 4636a4f4f6
commit 3b7a16564b
35 changed files with 725 additions and 15678 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/todo.md
/manual.md
/pivilion.config.md

View file

@ -15,3 +15,30 @@ Required hardware:
- Raspberry Pi with WiFi - Raspberry Pi with WiFi
- min 8 GB SD card - min 8 GB SD card
- battery or power adapter - battery or power adapter
## Installation on current Raspberry Pi OS
Pivilion supports Raspberry Pi OS Bullseye, Bookworm, and Trixie. Bookworm and
newer systems use NetworkManager automatically; Bullseye installations using
`dhcpcd` use the legacy hostapd backend. The repository layout and the original
commands are preserved on both backends.
On a fresh Raspberry Pi OS Lite installation:
```sh
git clone https://gitlab.com/hacklab01/pivilion.git
cd pivilion
sudo ./install.sh
sudo reboot
```
The installer defaults to the user that invoked `sudo`, not to a hard-coded
`pi` account. To customize paths, startup mode, hotspot SSID, or Wi-Fi
interface, copy `pivilion.conf.example` to `/boot/firmware/pivilion.conf` (or
`/etc/pivilion.conf`) and edit it before installing. The hotspot is intentionally
open and passwordless.
Use `pikey` to save upstream Wi-Fi credentials, then `onion` and reboot to host
through Tor. Use `hotspot` and reboot to run the local captive gallery at
`http://10.1.1.1/`. HTTPS interception is intentionally not attempted because a
local captive portal cannot present valid certificates for arbitrary sites.

View file

@ -647,6 +647,4 @@
# Include all files in a directory which end in .conf # Include all files in a directory which end in .conf
#conf-dir=/etc/dnsmasq.d/*.conf #conf-dir=/etc/dnsmasq.d/*.conf
interface=wlan0 # Pivilion settings are generated in /etc/dnsmasq.d/pivilion-runtime.conf.
dhcp-range=10.1.0.50,10.1.0.200,12h
address=/#/10.1.0.1

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

5
etc/php/pivilion.ini Normal file
View file

@ -0,0 +1,5 @@
upload_max_filesize = 256M
post_max_size = 272M
max_file_uploads = 100
max_execution_time = 300
memory_limit = 512M

View file

@ -0,0 +1,12 @@
[Unit]
Description=Pivilion captive-portal DHCP and DNS
After=network.target
[Service]
Type=simple
ExecStartPre=/usr/sbin/dnsmasq --test --conf-file=/etc/dnsmasq.d/pivilion-runtime.conf
ExecStart=/usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/dnsmasq.d/pivilion-runtime.conf
Restart=on-failure
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,13 @@
[Unit]
Description=Select Pivilion hotspot or onion networking mode
After=network-pre.target NetworkManager.service dhcpcd.service
Wants=network-pre.target
[Service]
Type=oneshot
ExecStart=/usr/local/lib/pivilion/mode.sh
RemainAfterExit=yes
TimeoutStartSec=90
[Install]
WantedBy=multi-user.target

View file

@ -0,0 +1,4 @@
SocksPort 0
HiddenServiceDir /var/lib/tor/pivilion/
HiddenServiceVersion 3
HiddenServicePort 80 127.0.0.1:80

View file

@ -1,19 +1,8 @@
interface=br0 # Documentation template; mode.sh generates /etc/dnsmasq.d/pivilion-runtime.conf.
interface=@WIFI_INTERFACE@
bind-dynamic
listen-address=10.1.1.1 listen-address=10.1.1.1
no-hosts dhcp-range=10.1.1.2,10.1.1.254,255.255.255.0,72h
dhcp-range=10.1.1.2,10.1.1.254,72h
dhcp-option=option:router,10.1.1.1 dhcp-option=option:router,10.1.1.1
dhcp-authoritative dhcp-authoritative
address=/#/10.1.1.1 address=/#/10.1.1.1
address=/clients1.google.com/1.2.3.4
address=/clients3.google.com/1.2.3.4
address=/connectivitycheck.android.com/1.2.3.4
address=/connectivitycheck.gstatic.com/1.2.3.4
address=/connect.rom.miui.com/generate_204/1.2.3.4
address=/www.apple.com/library/test/success.html/1.2.3.4
server=/0.debian.pool.ntp.org/#
server=/1.debian.pool.ntp.org/#
server=/2.debian.pool.ntp.org/#
server=/3.debian.pool.ntp.org/#
server=/deb.debian.org/debian/#
#server=/formatc.hr/#

View file

@ -1,9 +1,8 @@
interface=wlan0 # Documentation template; mode.sh substitutes the detected interface and SSID.
interface=@WIFI_INTERFACE@
driver=nl80211
channel=6 channel=6
hw_mode=g hw_mode=g
ssid=@HOTSPOT_SSID@
ssid=pivilion
bridge=br0
auth_algs=1 auth_algs=1
wmm_enabled=0 wmm_enabled=0

View file

@ -1,35 +1,2 @@
# interfaces(5) file used by ifup(8) and ifdown(8) # Compatibility note: hotspot addressing is generated at runtime by
# /usr/local/lib/pivilion/mode.sh. This file is intentionally not installed.
# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
auto lo
iface lo inet loopback
iface eth0 inet manual
#avoid stupid Rasbian static IP config via dhcpcd.conf (WTF???)
#auto eth0
#iface eth0 inet static
#address 192.168.1.5
#netmask 255.255.255.0
#gateway 192.168.1.1
allow-hotplug wlan0
iface wlan0 inet static
address 10.1.0.1
netmask 255.255.255.0
network 10.1.0.1
broadcast 10.1.0.255
#allow-hotplug wlan0
#iface wlan0 inet manual
# wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
#allow-hotplug wlan1
#iface wlan1 inet manual
# wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

View file

@ -1,35 +1,2 @@
# interfaces(5) file used by ifup(8) and ifdown(8) # Compatibility note: upstream Wi-Fi is managed by NetworkManager or the
# system wpa_supplicant/dhcpcd configuration. This file is not installed.
# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d
auto lo
iface lo inet loopback
iface eth0 inet manual
#avoid stupid Rasbian static IP config via dhcpcd.conf (WTF???)
#auto eth0
#iface eth0 inet static
#address 192.168.1.5
#netmask 255.255.255.0
#gateway 192.168.1.1
#allow-hotplug wlan0
#iface wlan0 inet static
# address 10.1.0.1
# netmask 255.255.255.0
# network 10.1.0.1
# broadcast 10.1.0.255
allow-hotplug wlan0
iface wlan0 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
allow-hotplug wlan1
iface wlan1 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

View file

@ -1,20 +1,3 @@
#!/bin/bash #!/bin/bash
# Compatibility entry point. Boot-time mode selection is handled by systemd.
service apache2 start exec /usr/local/lib/pivilion/mode.sh hotspot
sleep 1
ifconfig wlan0 down
ifconfig wlan0 up
sleep 1
hostapd -B /etc/hostapd/hostapd.conf
sleep 2
ifconfig br0 up
ifconfig br0 10.1.1.1 netmask 255.255.255.0
sysctl net.ipv4.ip_forward=1
iptables --flush
iptables -t nat --flush
iptables -t nat -A PREROUTING -i br0 -p udp -m udp --dport 53 -j DNAT --to-destination 10.1.1.1:53
iptables -t nat -A PREROUTING -i br0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.1.1.1:80
iptables -t nat -A PREROUTING -i br0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.1.1.1:80
iptables -t nat -A POSTROUTING -j MASQUERADE
service dnsmasq start
exit 0

View file

@ -1,20 +1,3 @@
#!/bin/bash #!/bin/bash
# Deprecated compatibility entry point; /etc/rc.local is no longer modified.
service apache2 start exec /usr/local/lib/pivilion/mode.sh hotspot
sleep 1
ifconfig wlan0 down
ifconfig wlan0 up
sleep 1
hostapd -B /etc/hostapd/hostapd.conf
sleep 2
ifconfig br0 up
ifconfig br0 10.1.1.1 netmask 255.255.255.0
sysctl net.ipv4.ip_forward=1
iptables --flush
iptables -t nat --flush
iptables -t nat -A PREROUTING -i br0 -p udp -m udp --dport 53 -j DNAT --to-destination 10.1.1.1:53
iptables -t nat -A PREROUTING -i br0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 10.1.1.1:80
iptables -t nat -A PREROUTING -i br0 -p tcp -m tcp --dport 443 -j DNAT --to-destination 10.1.1.1:80
iptables -t nat -A POSTROUTING -j MASQUERADE
service dnsmasq start
exit 0

View file

@ -1,23 +1,3 @@
#!/bin/sh -e #!/bin/bash
# # Deprecated compatibility entry point; /etc/rc.local is no longer modified.
# rc.local exec /usr/local/lib/pivilion/mode.sh onion
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
printf "My IP address is %s\n" "$_IP"
fi
# Display onion domain in MOTD
cat /var/lib/tor/hidden_service/hostname > /home/pi/torname
exit 0

133
install.sh Executable file
View file

@ -0,0 +1,133 @@
#!/bin/bash
set -euo pipefail
if [ "$(id -u)" -ne 0 ]; then
echo "Run this installer with sudo: sudo ./install.sh" >&2
exit 1
fi
SOURCE_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
source "$SOURCE_DIR/usr/local/lib/pivilion/common.sh"
pivilion_load_config
export DEBIAN_FRONTEND=noninteractive
is_networkmanager_system() {
command -v nmcli >/dev/null 2>&1 && {
systemctl is-enabled --quiet NetworkManager 2>/dev/null ||
systemctl is-active --quiet NetworkManager 2>/dev/null
}
}
install_packages() {
local packages=(apache2 libapache2-mod-php php php-cli tor dnsmasq nftables iproute2 iw rfkill wget unzip wpasupplicant)
apt-get update
apt-get install -y "${packages[@]}"
if is_networkmanager_system; then
echo "Using the installed NetworkManager backend."
elif command -v dhcpcd >/dev/null 2>&1 || dpkg-query -W dhcpcd5 >/dev/null 2>&1; then
apt-get install -y hostapd dhcpcd5
echo "Using the installed dhcpcd/hostapd backend."
else
apt-get install -y network-manager
systemctl enable NetworkManager
echo "No active networking backend was found; installed NetworkManager."
fi
}
deploy_files() {
local php_version
install -d -m 0755 /usr/local/lib/pivilion /usr/local/bin /etc/systemd/system /etc/tor/torrc.d
install -m 0644 "$SOURCE_DIR/usr/local/lib/pivilion/common.sh" /usr/local/lib/pivilion/common.sh
install -m 0755 "$SOURCE_DIR/usr/local/lib/pivilion/mode.sh" /usr/local/lib/pivilion/mode.sh
install -m 0755 "$SOURCE_DIR"/usr/local/bin/* /usr/local/bin/
install -m 0644 "$SOURCE_DIR/etc/systemd/system/pivilion-mode.service" /etc/systemd/system/pivilion-mode.service
install -m 0644 "$SOURCE_DIR/etc/systemd/system/pivilion-dnsmasq.service" /etc/systemd/system/pivilion-dnsmasq.service
install -m 0644 "$SOURCE_DIR/etc/tor/torrc.d/pivilion.conf" /etc/tor/torrc.d/pivilion.conf
cat > /etc/pivilion.defaults <<EOF
PIVILION_USER=$PIVILION_USER
PIVILION_HOME=$PIVILION_HOME
PIVILION_DIR=$PIVILION_DIR
PIVILION_WEBROOT=$PIVILION_WEBROOT
PIVILION_MODE=$PIVILION_MODE
PIVILION_HOTSPOT_SSID=$PIVILION_HOTSPOT_SSID
PIVILION_WIFI_INTERFACE=$PIVILION_WIFI_INTERFACE
EOF
chmod 0644 /etc/pivilion.defaults
install -d -m 0755 -o "$PIVILION_USER" -g "$PIVILION_GROUP" "$PIVILION_DIR" "$PIVILION_DIR/config"
cp -a "$SOURCE_DIR/home/pi/pivilion/config/." "$PIVILION_DIR/config/"
chown -R "$PIVILION_USER:$PIVILION_GROUP" "$PIVILION_DIR/config"
install -d -m 0755 -o "$PIVILION_USER" -g "$PIVILION_GROUP" \
"$PIVILION_DIR/static" "$PIVILION_DIR/hotglue" "$PIVILION_DIR/hotglue/backup"
[ -s "$PIVILION_DIR/mode" ] || pivilion_set_mode "$PIVILION_MODE"
[ -e "$PIVILION_DIR/torname" ] || install -m 0644 -o "$PIVILION_USER" -g "$PIVILION_GROUP" /dev/null "$PIVILION_DIR/torname"
install -d -m 2775 -o www-data -g www-data "$PIVILION_WEBROOT" "$PIVILION_WEBROOT/gen"
cp -a "$SOURCE_DIR/var/www/html/pivilion/scripts" "$PIVILION_WEBROOT/"
cp -a "$SOURCE_DIR/var/www/html/pivilion/images" "$PIVILION_WEBROOT/"
cp -a "$SOURCE_DIR/var/www/html/pivilion/skeleton" "$PIVILION_WEBROOT/"
install -m 0664 -o www-data -g www-data "$SOURCE_DIR/var/www/html/pivilion/gen.php" "$PIVILION_WEBROOT/gen.php"
install -m 0644 -o www-data -g www-data "$SOURCE_DIR/var/www/html/pivilion/index.html" "$PIVILION_WEBROOT/index.html"
install -m 0644 -o www-data -g www-data "$SOURCE_DIR/var/www/html/pivilion/pi-logo_128.png" "$PIVILION_WEBROOT/pi-logo_128.png"
if [ ! -e "$PIVILION_WEBROOT/gen/index.php" ]; then
cp -a "$SOURCE_DIR/var/www/html/pivilion/gen/." "$PIVILION_WEBROOT/gen/"
fi
chown -R www-data:www-data "$PIVILION_WEBROOT/scripts" "$PIVILION_WEBROOT/images" "$PIVILION_WEBROOT/skeleton"
chown -R www-data:www-data "$PIVILION_WEBROOT/gen"
find "$PIVILION_WEBROOT" -type d -exec chmod 2775 {} +
find "$PIVILION_WEBROOT" -type f -exec chmod 0664 {} +
cat > /etc/pivilion.php <<EOF
<?php
define('PIVILION_DIR', ${PIVILION_DIR@Q});
define('PIVILION_WEBROOT', ${PIVILION_WEBROOT@Q});
EOF
chmod 0644 /etc/pivilion.php
php_version=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
install -d -m 0755 "/etc/php/$php_version/apache2/conf.d"
install -m 0644 "$SOURCE_DIR/etc/php/pivilion.ini" "/etc/php/$php_version/apache2/conf.d/99-pivilion.ini"
}
configure_services() {
sed "s|/var/www/html/pivilion|$PIVILION_WEBROOT|g" "$SOURCE_DIR/etc/apache2/sites-available/000-default.conf" > /etc/apache2/sites-available/000-default.conf
sed "s|/var/www/html/pivilion|$PIVILION_WEBROOT|g" "$SOURCE_DIR/etc/apache2/sites-available/000-upload.conf" > /etc/apache2/sites-available/000-upload.conf
install -m 0644 "$SOURCE_DIR/etc/apache2/ports.conf" /etc/apache2/ports.conf
cat > /etc/apache2/conf-available/pivilion.conf <<EOF
<Directory "$PIVILION_WEBROOT">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
EOF
a2enmod rewrite
a2enconf pivilion
a2ensite 000-default.conf
if ! grep -Fqx '%include /etc/tor/torrc.d/*.conf' /etc/tor/torrc; then
printf '\n%%include /etc/tor/torrc.d/*.conf\n' >> /etc/tor/torrc
fi
systemctl daemon-reload
systemctl enable apache2 pivilion-mode.service
systemctl enable tor@default.service 2>/dev/null || systemctl enable tor.service
systemctl disable --now dnsmasq 2>/dev/null || true
systemctl disable pivilion-dnsmasq.service 2>/dev/null || true
}
validate_install() {
apache2ctl configtest
tor --verify-config -f /etc/tor/torrc
dnsmasq --test
bash -n /usr/local/lib/pivilion/common.sh /usr/local/lib/pivilion/mode.sh /usr/local/bin/pivilion \
/usr/local/bin/hotspot /usr/local/bin/onion /usr/local/bin/pikey /usr/local/bin/generator \
/usr/local/bin/static /usr/local/bin/hotglue /usr/local/bin/htaccess
}
install_packages
deploy_files
configure_services
validate_install
echo "Pivilion installed for $PIVILION_USER. Reboot to enter $(pivilion_current_mode) mode."

9
pivilion.conf.example Normal file
View file

@ -0,0 +1,9 @@
# Copy this file to /boot/firmware/pivilion.conf or /etc/pivilion.conf.
# Values are parsed as data; this is not a shell script.
PIVILION_USER=pi
PIVILION_HOME=/home/pi
PIVILION_DIR=/home/pi/pivilion
PIVILION_WEBROOT=/var/www/html/pivilion
PIVILION_MODE=onion
PIVILION_HOTSPOT_SSID=pivilion
# PIVILION_WIFI_INTERFACE=wlan0

View file

@ -1,25 +1,31 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
source /usr/local/lib/pivilion/common.sh
[ "$(id -u)" -eq 0 ] || exec sudo "$0" "$@"
pivilion_load_config
echo "Would you like to enable or disable the Static Generator Script?" backup_gallery() {
select stagen in "Enable" "Disable"; do local destination="$PIVILION_DIR/backups/gen-$(date +%Y%m%d-%H%M%S)"
case $stagen in install -d -m 0755 -o "$PIVILION_USER" -g "$PIVILION_GROUP" "$PIVILION_DIR/backups"
Enable ) sudo a2ensite 000-upload.conf > /dev/null; cp -a "$PIVILION_WEBROOT/gen" "$destination"
sudo systemctl reload apache2; chown -R "$PIVILION_USER:$PIVILION_GROUP" "$destination"
echo "Static Generator Script enabled, access it by adding :81 to your Rpi IP in your browser"; echo "Gallery backup: $destination"
sudo rm -rf /var/www/html/piviliomn/gen/* }
sudo chown -R pi:pi /home/pi
sudo chown -R www-data:www-data /var/www/; select choice in "Enable" "Disable"; do
sudo chmod -R 775 /var/www; case "$choice" in
sudo mkdir /var/www/html/pivilion/gen/upload Enable)
sudo chmod -R 777 /var/www/html/pivilion/gen/upload backup_gallery
break;; a2ensite 000-upload.conf >/dev/null
Disable ) sudo a2dissite 000-upload.conf > /dev/null; systemctl reload apache2
sudo systemctl reload apache2; install -d -m 2775 -o www-data -g www-data "$PIVILION_WEBROOT/gen/upload"
echo "Static Generator Script disabled"; echo "Generator enabled at http://<device-address>:81/"
sudo chown -R pi:pi /home/pi break ;;
sudo chown -R www-data:www-data /var/www/; Disable)
sudo chmod -R 775 /var/www; a2dissite 000-upload.conf >/dev/null || true
break;; systemctl reload apache2
esac echo "Generator disabled."
done break ;;
exit 0 *) echo "Choose 1 or 2." ;;
esac
done

View file

@ -1,31 +1,56 @@
#!/bin/bash #!/bin/bash
echo "Would you like to install or restore Hotglue? Installing will overwrite any existing files in /var/www/html/pivilion/gen" set -euo pipefail
select sres in "Install" "Restore"; do source /usr/local/lib/pivilion/common.sh
case $sres in [ "$(id -u)" -eq 0 ] || exec sudo "$0" "$@"
Install ) wget https://hotglue.org/download/hotglue-latest-dev.zip -P /home/pi/pivilion/hotglue/; pivilion_load_config
unzip /home/pi/pivilion/hotglue/hotglue-latest-dev.zip -d /home/pi/pivilion/hotglue/;
sudo mv /home/pi/pivilion/hotglue/k0a1a-*/* /home/pi/pivilion/hotglue/;
echo "Enter Hotglue admin user";
read user;
echo "Enter Hotglue admin password";
read password;
echo -e "<?php\n@define('AUTH_USER', '$user');\n@define('AUTH_PASSWORD', '$password');" > /home/pi/pivilion/hotglue/user-config.inc.php
sudo rm -rf /var/www/html/pivilion/gen/{,.[!.],..?}*;
sudo cp -rT /home/pi/pivilion/hotglue /var/www/html/pivilion/gen;
sudo chmod 777 /var/www/html/pivilion/gen/content;
sudo chown -R pi:pi /home/pi;
sudo chown -R www-data:www-data /var/www/;
sudo chmod -R 775 /var/www;
break;;
Restore ) sudo rm -rf /var/www/html/pivilion/gen/{,.[!.],..?}*;
sudo cp -aR /home/pi/pivilion/hotglue/backup /var/www/html/pivilion/gen;
sudo mv /var/www/html/pivilion/gen/backup/* /var/www/html/pivilion/gen
sudo chmod -R 777 /var/www/html/pivilion/gen/content;
sudo chown -R pi:pi /home/pi;
sudo chown -R www-data:www-data /var/www/;
sudo chmod -R 775 /var/www;
break;;
esac
done
exit 0
backup_gallery() {
local destination="$PIVILION_DIR/hotglue/backup-$(date +%Y%m%d-%H%M%S)"
cp -a "$PIVILION_WEBROOT/gen" "$destination"
chown -R "$PIVILION_USER:$PIVILION_GROUP" "$destination"
printf '%s\n' "$destination"
}
replace_gallery() {
local source=$1
[ -d "$source" ] || { echo "Restore source does not exist: $source" >&2; return 1; }
find "$PIVILION_WEBROOT/gen" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
cp -a "$source/." "$PIVILION_WEBROOT/gen/"
chown -R www-data:www-data "$PIVILION_WEBROOT/gen"
find "$PIVILION_WEBROOT/gen" -type d -exec chmod 2775 {} +
find "$PIVILION_WEBROOT/gen" -type f -exec chmod 0664 {} +
[ ! -d "$PIVILION_WEBROOT/gen/content" ] || chmod 2775 "$PIVILION_WEBROOT/gen/content"
}
install -d -m 0755 -o "$PIVILION_USER" -g "$PIVILION_GROUP" "$PIVILION_DIR/hotglue"
select choice in "Install" "Restore latest backup"; do
case "$choice" in
Install)
work=$(mktemp -d "$PIVILION_DIR/hotglue/download.XXXXXX")
trap 'rm -rf "$work"' EXIT
wget --https-only https://hotglue.org/download/hotglue-latest-dev.zip -O "$work/hotglue.zip"
unzip -q "$work/hotglue.zip" -d "$work/unpacked"
source_dir=$(find "$work/unpacked" -mindepth 1 -maxdepth 1 -type d -name 'k0a1a-*' -print -quit)
[ -n "$source_dir" ] || { echo "Unexpected Hotglue archive layout." >&2; exit 1; }
read -r -p "Hotglue admin user: " admin_user
read -r -s -p "Hotglue admin password: " admin_password
printf '\n'
escaped_user=$(printf '%s' "$admin_user" | sed "s/\\\\/\\\\\\\\/g; s/'/\\\\'/g")
escaped_password=$(printf '%s' "$admin_password" | sed "s/\\\\/\\\\\\\\/g; s/'/\\\\'/g")
printf "<?php\n@define('AUTH_USER', '%s');\n@define('AUTH_PASSWORD', '%s');\n" \
"$escaped_user" "$escaped_password" > "$source_dir/user-config.inc.php"
unset admin_password escaped_password
backup=$(backup_gallery)
replace_gallery "$source_dir"
echo "Hotglue installed. Original backup: $backup"
break ;;
"Restore latest backup")
backup=$(find "$PIVILION_DIR/hotglue" -maxdepth 1 -type d -name 'backup-*' -printf '%T@ %p\n' | sort -nr | sed -n '1s/^[^ ]* //p')
[ -n "$backup" ] || { echo "No Hotglue backup is available." >&2; exit 1; }
current=$(backup_gallery)
replace_gallery "$backup"
echo "Restored $backup. Previous gallery saved at $current"
break ;;
*) echo "Choose 1 or 2." ;;
esac
done

View file

@ -1,29 +1,7 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
echo "Checking for required packages and installing what's missing" source /usr/local/lib/pivilion/common.sh
if [ $(dpkg-query -W -f='${Status}' apache2 2>/dev/null | grep -c "ok installed") -eq 0 ]; [ "$(id -u)" -eq 0 ] || exec sudo "$0" "$@"
then pivilion_load_config
sudo apt update pivilion_set_mode hotspot
sudo apt -y install hostapd dnsmasq apache2 php echo "Pivilion will start in open hotspot mode after the next reboot."
sudo cp -rT /home/pi/pivilion/config/html /var/www/html/pivilion/gen
fi
echo "Configuring components..."
if ! test -f /etc/hostapd/hostapd.conf;
then sudo cp -f /home/pi/pivilion/config/hostapd.hotspot /etc/hostapd/hostapd.conf
fi
sudo cp -f /home/pi/pivilion/config/dnsmasq.hotspot /etc/dnsmasq.conf
sudo cp /home/pi/pivilion/config/html/.htaccess /var/www/html/pivilion/gen/.htaccess
sudo chown -R www-data:www-data /var/www/html
sudo chown root:www-data /var/www/html/pivilion/gen/.htaccess
sudo cp -f /home/pi/pivilion/config/rc.hotspot /etc/rc.local
sudo cp -f /home/pi/pivilion/config/override.hotspot /etc/apache2/conf-available/override.conf
sudo a2enconf override
sudo a2enmod rewrite
echo "Backing up wireless network configuration..."
sudo mv /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.bak
echo "Captive portal enabled. Reboot to execute."
sudo bash -c 'echo "hotspot" > /home/pi/pivilion/mode'
exit 0

View file

@ -1,9 +1,17 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
source /usr/local/lib/pivilion/common.sh
[ "$(id -u)" -eq 0 ] || exec sudo "$0" "$@"
pivilion_load_config
echo "Would you like to remove or reset htaccess redirection" select choice in "Reset" "Remove"; do
select hson in "Reset" "Remove"; do case "$choice" in
case $hson in Reset)
Reset) sudo cp /home/pi/pivilion/config/html/.htaccess /var/www/html/pivilion/gen; break;; install -m 0644 -o root -g www-data "$PIVILION_DIR/config/html/.htaccess" "$PIVILION_WEBROOT/gen/.htaccess"
Remove) sudo rm /var/www/html/pivilion/gen/.htaccess; break;; break ;;
esac Remove)
rm -f "$PIVILION_WEBROOT/gen/.htaccess"
break ;;
*) echo "Choose 1 or 2." ;;
esac
done done

View file

@ -1,16 +1,13 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
cat /home/pi/pivilion/config/dhcpcd.orig > /etc/dhcpcd.conf source /usr/local/lib/pivilion/common.sh
[ "$(id -u)" -eq 0 ] || exec sudo "$0" "$@"
sudo bash -c 'cat /home/pi/pivilion/config/interfaces.onion > /etc/network/interfaces' pivilion_load_config
pivilion_set_mode onion
sudo update-rc.d dnsmasq disable rm -f "$PIVILION_WEBROOT/gen/.htaccess"
echo "Pivilion will start in onion mode after the next reboot."
sudo bash -c 'cat /home/pi/pivilion/config/rc.local.onion > /etc/rc.local' if [ -s "$PIVILION_DIR/torname" ]; then
sudo mv /etc/wpa_supplicant/wpa_supplicant.bak /etc/wpa_supplicant/wpa_supplicant.conf printf 'Your onion domain is %s\n' "$(tr -d '\r\n' < "$PIVILION_DIR/torname")"
sudo rm /var/www/html/pivilion/gen/.htaccess else
sudo echo "The next time you reboot, your Pi will start in onion mode"! echo "The onion domain will appear after Tor starts successfully."
sudo echo "Your onion domain is `cat /home/pi/pivilion/torname`" fi
sudo bash -c 'echo "onion" > /home/pi/pivilion/mode'

View file

@ -1,12 +1,35 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
source /usr/local/lib/pivilion/common.sh
[ "$(id -u)" -eq 0 ] || exec sudo "$0" "$@"
pivilion_load_config
IFACE=$(pivilion_wifi_interface)
[ -n "$IFACE" ] || { echo "No Wi-Fi interface found." >&2; exit 1; }
echo "Enter SSID" read -r -p "Wi-Fi SSID: " ssid
read name read -r -s -p "Wi-Fi password: " password
echo "Enter password" printf '\n'
read password [ -n "$ssid" ] || { echo "SSID cannot be empty." >&2; exit 1; }
sudo bash -c "cp /etc/wpa_supplicant/wpa_supplicant.conf /home/pi/pivilion/config/wpa_supplicant.conf" [ "${#password}" -ge 8 ] && [ "${#password}" -le 63 ] || {
sudo bash -c "wpa_passphrase "$name" "$password" >> /home/pi/pivilion/config/wpa_supplicant.conf" echo "WPA password must contain 8-63 characters." >&2; exit 1;
sudo bash -c "cp /home/pi/pivilion/config/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf" }
echo "Configured Wifi networks"
sudo bash -c "cat /etc/wpa_supplicant/wpa_supplicant.conf" if pivilion_uses_networkmanager; then
echo "If this is correct set your Pi to restart in onion mode by running the onion command!" nmcli connection delete pivilion-onion >/dev/null 2>&1 || true
nmcli connection add type wifi ifname "$IFACE" con-name pivilion-onion ssid "$ssid" >/dev/null
nmcli connection modify pivilion-onion 802-11-wireless.mode infrastructure \
802-11-wireless-security.key-mgmt wpa-psk 802-11-wireless-security.psk "$password" \
ipv4.method auto ipv6.method auto connection.autoconnect yes
else
tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT
wpa_passphrase "$ssid" "$password" | sed '/^[[:space:]]*#psk=/d' > "$tmp"
install -d -m 0755 /etc/wpa_supplicant
install -m 0600 "$tmp" /etc/wpa_supplicant/pivilion.conf
touch /etc/wpa_supplicant/wpa_supplicant.conf
grep -Fqx 'include=/etc/wpa_supplicant/pivilion.conf' /etc/wpa_supplicant/wpa_supplicant.conf || \
printf '\ninclude=/etc/wpa_supplicant/pivilion.conf\n' >> /etc/wpa_supplicant/wpa_supplicant.conf
chmod 0600 /etc/wpa_supplicant/wpa_supplicant.conf
fi
unset password
echo "Wi-Fi credentials saved. Run onion and reboot when ready."

View file

@ -1,44 +1,31 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
source /usr/local/lib/pivilion/common.sh
pivilion_load_config
pause(){ mode=$(pivilion_current_mode)
read -n1 -rsp $'\nPress any key to continue or Ctrl+C to exit...\n\n' torname="not generated yet"
} [ ! -s "$PIVILION_DIR/torname" ] || torname=$(tr -d '\r\n' < "$PIVILION_DIR/torname")
sudo bash -c 'cat /var/lib/tor/hidden_service/hostname > /home/pi/pivilion/torname' uptime_text=$(uptime -p 2>/dev/null || true)
sudo bash -c 'echo "onion" > /home/pi/pivilion/mode'
sudo chown -R pi:www-data /var/www/html/pivilion/gen
echo -e "\nWelcome to pivilion!" cat <<EOF
let upSeconds="$(/usr/bin/cut -d. -f1 /proc/uptime)" Welcome to Pivilion!
let secs=$((${upSeconds}%60))
let mins=$((${upSeconds}/60%60))
let hours=$((${upSeconds}/3600%24))
let days=$((${upSeconds}/86400))
UPTIME=`printf "%d days, %02dh%02dm%02ds" "$days" "$hours" "$mins" "$secs"`
# get the load averages Host...............: $(uname -n)
read one five fifteen rest < /proc/loadavg System.............: $(uname -srmo)
echo " Uptime.............: ${uptime_text:-unknown}
@@@@@@@@@@@@@@@@@@@ `date +"%A, %e %B %Y, %r"` Mode after reboot..: $mode
@@@@@@, &@& *@@@@@@ `uname -srnmo` Onion address......: $torname
@@@@@@@. .@@@@@@@ Uptime.............: ${UPTIME} Web root...........: $PIVILION_WEBROOT
@@@@ .@@@. @@@@ Memory.............: `cat /proc/meminfo | grep MemFree | awk {'print $2'}`kB (Free) / `cat /proc/meminfo | grep MemTotal | awk {'print $2'}`kB (Total)
@ &@@@@.@@@@# @ Load Averages......: ${one}, ${five}, ${fifteen} (1, 5, 15 min)
@ @ . #@@@# . @ @ Running Processes..: `ps ax | wc -l | tr -d " "`
@ @@@, # ,@@@ @ Manual / more info.: pivilion.net
@@, @ ,@@ Onion Address......: `cat /home/pi/pivilion/torname`
@@@@@#@@@@@@@#@@@@@ Running in `cat /home/pi/pivilion/mode` mode"
pause
echo -e "There are four commands for you to use: \n \n 1) \"pivilion\" will display this message. \n \n 2) \"onion\" will set your Pi to start in onion mode on next reboot. This is the default mode. \n \n 3) \"hotspot\" will set your Pi to start in hotspot mode on next reboot. \n Please remember to set the mode properly before each reboot or you might have to access your Pi via ethernet cable or screen. \n \n 4) \"pikey\" is used to setup a Wifi network and password to be used in onion mode. \n \n A more thorough explanation is available at pivilion.net.\n"
echo -e "The following is a usage scenario." Commands:
pause pivilion show this status
echo -e "You are in a queue in a bank and they let you have their Wifi password. It's taking ages...\n\nYou already setup your gallery by either using our PHP gallery generation script or by uploading your own website to /var/www/html on your Pivilion box and set your Pi to run in hotspot mode." onion select Tor onion mode for the next reboot
pause hotspot select open captive-hotspot mode for the next reboot
echo -e "All you have to do now is \n - connect your phone to your Pivilion box, powered by a battery pack in your backpack, \n - ssh to it using a terminal emulator for your phone, \n - run pikey to input the network SSID and password, \n - run onion to set Pivilion to run as a tor hidden service on the next boot and \n - reboot " pikey save upstream Wi-Fi credentials for onion mode
pause generator enable or disable the gallery generator on port 81
echo -e "And there you have it! \nYou just hosted an online darknet exhibition powered by your local bank! =P" static convert the current gallery to static files
pause hotglue install or restore Hotglue
echo -e "For detailed info and support visit http://pivilion.net or https://gitlab.com/hacklab01/pivilion/" htaccess reset or remove captive redirect rules
EOF
exit 0

View file

@ -1,18 +1,35 @@
#!/bin/bash #!/bin/bash
sudo rm -rf /home/pi/pivilion/static/{,.[!.],..?}* set -euo pipefail
sudo cp -a -R /var/www/html/pivilion/gen /home/pi/pivilion/hotglue/backup source /usr/local/lib/pivilion/common.sh
wget --mirror --convert-links --adjust-extension --page-requisites --restrict-file-names=ascii,windows http://127.0.0.1 -P /home/pi/pivilion/static [ "$(id -u)" -eq 0 ] || exec sudo "$0" "$@"
sudo rm -rf /var/www/html/pivilion/gen/{,.[!.],..?}* pivilion_load_config
sudo cp -rT /home/pi/pivilion/static/127.0.0.1 /var/www/html/pivilion/gen
sudo mv /var/www/html/pivilion/gen/index.html //var/www/html/pivilion/gen/index.php work=$(mktemp -d "$PIVILION_DIR/static.XXXXXX")
sudo chown -R pi:pi /home/pi backup="$PIVILION_DIR/backups/gen-$(date +%Y%m%d-%H%M%S)"
sudo chown -R www-data:www-data /var/www/; trap 'rm -rf "$work"' EXIT
sudo chmod -R 775 /var/www; install -d -m 0755 -o "$PIVILION_USER" -g "$PIVILION_GROUP" "$PIVILION_DIR/backups"
echo "Are you using static HTML with hotspot or onion mode?" cp -a "$PIVILION_WEBROOT/gen" "$backup"
select hson in "Hotspot" "Onion"; do
case $hson in wget --mirror --convert-links --adjust-extension --page-requisites \
Hotspot ) sudo cp /home/pi/pivilion/config/html/.htaccess /var/www/html/pivilion/gen; break;; --restrict-file-names=ascii,windows http://127.0.0.1/ -P "$work"
Onion ) sudo rm /var/www/html/pivilion/gen/.htaccess; break;; [ -f "$work/127.0.0.1/index.html" ] || { echo "Static capture did not produce index.html; gallery was not changed." >&2; exit 1; }
esac
done find "$PIVILION_WEBROOT/gen" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
exit 0 cp -a "$work/127.0.0.1/." "$PIVILION_WEBROOT/gen/"
mv "$PIVILION_WEBROOT/gen/index.html" "$PIVILION_WEBROOT/gen/index.php"
chown -R www-data:www-data "$PIVILION_WEBROOT/gen"
find "$PIVILION_WEBROOT/gen" -type d -exec chmod 2775 {} +
find "$PIVILION_WEBROOT/gen" -type f -exec chmod 0664 {} +
echo "Static gallery installed. Original backup: $backup"
select choice in "Hotspot" "Onion"; do
case "$choice" in
Hotspot)
install -m 0644 -o root -g www-data "$PIVILION_DIR/config/html/.htaccess" "$PIVILION_WEBROOT/gen/.htaccess"
break ;;
Onion)
rm -f "$PIVILION_WEBROOT/gen/.htaccess"
break ;;
*) echo "Choose 1 or 2." ;;
esac
done

View file

@ -0,0 +1,113 @@
#!/bin/bash
# Shared configuration and small helpers for the Pivilion commands.
PIVILION_CONFIG=""
_pivilion_trim() {
local value=$1
value="${value#"${value%%[![:space:]]*}"}"
value="${value%"${value##*[![:space:]]}"}"
printf '%s' "$value"
}
_pivilion_config_value() {
local key=$1 file line name value
for file in /boot/firmware/pivilion.conf /boot/pivilion.conf /etc/pivilion.conf /etc/pivilion.defaults; do
[ -r "$file" ] || continue
while IFS= read -r line || [ -n "$line" ]; do
line=$(_pivilion_trim "$line")
case "$line" in ''|'#'*) continue ;; esac
name=$(_pivilion_trim "${line%%=*}")
[ "$name" = "$key" ] || continue
value=$(_pivilion_trim "${line#*=}")
case "$value" in
\"*\") value=${value#\"}; value=${value%\"} ;;
\'*\') value=${value#\'}; value=${value%\'} ;;
esac
printf '%s' "$value"
return 0
done < "$file"
done
return 1
}
pivilion_load_config() {
local default_user configured ssid_bytes
default_user=${SUDO_USER:-${USER:-}}
[ -n "$default_user" ] && [ "$default_user" != root ] || default_user=$(id -nu 1000 2>/dev/null || true)
configured=$(_pivilion_config_value PIVILION_USER || true)
PIVILION_USER=${configured:-$default_user}
[ -n "$PIVILION_USER" ] || { echo "Cannot determine PIVILION_USER" >&2; return 1; }
getent passwd "$PIVILION_USER" >/dev/null || { echo "Configured user '$PIVILION_USER' does not exist" >&2; return 1; }
PIVILION_GROUP=$(id -gn "$PIVILION_USER")
configured=$(_pivilion_config_value PIVILION_HOME || true)
PIVILION_HOME=${configured:-$(getent passwd "$PIVILION_USER" | cut -d: -f6)}
configured=$(_pivilion_config_value PIVILION_DIR || true)
PIVILION_DIR=${configured:-$PIVILION_HOME/pivilion}
configured=$(_pivilion_config_value PIVILION_WEBROOT || true)
PIVILION_WEBROOT=${configured:-/var/www/html/pivilion}
configured=$(_pivilion_config_value PIVILION_MODE || true)
PIVILION_MODE=${configured:-onion}
configured=$(_pivilion_config_value PIVILION_HOTSPOT_SSID || true)
PIVILION_HOTSPOT_SSID=${configured:-pivilion}
configured=$(_pivilion_config_value PIVILION_WIFI_INTERFACE || true)
PIVILION_WIFI_INTERFACE=${configured:-}
case "$PIVILION_MODE" in onion|hotspot) ;; *) echo "PIVILION_MODE must be onion or hotspot" >&2; return 1 ;; esac
ssid_bytes=$(LC_ALL=C printf '%s' "$PIVILION_HOTSPOT_SSID" | wc -c)
[ "$ssid_bytes" -ge 1 ] && [ "$ssid_bytes" -le 32 ] || {
echo "PIVILION_HOTSPOT_SSID must contain 1-32 bytes" >&2; return 1;
}
case "$PIVILION_HOME$PIVILION_DIR$PIVILION_WEBROOT$PIVILION_WIFI_INTERFACE$PIVILION_HOTSPOT_SSID" in
*$'\n'*|*$'\r'*) echo "Invalid control character in Pivilion configuration" >&2; return 1 ;;
esac
case "$PIVILION_HOME:$PIVILION_DIR:$PIVILION_WEBROOT" in
/*:/*:/*) ;; *) echo "Pivilion paths must be absolute" >&2; return 1 ;;
esac
[[ "$PIVILION_HOME" =~ ^/[A-Za-z0-9._/+:-]+$ && "$PIVILION_DIR" =~ ^/[A-Za-z0-9._/+:-]+$ && "$PIVILION_WEBROOT" =~ ^/[A-Za-z0-9._/+:-]+$ ]] || {
echo "Pivilion paths contain unsupported characters" >&2; return 1;
}
[ -z "$PIVILION_WIFI_INTERFACE" ] || [[ "$PIVILION_WIFI_INTERFACE" =~ ^[A-Za-z0-9._:-]+$ ]] || {
echo "Invalid PIVILION_WIFI_INTERFACE" >&2; return 1;
}
export PIVILION_USER PIVILION_GROUP PIVILION_HOME PIVILION_DIR PIVILION_WEBROOT PIVILION_MODE PIVILION_HOTSPOT_SSID PIVILION_WIFI_INTERFACE
}
pivilion_wifi_interface() {
local iface
if [ -n "${PIVILION_WIFI_INTERFACE:-}" ]; then printf '%s\n' "$PIVILION_WIFI_INTERFACE"; return; fi
if command -v nmcli >/dev/null 2>&1; then
iface=$(nmcli -t -f DEVICE,TYPE device status 2>/dev/null | awk -F: '$2=="wifi" {print $1; exit}')
[ -n "$iface" ] && { printf '%s\n' "$iface"; return; }
fi
if command -v iw >/dev/null 2>&1; then
iface=$(iw dev 2>/dev/null | awk '$1=="Interface" {print $2; exit}')
[ -n "$iface" ] && { printf '%s\n' "$iface"; return; }
fi
iface=$(find /sys/class/net -maxdepth 1 -type l -name 'wl*' -printf '%f\n' 2>/dev/null | head -n1)
[ -n "$iface" ] && printf '%s\n' "$iface"
}
pivilion_uses_networkmanager() {
command -v nmcli >/dev/null 2>&1 && systemctl is-active --quiet NetworkManager
}
pivilion_set_mode() {
local mode=$1
case "$mode" in onion|hotspot) ;; *) return 2 ;; esac
install -d -m 0755 -o "$PIVILION_USER" -g "$PIVILION_GROUP" "$PIVILION_DIR"
printf '%s\n' "$mode" | install -m 0644 -o "$PIVILION_USER" -g "$PIVILION_GROUP" /dev/stdin "$PIVILION_DIR/mode"
}
pivilion_current_mode() {
local mode
mode=$(head -n1 "$PIVILION_DIR/mode" 2>/dev/null || true)
case "$mode" in onion|hotspot) printf '%s\n' "$mode" ;; *) printf '%s\n' "$PIVILION_MODE" ;; esac
}
pivilion_require_root() {
[ "$(id -u)" -eq 0 ] || { echo "This operation must run as root (use sudo)." >&2; return 1; }
}

138
usr/local/lib/pivilion/mode.sh Executable file
View file

@ -0,0 +1,138 @@
#!/bin/bash
set -euo pipefail
source /usr/local/lib/pivilion/common.sh
pivilion_require_root
pivilion_load_config
MODE=${1:-$(pivilion_current_mode)}
IFACE=$(pivilion_wifi_interface)
[ -n "$IFACE" ] || { echo "No Wi-Fi interface found; set PIVILION_WIFI_INTERFACE" >&2; exit 1; }
RUN_DIR=/run/pivilion
DNSMASQ_CONF=/etc/dnsmasq.d/pivilion-runtime.conf
NM_HOTSPOT=pivilion-hotspot
stop_hotspot() {
systemctl stop pivilion-dnsmasq.service 2>/dev/null || true
rm -f "$DNSMASQ_CONF"
nft delete table inet pivilion 2>/dev/null || true
if pivilion_uses_networkmanager; then
nmcli connection down "$NM_HOTSPOT" 2>/dev/null || true
nmcli connection delete "$NM_HOTSPOT" 2>/dev/null || true
else
systemctl stop hostapd 2>/dev/null || true
ip address flush dev "$IFACE" 2>/dev/null || true
fi
}
write_dnsmasq_config() {
install -d -m 0755 /etc/dnsmasq.d
cat > "$DNSMASQ_CONF" <<EOF
interface=$IFACE
bind-dynamic
listen-address=10.1.1.1
dhcp-range=10.1.1.2,10.1.1.254,255.255.255.0,72h
dhcp-option=option:router,10.1.1.1
dhcp-authoritative
address=/#/10.1.1.1
EOF
}
start_firewall() {
install -d -m 0755 "$RUN_DIR"
cat > "$RUN_DIR/pivilion.nft" <<EOF
table inet pivilion {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
iifname "$IFACE" udp dport 53 redirect to :53
iifname "$IFACE" tcp dport 53 redirect to :53
iifname "$IFACE" tcp dport 80 redirect to :80
}
}
EOF
nft delete table inet pivilion 2>/dev/null || true
nft -f "$RUN_DIR/pivilion.nft"
}
start_hotspot() {
stop_hotspot
rfkill unblock wifi 2>/dev/null || true
systemctl start apache2
if pivilion_uses_networkmanager; then
nmcli connection add type wifi ifname "$IFACE" con-name "$NM_HOTSPOT" ssid "$PIVILION_HOTSPOT_SSID"
nmcli connection modify "$NM_HOTSPOT" 802-11-wireless.mode ap 802-11-wireless.band bg \
ipv4.method manual ipv4.addresses 10.1.1.1/24 ipv4.never-default yes ipv6.method disabled
nmcli connection up "$NM_HOTSPOT"
else
systemctl stop "wpa_supplicant@$IFACE.service" 2>/dev/null || true
command -v dhcpcd >/dev/null 2>&1 && dhcpcd -k "$IFACE" 2>/dev/null || true
ip link set "$IFACE" down
ip address flush dev "$IFACE"
ip address add 10.1.1.1/24 dev "$IFACE"
ip link set "$IFACE" up
install -d -m 0755 /etc/hostapd
cat > /etc/hostapd/hostapd.conf <<EOF
interface=$IFACE
driver=nl80211
ssid=$PIVILION_HOTSPOT_SSID
hw_mode=g
channel=6
auth_algs=1
wmm_enabled=0
EOF
systemctl unmask hostapd 2>/dev/null || true
systemctl restart hostapd
fi
write_dnsmasq_config
dnsmasq --test --conf-file="$DNSMASQ_CONF"
systemctl restart pivilion-dnsmasq.service
start_firewall
echo "Pivilion hotspot '$PIVILION_HOTSPOT_SSID' is active on $IFACE (10.1.1.1)."
}
update_torname() {
local source=/var/lib/tor/pivilion/hostname hostname tmp i
for i in $(seq 1 30); do
if [ -s "$source" ]; then
hostname=$(tr -d '\r\n' < "$source")
if [[ ! "$hostname" =~ ^[a-z2-7]{56}\.onion$ ]]; then
echo "Tor produced an invalid v3 onion hostname." >&2
return 1
fi
tmp=$(mktemp "$PIVILION_DIR/.torname.XXXXXX")
printf '%s\n' "$hostname" > "$tmp"
chown "$PIVILION_USER:$PIVILION_GROUP" "$tmp"
chmod 0644 "$tmp"
mv -f "$tmp" "$PIVILION_DIR/torname"
return 0
fi
sleep 1
done
echo "Tor started, but no onion hostname was generated within 30 seconds." >&2
return 1
}
start_onion() {
stop_hotspot
if pivilion_uses_networkmanager; then
nmcli connection up pivilion-onion 2>/dev/null || echo "No saved Pivilion Wi-Fi connection; run pikey." >&2
else
systemctl restart dhcpcd 2>/dev/null || true
systemctl restart "wpa_supplicant@$IFACE.service" 2>/dev/null || systemctl restart wpa_supplicant 2>/dev/null || true
fi
rm -f "$PIVILION_WEBROOT/gen/.htaccess"
systemctl start apache2
if systemctl cat tor@default.service >/dev/null 2>&1; then
systemctl restart tor@default.service
else
systemctl restart tor.service
fi
update_torname || true
echo "Pivilion onion mode is active."
}
case "$MODE" in
hotspot) start_hotspot ;;
onion) start_onion ;;
*) echo "Unknown Pivilion mode: $MODE" >&2; exit 2 ;;
esac

View file

@ -1,16 +1,25 @@
<?php <?php
require_once '/etc/pivilion.php';
ob_start(); // start trapping output ob_start(); // start trapping output
$banana = @$_POST['banana']; $banana = $_POST['banana'] ?? '';
$title = @$_POST['title']; $title = $_POST['title'] ?? '';
$description = @$_POST['description']; $description = $_POST['description'] ?? '';
$images_array = $_FILES['mytest']; $images_array = $_FILES['mytest'] ?? null;
$slides_array = @$_POST['imgs']; $slides_array = $_POST['imgs'] ?? array();
$slides_autors = @$_POST['author']; $slides_autors = $_POST['author'] ?? array();
$slides_desc = @$_POST['work_desc']; $slides_desc = $_POST['work_desc'] ?? array();
$color = @$_POST['color']; $color = $_POST['color'] ?? '';
$slides_array = is_array($slides_array) ? $slides_array : array();
$slides_autors = is_array($slides_autors) ? $slides_autors : array();
$slides_desc = is_array($slides_desc) ? $slides_desc : array();
function rearrange($arr) function rearrange($arr)
{ {
$new = array();
if (!is_array($arr))
{
return $new;
}
foreach ($arr as $key => $all) foreach ($arr as $key => $all)
{ {
foreach ($all as $i => $val) foreach ($all as $i => $val)
@ -35,7 +44,7 @@ if (isset($_FILES['mytest']))
$target_file = $target_dir . str_replace(",", "", str_replace(".", "", number_format(microtime(true) , 4))) . '.' . pathinfo($file['name'], PATHINFO_EXTENSION); $target_file = $target_dir . str_replace(",", "", str_replace(".", "", number_format(microtime(true) , 4))) . '.' . pathinfo($file['name'], PATHINFO_EXTENSION);
$uploadOk = 1; $uploadOk = 1;
$imageFileType = pathinfo($target_file, PATHINFO_EXTENSION); $imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image // Check if image file is a actual image or fake image
//echo $imageFileType; //echo $imageFileType;
// $check = getimagesize($file['tmp_name']); // $check = getimagesize($file['tmp_name']);
@ -189,6 +198,7 @@ $myfiles = preg_replace("/gen\//", "", $myfiles);
//var_dump($myfiles); //var_dump($myfiles);
$cnt = 1; $cnt = 1;
$sld = 1;
foreach ($slides_array as $imageVal) foreach ($slides_array as $imageVal)
{ {
// echo $cnt; // echo $cnt;
@ -206,7 +216,9 @@ foreach ($slides_array as $imageVal)
else else
{ {
$ext = ""; $ext = "";
$ext = explode(".", current($myfiles)); $current_file = current($myfiles);
$current_file = is_string($current_file) ? $current_file : '';
$ext = explode(".", $current_file);
$format = $ext[sizeof($ext) - 1]; $format = $ext[sizeof($ext) - 1];
switch ($format) switch ($format)
{ {
@ -247,15 +259,22 @@ foreach ($slides_array as $imageVal)
</body> </body>
</html> </html>
<?php <?php
$source = "skeleton/"; $source = PIVILION_WEBROOT . "/skeleton/";
$dest = "/var/www/html/pivilion/gen"; $dest = PIVILION_WEBROOT . "/gen";
mkdir($dest, 0755); if (!is_dir($dest) && !mkdir($dest, 0775, true) && !is_dir($dest))
{
throw new RuntimeException("Unable to create gallery directory");
}
foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS) , \RecursiveIteratorIterator::SELF_FIRST) as $item) foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS) , \RecursiveIteratorIterator::SELF_FIRST) as $item)
{ {
if ($item->isDir()) if ($item->isDir())
{ {
mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName()); $directory = $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName();
if (!is_dir($directory))
{
mkdir($directory, 0775, true);
}
} }
else else
{ {
@ -264,12 +283,17 @@ foreach ($iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryItera
} }
?> ?>
<?php <?php
$torname = file_get_contents('/home/pi/pivilion/torname'); $torname_file = PIVILION_DIR . '/torname';
$torname = is_readable($torname_file) ? file_get_contents($torname_file) : '';
$tornamemode = preg_replace('/\s+/', '', $torname); $tornamemode = preg_replace('/\s+/', '', $torname);
$output = ob_get_contents(); // get contents of trapped output $output = ob_get_contents(); // get contents of trapped output
//write to file, e.g. //write to file, e.g.
$newfile = "/var/www/html/pivilion/gen/index.php"; $newfile = PIVILION_WEBROOT . "/gen/index.php";
$file = fopen($newfile, "w"); $file = fopen($newfile, "w");
if ($file === false)
{
throw new RuntimeException("Unable to write generated gallery");
}
fwrite($file, $output); fwrite($file, $output);
fclose($file); fclose($file);
ob_end_clean(); // discard trapped output and stop trapping ob_end_clean(); // discard trapped output and stop trapping