<?php
// =============================================================================
// GET /vpns.php — Glass VPN picker source.
//
// Plain GET, no signing. Returns every enabled vpn_profile in sort_order.
// Glass picker (com.GlassVpnPicker) only consumes name/ovpn/username/password
// returns 8 fields per entry.
// =============================================================================

require_once __DIR__ . '/includes/client_common.php';

require_method('GET');

$rows = db_all(
    'SELECT name, provider, country, state, url, ovpn, username, password
     FROM vpn_profiles WHERE enabled = 1 ORDER BY sort_order ASC, id ASC'
);

// Normalise types — Glass calls .optString() which expects strings.
// Also drop profiles that would force LaunchVPN into askForPW(): if the
// .ovpn declares `auth-user-pass` but the operator hasn't attached creds via
// the Credentials tab yet, mUsername/mPassword hit the profile empty →
// needUserPWInput() returns non-zero → askForPW inflates R.layout.userpass
// → NPE (crash). Hiding these entries fails-closed; they were unusable in
// the picker anyway. Cert-only profiles (no `auth-user-pass`) still get
// served whether or not username/password are set.
$out = [];
foreach ($rows as $r) {
    $ovpn = (string)$r['ovpn'];
    $u    = (string)$r['username'];
    $p    = (string)$r['password'];
    if (($u === '' || $p === '') && stripos($ovpn, 'auth-user-pass') !== false) {
        continue;
    }
    $out[] = [
        'name'     => (string)$r['name'],
        'provider' => (string)$r['provider'],
        'country'  => (string)$r['country'],
        'state'    => (string)$r['state'],
        'url'      => (string)$r['url'],
        'ovpn'     => $ovpn,
        'username' => $u,
        'password' => $p,
    ];
}

client_log_request(null, 'GET', '/vpns.php', client_request_headers(), null, 200, ['vpns_count' => count($out)]);

json_response(['vpns' => $out]);
