flexday/q.php

316 lines
9.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Execute Query</title>
<style>
:root {
--bg: #f6f7fb;
--card: #fff;
--border: #e5e7eb;
--text: #0f172a;
--muted: #64748b;
--accent: #2563eb;
}
html, body {
background: var(--bg);
color: var(--text);
font: 14px/1.5 system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
margin: 0;
}
.page {
max-width: 1100px;
margin: 28px auto; /* page margin */
padding: 0 18px;
}
.card {
background: var(--card);
border: 1px solid var(--border);
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0,0,0,.04);
padding: 16px;
}
h2, h3 { margin: 0 0 12px; }
/* Query area layout */
.query-wrap { display: grid; gap: 12px; }
.toolbar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 12px;
justify-content: space-between; /* left/right split */
}
.toolbar-left { display: flex; align-items: center; gap: 12px; }
.toolbar-right { display: flex; align-items: center; gap: 10px; }
textarea#query {
width: 100%;
min-height: 160px;
resize: vertical;
box-sizing: border-box;
padding: 12px 14px;
border: 1px solid var(--border);
border-radius: 10px;
background: #fff;
font: 13px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.btn {
display: inline-block;
padding: 8px 14px;
border-radius: 10px;
border: 1px solid var(--border);
background: var(--accent);
color: #fff;
cursor: pointer;
}
.btn.secondary {
background: #fff;
color: var(--text);
}
label.small { color: var(--muted); font-size: 13px; user-select: none; }
/* Saved queries */
.query-select {
width: 100%;
box-sizing: border-box;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 10px;
background: #fff;
font-size: 14px;
}
/* Results */
.results { margin-top: 16px; }
.results-header {
display: flex; align-items: center; justify-content: space-between;
margin: 4px 0 12px;
}
.results-meta { color: var(--muted); font-size: 13px; }
table {
width: 100%;
border-collapse: collapse;
border: 1px solid var(--border);
border-radius: 10px;
overflow: hidden;
background: #fff;
font-size: 13px;
}
th, td { padding: 8px 10px; border-bottom: 1px solid var(--border); text-align: left; }
th { background: #f2f4f7; }
code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.csv-box {
width: 100%; height: 360px; resize: vertical;
white-space: pre; overflow: auto;
font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
background: #0b1020; color: #e5e7eb;
border: 1px solid #111827; border-radius: 10px; padding: 12px;
}
</style>
<script>
// JavaScript function to populate the textarea with the clicked query
function populateQuery(query) {
document.getElementById('query').value = query;
}
function copyCsv(id) {
const ta = document.getElementById(id);
ta.focus();
ta.select();
document.execCommand('copy');
}
</script>
</head>
<body>
<?php
// Allowed IP address
$allowed_ip1 = '47.45.92.162';
$ip2 = '207.62.201.30';
$ip3 = '192.168.1.70';
function get_client_ip() {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
// It may contain multiple IPs separated by commas, so we take the first one
$ip_list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ip_list[0]);
} elseif (isset($_SERVER['HTTP_X_REAL_IP'])) {
// Some proxies may use this header
$ip = $_SERVER['HTTP_X_REAL_IP'];
} else {
// Fallback to REMOTE_ADDR
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
// Get client IP address
$client_ip = get_client_ip();
// Check if the incoming IP address matches the allowed IP
if ($client_ip !== $allowed_ip1 && $client_ip !== $ip2 && $client_ip !== $ip3) {
die("Access denied. Unauthorized IP address.");
}
?>
<div class="page">
<div class="card">
<h2>Execute Query</h2>
<form method="post" action="" class="query-wrap">
<textarea id="query" name="query" placeholder="Enter your MySQL query here"><?php
echo isset($_POST['query']) ? htmlspecialchars($_POST['query']) : '';
?></textarea>
<div class="toolbar">
<div class="toolbar-left">
<label class="small">
<input type="checkbox" name="csv_output" value="1" <?php
echo !empty($_POST['csv_output']) ? 'checked' : '';
?>> CSV output
</label>
</div>
<div class="toolbar-right">
<button type="submit" name="submit" class="btn">Execute Query</button>
</div>
</div>
</form>
</div>
<div class="card" style="margin-top:16px;">
<h3>Available Queries</h3>
<?php
$file = 'queries.txt';
if (file_exists($file)) {
$queries = file($file, FILE_IGNORE_NEW_LINES);
echo '<select id="querySelect" class="query-select" onchange="populateQuery(this.value)">';
echo '<option value="">Select a query...</option>';
foreach ($queries as $line) {
list($label, $q) = explode('|', $line, 2);
echo '<option value="' . htmlspecialchars($q) . '">' . htmlspecialchars($label) . '</option>';
}
echo '</select>';
} else {
echo "<p>{$file} file not found.</p>";
}
?>
<div class="results">
<?php
if (isset($_POST['submit'])) {
// Connection parameters (adjust for your MySQL server)
include_once("peter_db.php");
$peter_db = new peter_db();
$conn = $peter_db->getConnection();
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$query = $_POST['query'] ?? '';
$as_csv = !empty($_POST['csv_output']);
// Helper: CSV line builder (RFC 4180 style quoting)
$csv_line = function(array $vals): string {
$out = [];
foreach ($vals as $v) {
if ($v === null) {
$out[] = '';
continue;
}
$s = (string)$v;
// Normalize line breaks
$s = str_replace(["\r\n", "\r"], "\n", $s);
// Escape double quotes by doubling them
if (strpbrk($s, ",\"\n") !== false) {
$s = '"' . str_replace('"', '""', $s) . '"';
}
$out[] = $s;
}
return implode(',', $out);
};
// Split on semicolons (simple splitter; wont handle semicolons inside strings)
$queries = array_filter(array_map('trim', explode(';', $query)));
foreach ($queries as $sql) {
if ($sql === '') { continue; }
echo "<p><code>" . htmlspecialchars($sql) . "</code></p>";
$result = $conn->query($sql);
if ($result === FALSE) {
echo "<p>Error: " . htmlspecialchars($conn->error) . "</p>";
} elseif ($result === TRUE) {
echo "<p>Query executed successfully.</p>";
} else {
// SELECT-like result
if ($as_csv) {
// Build header
$fields = $result->fetch_fields();
$headers = array_map(fn($f) => $f->name, $fields);
$csv = [];
$csv[] = $csv_line($headers);
// Rows
while ($row = $result->fetch_assoc()) {
// Preserve column order per $headers
$vals = [];
foreach ($headers as $h) { $vals[] = $row[$h]; }
$csv[] = $csv_line($vals);
}
$csv_text = implode("\n", $csv) . "\n";
// Show in a textarea for easy copy without HTML escaping issues
// Adjust rows/cols as you like
$rows = min(40, max(10, count($csv) + 2));
echo '<textarea readonly rows="' . $rows . '" cols="120">'
. htmlspecialchars($csv_text)
. '</textarea><br><br>';
} else {
// HTML table
echo "<table border='1'><tr>";
$fields = $result->fetch_fields();
foreach ($fields as $field) {
echo "<th>" . htmlspecialchars($field->name) . "</th>";
}
echo "</tr>";
while ($row = $result->fetch_assoc()) {
echo "<tr>";
foreach ($row as $value) {
echo "<td>" . htmlspecialchars((string)$value) . "</td>";
}
echo "</tr>";
}
echo "</table><br><br>";
}
}
}
$conn->close();
}
?>
</div>
</div>
</div>
<script>
function populateQuery(q) { document.getElementById('query').value = q; }
</script>
</body>
</html>