Login | Register (Invite Only)
Title: Page Telegram of Amfile.org
Description: Brown Hats Collective F' Around and Find Out user of the Interwebs and Project Developer for a Cause Toward Insuring a Future of Liberty without Illusion.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@=:---#@@@#%@@@*=+#@%====@@@@..:--@#====@-==#@@@+===#@%=-+@... -@@@@*@@@=+@%-*@ @@@.*@-.@@@.:@@==@:=@+ -..*@@@:# @:@=.=. #%.#@@@@ ::..@.%#.@@ %+ %@@% #@@-.@+ #@ @@@.*@+.@@@:.@@.#@%*@*.@.-*@@%@#.@.@=.%..#% *@@@@ %:+:+:@@=@@ #+ %@@+..@@= %: @@ @@@..-.=@@:* %@.%#=+@+..:@@@@@@*.@@@=..:@@@ %@%%% :.@@+-@:=#@ ...@@@:+ @@+ :- @@ @@@.+@@@@@.- =@.#@.-@*.@:=@@@@@+ @@@+:@-:@% @@*=@ @=%#+-@-.#@ @*.%@@.- #@=. + @@ @@@.+@@@@+.@..@:*%.*@*.@%.@@@@%- +@@=:@%.@@.%@:=@ @@=*#:@::@@ *# =@--% -@:- * @@ @@-::#@@%::+::*@-:=%@::.::@@@@+-::@*:.:::@::...%:::::#@*:==@#==@+:*.:=::%:-=::=@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#-. .-#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*. .+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@: .++: .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@= :@@@@@@- -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@# =@@@@@@@@+ #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@: =@@@@@@@@@@+ .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@# .@@@@@@@@@@@@. *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@. %@@@@@@@@@@@@%. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@% -@@@@@@@@@@@@@@- #@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@= #@@@@@@@@@@@@@@% -@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@ -@@@@%##***#%@@@@+ %@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@* %@#:.. .:+@% *@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@= =. : -@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@. .=%@@@@@@@+: .@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@# .%@@@@@@@@@@@@@- -@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@# .*@@@@@@@@@@@@@@@@%: -@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@%. .@@@@@@*%@@@@%#@@@@@@= *@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@. :@@@@@@@@:-@@*.%@@@@@@@+ %@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@+ :@@@@@@@@@@---.@@@@@@@@@@= :@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@. @@@@@@@@@@@. @@@@@@@@@@@: #@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@= #@@@+--#@@@@ #@@@@%#@@@@@. .@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@. :@%- .%@@- .@@@*. .+@@= #@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@# *+. .@@@#*@@@= .#@ -@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@- .# =@@-.@@%. += .@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. -@. @@. %@: #% %@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. #@- +% =% .@@. *@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@% %@% :+ .+ +@@. =@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@# @@@: .: .- .@@@: -@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@* .@@@% # .# =@@@: :@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@* .@@@@= -@ @- .@@@@: :@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@# @@@@@. .@@ @@. %@@@@: -@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@% %@@@@@: :@@@ @@@. .*@@@@@. =@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. #@@@@@@#+#@@@@ @@@@=.:%@@@@@@. *@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@. :@@@@@@-..:*@@ @@#-..:%@@@@@# %@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@- .@@@@@: .@ @. .@@@@@- .@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@# *@@@% @. .@ *@@@@ -@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@. .@@@+ @- .@. -@@@= #@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@+ +@@%. .@* :@- .*@@%. .@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@. %@@@- *@% #@%. :%@@@. %@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@* .@@@@%=-+@@@. @@@*--#@@@@- -@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@: .@@@@@@@@@@*=@@@@@@@@@@: @@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@. .%@@@@@@@@@@@@@@@@@@@- .#@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@%. +@@@@@@@@@@@@@@@@#. +@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@%. .+@@@@@@@@@@@@%: +@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@%. -*%@@@@@#=. .*@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@: .%@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@#. +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+. .=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=. .-%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%###%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
<?php
// setup.php
// Create necessary directories
$directories = [
'data',
'data/surveys',
'data/results',
'styles',
'js',
'assets'
];
foreach ($directories as $dir) {
if (!file_exists($dir)) {
mkdir($dir, 0777, true);
}
}
// Array of files to create with their content
$files = [
'styles/brownhatsurvey.css' => "/* Global Styles */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: monospace;
background-color: black;
color: orange;
padding: 20px;
margin: 0;
text-align: center;
font-size: 18px;
line-height: 1.6;
}
.container {
max-width: 900px;
margin: auto;
padding: 20px;
}
input, textarea, select {
background-color: orange;
color: black;
border: 2px solid black;
padding: 12px;
width: 100%;
font-family: monospace;
font-size: 18px;
min-height: 40px;
}
input::placeholder, textarea::placeholder {
color: black;
font-size: 16px;
}
button, a {
display: inline-block;
background-color: orange;
color: black;
padding: 12px 18px;
text-decoration: none;
border: 2px solid black;
font-weight: bold;
cursor: pointer;
text-align: center;
transition: background-color 0.3s ease, color 0.3s ease;
font-size: 18px;
border-radius: 6px;
min-width: 160px;
}
button:hover, a:hover {
background-color: black;
color: orange;
border: 2px solid orange;
}
a {
display: inline-block;
width: fit-content;
margin: 10px auto;
}
label {
display: block;
margin-bottom: 10px;
font-size: 20px;
}
.admin-container {
width: 95%;
margin: auto;
overflow-x: auto;
}
.admin-table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
.admin-table th, .admin-table td {
border: 2px solid orange;
padding: 10px;
text-align: left;
font-size: 18px;
}
.admin-table th {
background-color: black;
color: orange;
}
.action-buttons {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
}
.question-box {
border: 2px solid orange;
padding: 12px;
margin-bottom: 12px;
background-color: black;
color: orange;
display: flex;
flex-direction: column;
font-size: 18px;
}
.question-box p {
text-align: left !important;
margin: 0 0 12px 0;
}
.survey-intro {
text-align: left;
margin: 20px 0;
}
.survey-intro p {
text-align: left !important;
text-indent: 2em;
margin: 0 0 1em 0;
}
@media (max-width: 1024px) {
body {
font-size: 22px;
padding: 15px;
}
.admin-table, .admin-table th, .admin-table td {
font-size: 22px;
padding: 12px;
}
button, a {
font-size: 22px;
padding: 16px 20px;
width: 100%;
}
.action-buttons {
flex-direction: column;
align-items: center;
}
input, textarea, select {
font-size: 22px;
min-height: 50px;
}
.survey-intro, .question-box {
font-size: 22px;
}
}
@media (max-width: 768px) {
body {
font-size: 24px;
padding: 15px;
}
.admin-table, .admin-table th, .admin-table td {
font-size: 24px;
padding: 14px;
}
button, a {
font-size: 24px;
padding: 18px 22px;
}
input, textarea, select {
font-size: 24px;
min-height: 55px;
}
.survey-intro, .question-box {
font-size: 24px;
}
}
@media (max-width: 480px) {
body {
font-size: 26px;
padding: 10px;
}
button, a {
font-size: 26px;
padding: 20px 24px;
width: 100%;
}
.admin-table, .admin-table th, .admin-table td {
font-size: 26px;
padding: 16px;
}
input, textarea, select {
font-size: 26px;
min-height: 60px;
}
.survey-intro, .question-box {
font-size: 26px;
}
}
.styled-divider {
border: 3px solid orange;
margin: 20px 0;
width: 80%;
}
.divider-label {
font-size: 22px;
font-weight: bold;
color: orange;
text-align: center;
margin-bottom: 20px;
}",
'js/admin.js' => "// Admin panel JavaScript can be added here\n",
'assets/favicon.ico' => "// Placeholder for favicon\n",
'assets/logo.png' => "// Placeholder for logo\n",
'index.php' => '<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$code = trim($_POST["survey_code"]);
if (preg_match(\'/^[a-f0-9]{7}$/i\', $code)) {
header("Location: survey.php?code=" . htmlspecialchars($code));
exit();
} else {
$error = "Invalid survey code.";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="SurveyGram - A flexible survey system for creating and taking surveys.">
<meta property="og:title" content="SurveyGram">
<meta property="og:description" content="A flexible, user-friendly survey system.">
<meta property="og:image" content="./assets/logo.png">
<link rel="icon" type="image/x-icon" href="./assets/favicon.ico">
<title>SurveyGram 2.13 by Page Telegram</title>
<link rel="stylesheet" href="styles/brownhatsurvey.css">
</head>
<body>
<h1>Enter Your Survey Code</h1>
<form method="POST">
<input type="text" name="survey_code" maxlength="7" required>
<button type="submit">Start Survey</button>
</form>
<?php if (isset($error)) echo "<p>$error</p>"; ?>
</body>
<br>
<hr>
<p>
<footer><center><tt><i>SurveyGram produced by Page Telegram Volunteer Services, working towards liberty and the pursuit of happiness (CC) 2025.</i></tt></center></footer>
</p>
</html>',
'survey.php' => '<?php
$code = $_GET[\'code\'] ?? \'\';
$user = $_GET[\'user\'] ?? \'\';
if (!preg_match(\'/^[a-f0-9]{7}$/i\', $code)) {
die("Invalid survey code.");
}
if (!preg_match(\'/^[a-f0-9]{4}$/i\', $user)) {
$user = substr(bin2hex(random_bytes(2)), 0, 4);
header("Location: survey.php?code=$code&user=$user");
exit();
}
$surveyFile = "data/surveys/$code.json";
$responseFile = "data/results/$code-$user.json";
if (!file_exists($surveyFile)) {
die("Survey not found.");
}
$survey = json_decode(file_get_contents($surveyFile), true);
$responses = file_exists($responseFile) ? json_decode(file_get_contents($responseFile), true) : [];
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$response_data = [];
foreach ($survey[\'questions\'] as $index => $q) {
if ($q[\'type\'] !== \'divider\' && $q[\'type\'] !== \'link\') {
$response_data["q$index"] = $_POST["q$index"] ?? ($q[\'type\'] === \'scale\' ? \'0\' : \'\');
}
}
$response_data[\'timestamp\'] = date(\'Y-m-d H:i:s\');
file_put_contents($responseFile, json_encode($response_data, JSON_PRETTY_PRINT));
if (!isset($survey[\'responses\'])) {
$survey[\'responses\'] = [];
}
$survey[\'responses\'][$user] = $response_data;
file_put_contents($surveyFile, json_encode($survey, JSON_PRETTY_PRINT));
header("Location: completed.php?code=$code&user=$user");
exit();
}
$dividerCount = 0;
$surveyURL = "survey.php?code=$code&user=$user";
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo htmlspecialchars($survey[\'title\']); ?></title>
<link rel="stylesheet" href="styles/brownhatsurvey.css">
</head>
<body>
<h1><?php echo nl2br(htmlspecialchars($survey[\'title\'])); ?></h1>
<div class="survey-intro">
<?php
$paragraphs = explode("\n", trim($survey[\'intro\']));
foreach ($paragraphs as $para) {
if ($para !== \'\') {
echo \'<p>\' . htmlspecialchars($para) . \'</p>\';
}
}
?>
</div>
<p><strong>Bookmark Your Survey Progress:</strong></p>
<button id="bookmark-button">Bookmark This Survey</button>
<form method="POST">
<input type="hidden" name="user" value="<?php echo htmlspecialchars($user); ?>">
<?php foreach ($survey[\'questions\'] as $index => $q): ?>
<?php if ($q[\'type\'] === \'divider\'): ?>
<?php $dividerCount++; ?>
<hr class="styled-divider">
<p class="divider-label"><?php echo nl2br(htmlspecialchars($q[\'label\'] ?? "Divider #$dividerCount")); ?></p>
<?php elseif ($q[\'type\'] === \'link\'): ?>
<div class="question-box">
<p><strong><?php echo nl2br(htmlspecialchars($q[\'description\'])); ?>:</strong>
<a href="<?php echo htmlspecialchars($q[\'url\']); ?>" target="_blank">
<?php echo htmlspecialchars($q[\'url\']); ?>
</a>
</p>
</div>
<?php else: ?>
<div class="question-box">
<p><?php echo nl2br(htmlspecialchars($q[\'text\'])); ?></p>
<?php if ($q[\'type\'] === \'text\'): ?>
<input type="text" name="q<?php echo $index; ?>" value="<?php echo htmlspecialchars($responses["q$index"] ?? \'\'); ?>" required>
<?php elseif ($q[\'type\'] === \'scale\'): ?>
<select name="q<?php echo $index; ?>">
<option value="0" <?php if (($responses["q$index"] ?? \'0\') == \'0\') echo \'selected\'; ?>>Skip</option>
<?php for ($i = $q[\'scale_min\']; $i <= $q[\'scale_max\']; $i++): ?>
<option value="<?php echo $i; ?>" <?php if (($responses["q$index"] ?? \'0\') == $i) echo \'selected\'; ?>><?php echo $i; ?></option>
<?php endfor; ?>
</select>
<?php elseif ($q[\'type\'] === \'comments\'): ?>
<textarea name="q<?php echo $index; ?>" rows="5"><?php echo htmlspecialchars($responses["q$index"] ?? \'\'); ?></textarea>
<?php endif; ?>
</div>
<?php endif; ?>
<?php endforeach; ?>
<button type="submit">Save and Quit</button>
</form>
<script>
document.getElementById("bookmark-button").addEventListener("click", function(event) {
event.preventDefault();
const url = "<?php echo htmlspecialchars($surveyURL); ?>";
const title = "Resume Survey - SurveyGram";
try {
if (window.sidebar && window.sidebar.addPanel) {
window.sidebar.addPanel(title, url, "");
} else if (window.external && ("AddFavorite" in window.external)) {
window.external.AddFavorite(url, title);
} else if (navigator.userAgent.toLowerCase().indexOf("android") !== -1) {
alert("To bookmark this survey on Android, tap the three-dot menu and select \'Add to Home Screen\' or \'Bookmark\'.");
} else if (navigator.userAgent.toLowerCase().indexOf("iphone") !== -1 || navigator.userAgent.toLowerCase().indexOf("ipad") !== -1) {
alert("To bookmark this survey on iPhone, tap the Share button (square with an arrow) and select \'Add to Home Screen\'.");
} else if (window.opera && window.print) {
var elem = document.createElement("a");
elem.setAttribute("href", url);
elem.setAttribute("title", title);
elem.setAttribute("rel", "sidebar");
elem.click();
} else {
alert("To bookmark this survey, press " + (navigator.userAgent.toLowerCase().indexOf("mac") !== -1 ? "Cmd + D" : "Ctrl + D") + " on your keyboard.");
}
} catch (e) {
alert("Bookmarking is not supported in this browser. Please manually bookmark this page.");
}
});
</script>
</body>
</html>',
'completed.php' => '<?php
$code = $_GET[\'code\'] ?? \'\';
$user = $_GET[\'user\'] ?? \'\';
if (!preg_match(\'/^[a-f0-9]{7}$/i\', $code) || !preg_match(\'/^[a-f0-9]{4}$/i\', $user)) {
die("Invalid request.");
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Survey Completed</title>
<link rel="stylesheet" href="styles/brownhatsurvey.css">
</head>
<body>
<h1>Survey Completed</h1>
<p>Thank you for completing the survey!</p>
<p><strong>Did you bookmark your progress?</strong></p>
<p>
If you did not, please go back and bookmark the survey link if you intend to make changes or add more later.
</p>
<p><strong>Click below to return to your survey session:</strong></p>
<p>
<a href="survey.php?code=<?php echo $code; ?>&user=<?php echo $user; ?>" class="button-link">
Go Back
</a>
</p>
</body>
</html>',
'admin.php' => '<?php
$passcode = $_GET[\'launchcode\'] ?? $_POST[\'launchcode\'] ?? \'\';
if ($passcode !== \'hackme\') {
?>
<!DOCTYPE html>
<html>
<head>
<title>Admin Login</title>
<link rel="stylesheet" href="styles/brownhatsurvey.css">
</head>
<body>
<h1>Admin Login</h1>
<form method="POST">
<label>Enter Admin Passcode:</label>
<input type="password" name="launchcode" required>
<button type="submit">Login</button>
</form>
</body>
</html>
<?php
exit();
}
$surveys = glob("data/surveys/*.json");
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST[\'css_content\'])) {
$css_content = $_POST[\'css_content\'];
file_put_contents("styles/brownhatsurvey.css", $css_content);
header("Location: admin.php?launchcode=hackme");
exit();
}
$css_content = file_get_contents("styles/brownhatsurvey.css");
?>
<!DOCTYPE html>
<html>
<head>
<title>Admin Dashboard</title>
<link rel="stylesheet" href="styles/brownhatsurvey.css">
<script src="js/admin.js" defer></script>
</head>
<body>
<div class="admin-container">
<h1><a href="index.php" style="text-decoration: none; color: inherit;">SurveyGram</a> Admin Dashboard</h1>
<a href="new_survey.php" class="button-link">+ Create New Survey</a>
<table class="admin-table">
<thead>
<tr>
<th>Survey Title</th>
<th>Survey Access Code</th>
<th>Responses</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($surveys as $file):
$surveyCode = basename($file, ".json");
$survey = json_decode(file_get_contents($file), true);
?>
<tr>
<td><?php echo nl2br(htmlspecialchars($survey[\'title\'])); ?></td>
<td><strong><?php echo $surveyCode; ?></strong></td>
<td><?php echo count($survey[\'responses\'] ?? []); ?></td>
<td class="action-buttons">
<a href="survey.php?code=<?php echo $surveyCode; ?>" class="button-link">Preview</a>
<a href="edit_survey.php?code=<?php echo $surveyCode; ?>" class="button-link">Edit</a>
<a href="export.php?code=<?php echo $surveyCode; ?>&format=json" class="button-link">Download JSON</a>
<a href="export.php?code=<?php echo $surveyCode; ?>&format=csv" class="button-link">Download CSV</a>
<a href="delete_survey.php?code=<?php echo $surveyCode; ?>" class="button-link" onclick="return confirm(\'Are you sure you want to delete this survey?\');">Delete</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<h2>Edit CSS</h2>
<form method="POST">
<textarea name="css_content" rows="20" style="width: 100%; font-family: monospace; font-size: 16px;"><?php echo htmlspecialchars($css_content); ?></textarea>
<button type="submit">Save CSS</button>
</form>
</div>
</body>
</html>',
'new_survey.php' => '<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$title = trim($_POST[\'title\']);
$intro = trim($_POST[\'intro\']);
$questions = [];
$sequence_offset = 0;
foreach ($_POST[\'questions\'] as $index => $q) {
$base_sequence = intval($_POST[\'sequence\'][$index]);
if ($q[\'type\'] === \'divider\') {
$questions[] = [
"sequence" => $base_sequence,
"type" => "divider",
"label" => trim($_POST[\'questions\'][$index][\'label\'] ?? "Divider #$index")
];
$sequence_offset++;
} elseif ($q[\'type\'] === \'link\') {
$questions[] = [
"sequence" => $base_sequence,
"type" => "link",
"description" => trim($_POST[\'questions\'][$index][\'description\']),
"url" => trim($_POST[\'questions\'][$index][\'url\'])
];
$sequence_offset++;
} else {
$question = [
"sequence" => $base_sequence,
"text" => trim($q[\'text\']),
"type" => $q[\'type\'],
"has_comments" => isset($_POST[\'questions\'][$index][\'has_comments\']) ? true : false
];
if ($q[\'type\'] === \'scale\') {
$question[\'scale_min\'] = intval($_POST[\'questions\'][$index][\'scale_min\']);
$question[\'scale_max\'] = intval($_POST[\'questions\'][$index][\'scale_max\']);
}
$questions[] = $question;
$sequence_offset++;
if ($question[\'has_comments\']) {
$questions[] = [
"sequence" => $base_sequence + 1,
"text" => "Any comments or questions?",
"type" => "comments"
];
$sequence_offset++;
}
}
}
usort($questions, fn($a, $b) => $a[\'sequence\'] - $b[\'sequence\']);
$surveyCode = substr(bin2hex(random_bytes(4)), 0, 7);
$surveyData = [
"title" => $title,
"intro" => $intro,
"questions" => $questions
];
file_put_contents("data/surveys/$surveyCode.json", json_encode($surveyData, JSON_PRETTY_PRINT));
header("Location: admin.php?launchcode=hackme");
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Create New Survey</title>
<link rel="stylesheet" href="styles/brownhatsurvey.css">
<script>
let dividerCount = 0;
let sequenceNum = 0;
function addQuestion() {
let container = document.getElementById("questions");
let index = container.children.length;
sequenceNum += 10;
let div = document.createElement("div");
div.className = "question-box";
div.innerHTML = `
<label>Order:</label>
<input type="number" name="sequence[${index}]" value="${sequenceNum}" required>
<input type="text" name="questions[${index}][text]" placeholder="Question text" required>
<select name="questions[${index}][type]" onchange="toggleScaleFields(this, ${index})">
<option value="text">Text</option>
<option value="scale">Scale</option>
<option value="comments">Comment Box</option>
<option value="link">Link</option>
</select>
<div class="scale-fields" style="display: none;">
<label>Scale Min:</label>
<input type="number" name="questions[${index}][scale_min]" placeholder="Min value" min="1">
<label>Scale Max:</label>
<input type="number" name="questions[${index}][scale_max]" placeholder="Max value" min="1">
</div>
<div class="comment-checkbox" style="display: none;">
<label><input type="checkbox" name="questions[${index}][has_comments]"> Include comment box after this question</label>
</div>
<button type="button" onclick="this.parentNode.remove()">Delete</button>
`;
container.appendChild(div);
toggleScaleFields(div.querySelector(\'select\'), index);
}
function addDivider() {
let container = document.getElementById("questions");
let index = container.children.length;
dividerCount++;
sequenceNum += 10;
let div = document.createElement("div");
div.className = "question-box";
div.innerHTML = `
<label>Order:</label>
<input type="number" name="sequence[${index}]" value="${sequenceNum}" required>
<input type="hidden" name="questions[${index}][type]" value="divider">
<input type="text" name="questions[${index}][label]" placeholder="Divider Label (Optional)">
<hr class="styled-divider">
<button type="button" onclick="this.parentNode.remove()">Delete</button>
`;
container.appendChild(div);
}
function toggleScaleFields(select, index) {
let scaleFields = select.parentNode.querySelector(\'.scale-fields\');
let commentCheckbox = select.parentNode.querySelector(\'.comment-checkbox\');
if (select.value === \'scale\') {
scaleFields.style.display = \'block\';
commentCheckbox.style.display = \'block\';
} else if (select.value === \'text\' || select.value === \'comments\') {
scaleFields.style.display = \'none\';
commentCheckbox.style.display = \'block\';
} else {
scaleFields.style.display = \'none\';
commentCheckbox.style.display = \'none\';
}
}
</script>
</head>
<body>
<h1>Create New Survey</h1>
<form method="POST">
<label>Survey Title:</label>
<input type="text" name="title" required><br><br>
<label>Survey Introduction:</label>
<textarea name="intro"></textarea><br><br>
<h2>Questions</h2>
<div id="questions"></div>
<button type="button" onclick="addQuestion()">Add Question</button>
<button type="button" onclick="addDivider()">Add Divider</button><br><br>
<button type="submit">Save Survey</button>
</form>
</body>
</html>',
'edit_survey.php' => '<?php
$code = $_GET[\'code\'] ?? \'\';
$surveyFile = "data/surveys/$code.json";
if (!file_exists($surveyFile)) {
die("Survey not found.");
}
$survey = json_decode(file_get_contents($surveyFile), true);
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$survey[\'title\'] = trim($_POST[\'title\']);
$survey[\'intro\'] = trim($_POST[\'intro\']);
$questions = [];
$sequence_offset = 0;
foreach ($_POST[\'questions\'] as $index => $q) {
$base_sequence = intval($_POST[\'sequence\'][$index]);
if ($q[\'type\'] === \'divider\') {
$questions[] = [
"sequence" => $base_sequence,
"type" => "divider",
"label" => trim($_POST[\'questions\'][$index][\'label\'] ?? "Divider #$index")
];
$sequence_offset++;
} elseif ($q[\'type\'] === \'link\') {
$questions[] = [
"sequence" => $base_sequence,
"type" => "link",
"description" => trim($_POST[\'questions\'][$index][\'description\']),
"url" => trim($_POST[\'questions\'][$index][\'url\'])
];
$sequence_offset++;
} else {
$question = [
"sequence" => $base_sequence,
"text" => trim($q[\'text\']),
"type" => $q[\'type\'],
"has_comments" => isset($_POST[\'questions\'][$index][\'has_comments\']) ? true : false
];
if ($q[\'type\'] === \'scale\') {
$question[\'scale_min\'] = intval($_POST[\'questions\'][$index][\'scale_min\']);
$question[\'scale_max\'] = intval($_POST[\'questions\'][$index][\'scale_max\']);
}
$questions[] = $question;
$sequence_offset++;
if ($question[\'has_comments\']) {
$questions[] = [
"sequence" => $base_sequence + 1,
"text" => "Any comments or questions?",
"type" => "comments"
];
$sequence_offset++;
}
}
}
usort($questions, fn($a, $b) => $a[\'sequence\'] - $b[\'sequence\']);
$survey[\'questions\'] = $questions;
file_put_contents($surveyFile, json_encode($survey, JSON_PRETTY_PRINT));
header("Location: edit_survey.php?code=$code");
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Edit Survey</title>
<link rel="stylesheet" href="styles/brownhatsurvey.css">
<script>
function addQuestion() {
let container = document.getElementById("questions");
let index = container.children.length;
let lastSequence = container.children.length > 0 ?
parseInt(container.lastChild.querySelector("input[name^=\'sequence\']").value) : 0;
let sequenceNum = lastSequence + 10;
let div = document.createElement("div");
div.className = "question-box";
div.innerHTML = `
<label>Order:</label>
<input type="number" name="sequence[${index}]" value="${sequenceNum}" required>
<input type="text" name="questions[${index}][text]" placeholder="Question text" required>
<select name="questions[${index}][type]" onchange="toggleScaleFields(this, ${index})">
<option value="text">Text</option>
<option value="scale">Scale</option>
<option value="comments">Comment Box</option>
<option value="link">Link</option>
</select>
<div class="scale-fields" style="display: none;">
<label>Scale Min:</label>
<input type="number" name="questions[${index}][scale_min]" placeholder="Min value" min="1">
<label>Scale Max:</label>
<input type="number" name="questions[${index}][scale_max]" placeholder="Max value" min="1">
</div>
<div class="comment-checkbox" style="display: none;">
<label><input type="checkbox" name="questions[${index}][has_comments]"> Include comment box after this question</label>
</div>
<button type="button" onclick="this.parentNode.remove()">Delete</button>
`;
container.appendChild(div);
toggleScaleFields(div.querySelector(\'select\'), index);
}
function addDivider() {
let container = document.getElementById("questions");
let index = container.children.length;
let lastSequence = container.children.length > 0 ?
parseInt(container.lastChild.querySelector("input[name^=\'sequence\']").value) : 0;
let sequenceNum = lastSequence + 10;
let div = document.createElement("div");
div.className = "question-box";
div.innerHTML = `
<label>Order:</label>
<input type="number" name="sequence[${index}]" value="${sequenceNum}" required>
<input type="hidden" name="questions[${index}][type]" value="divider">
<input type="text" name="questions[${index}][label]" placeholder="Divider Label (Optional)">
<hr class="styled-divider">
<button type="button" onclick="this.parentNode.remove()">Delete</button>
`;
container.appendChild(div);
}
function addLink() {
let container = document.getElementById("questions");
let index = container.children.length;
let lastSequence = container.children.length > 0 ?
parseInt(container.lastChild.querySelector("input[name^=\'sequence\']").value) : 0;
let sequenceNum = lastSequence + 10;
let div = document.createElement("div");
div.className = "question-box";
div.innerHTML = `
<label>Order:</label>
<input type="number" name="sequence[${index}]" value="${sequenceNum}" required>
<input type="hidden" name="questions[${index}][type]" value="link">
<input type="text" name="questions[${index}][description]" placeholder="Link Description" required>
<input type="url" name="questions[${index}][url]" placeholder="URL" required>
<button type="button" onclick="this.parentNode.remove()">Delete</button>
`;
container.appendChild(div);
}
function toggleScaleFields(select, index) {
let scaleFields = select.parentNode.querySelector(\'.scale-fields\');
let commentCheckbox = select.parentNode.querySelector(\'.comment-checkbox\');
if (select.value === \'scale\') {
scaleFields.style.display = \'block\';
commentCheckbox.style.display = \'block\';
} else if (select.value === \'text\' || select.value === \'comments\') {
scaleFields.style.display = \'none\';
commentCheckbox.style.display = \'block\';
} else {
scaleFields.style.display = \'none\';
commentCheckbox.style.display = \'none\';
}
}
</script>
</head>
<body>
<h1>Edit Survey: <?php echo nl2br(htmlspecialchars($survey[\'title\'])); ?></h1>
<form method="POST">
<label>Survey Title:</label>
<input type="text" name="title" value="<?php echo htmlspecialchars($survey[\'title\']); ?>" required><br><br>
<label>Survey Introduction:</label>
<textarea name="intro"><?php echo htmlspecialchars($survey[\'intro\']); ?></textarea><br><br>
<h2>Questions</h2>
<div id="questions">
<?php $dividerCount = 0; ?>
<?php foreach ($survey[\'questions\'] as $index => $q): ?>
<?php if ($q[\'type\'] !== \'comments\' || !isset($survey[\'questions\'][$index - 1]) || !$survey[\'questions\'][$index - 1][\'has_comments\']): ?>
<div class="question-box">
<label>Order:</label>
<input type="number" name="sequence[<?php echo $index; ?>]" value="<?php echo htmlspecialchars($q[\'sequence\']); ?>" required>
<?php if ($q[\'type\'] === \'divider\'): ?>
<?php $dividerCount++; ?>
<input type="hidden" name="questions[<?php echo $index; ?>][type]" value="divider">
<input type="text" name="questions[<?php echo $index; ?>][label]" value="<?php echo htmlspecialchars($q[\'label\'] ?? "Divider #$index"); ?>">
<hr class="styled-divider">
<?php elseif ($q[\'type\'] === \'link\'): ?>
<input type="hidden" name="questions[<?php echo $index; ?>][type]" value="link">
<input type="text" name="questions[<?php echo $index; ?>][description]" value="<?php echo htmlspecialchars($q[\'description\']); ?>" required>
<input type="url" name="questions[<?php echo $index; ?>][url]" value="<?php echo htmlspecialchars($q[\'url\']); ?>" required>
<?php else: ?>
<input type="text" name="questions[<?php echo $index; ?>][text]" value="<?php echo htmlspecialchars($q[\'text\']); ?>" required>
<select name="questions[<?php echo $index; ?>][type]" onchange="toggleScaleFields(this, <?php echo $index; ?>)">
<option value="text" <?php if ($q[\'type\'] === \'text\') echo \'selected\'; ?>>Text</option>
<option value="scale" <?php if ($q[\'type\'] === \'scale\') echo \'selected\'; ?>>Scale</option>
<option value="comments" <?php if ($q[\'type\'] === \'comments\') echo \'selected\'; ?>>Comment Box</option>
</select>
<div class="scale-fields" style="display: <?php echo $q[\'type\'] === \'scale\' ? \'block\' : \'none\'; ?>;">
<label>Scale Min:</label>
<input type="number" name="questions[<?php echo $index; ?>][scale_min]" value="<?php echo htmlspecialchars($q[\'scale_min\'] ?? \'\'); ?>" placeholder="Min value" min="1">
<label>Scale Max:</label>
<input type="number" name="questions[<?php echo $index; ?>][scale_max]" value="<?php echo htmlspecialchars($q[\'scale_max\'] ?? \'\'); ?>" placeholder="Max value" min="1">
</div>
<div class="comment-checkbox" style="display: <?php echo in_array($q[\'type\'], [\'text\', \'scale\', \'comments\']) ? \'block\' : \'none\'; ?>;">
<label><input type="checkbox" name="questions[<?php echo $index; ?>][has_comments]" <?php echo isset($q[\'has_comments\']) && $q[\'has_comments\'] ? \'checked\' : \'\'; ?>> Include comment box after this question</label>
</div>
<?php endif; ?>
<button type="button" onclick="this.parentNode.remove()">Delete</button>
</div>
<?php endif; ?>
<?php endforeach; ?>
</div>
<button type="button" onclick="addQuestion()">Add Question</button>
<button type="button" onclick="addDivider()">Add Divider</button>
<button type="button" onclick="addLink()">Add Link</button><br><br>
<button type="submit">Save Changes</button>
</form>
</body>
</html>',
'export.php' => '<?php
$code = $_GET[\'code\'] ?? \'\';
$format = $_GET[\'format\'] ?? \'json\';
$surveyFile = "data/surveys/$code.json";
if (!file_exists($surveyFile)) {
die("Survey not found.");
}
$survey = json_decode(file_get_contents($surveyFile), true);
$filename = "survey_results_$code";
if ($format === \'json\') {
header(\'Content-Type: application/json\');
header("Content-Disposition: attachment; filename=$filename.json");
echo json_encode($survey[\'responses\'], JSON_PRETTY_PRINT);
} elseif ($format === \'csv\') {
header(\'Content-Type: text/csv\');
header("Content-Disposition: attachment; filename=$filename.csv");
$output = fopen("php://output", "w");
$headers = array_merge(["User ID"], array_column($survey[\'questions\'], \'text\'));
fputcsv($output, $headers);
foreach ($survey[\'responses\'] as $user => $response) {
$row = array_merge([$user], array_values($response));
fputcsv($output, $row);
}
fclose($output);
} else {
die("Invalid export format.");
}
?>',
'delete_survey.php' => '<?php
$code = $_GET[\'code\'] ?? \'\';
$surveyFile = "data/surveys/$code.json";
if (!preg_match(\'/^[a-f0-9]{7}$/i\', $code) || !file_exists($surveyFile)) {
die("Survey not found.");
}
unlink($surveyFile);
header("Location: admin.php");
exit();
?>',
'changelog.html' => '<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SurveyGram Changelog</title>
<link rel="stylesheet" href="styles/brownhatsurvey.css">
</head>
<body>
<div class="container">
<h1>SurveyGram Changelog</h1>
<p>This changelog documents the updates and improvements made to SurveyGram, a flexible survey system by Page Telegram Volunteer Services.</p>
<h2>Version 2.13 - August 2025</h2>
<ul>
<li>Fixed issue in <code>survey.php</code> where text and scale form elements were not rendering, ensuring all question types (text, scale, comments, link, divider) display correctly.</li>
<li>Renamed submission timestamp field from <code>submitted_at</code> to <code>timestamp</code> in results JSON (<code>data/results/$code-$user.json</code> and <code>data/surveys/$code.json</code>).</li>
<li>Restored full functionality in <code>survey.php</code> and <code>admin.php</code> to address file size reduction, ensuring bookmarking script, survey management, and CSS editor are intact.</li>
</ul>
<h2>Version 2.12 - August 2025</h2>
<ul>
<li>Added timestamp recording for survey completions, storing the submission date and time in <code>submitted_at</code> field (format: <code>Y-m-d H:i:s</code>) in the results JSON file (<code>data/results/$code-$user.json</code>).</li>
<li>Added CSS editor in the admin dashboard (<code>admin.php</code>), allowing administrators to edit and save <code>styles/brownhatsurvey.css</code> directly from the interface.</li>
</ul>
<h2>Version 2.11 - August 2025</h2>
<ul>
<li>Fixed text alignment issue ensuring survey question text, comment text, link descriptions, and introduction paragraphs are consistently left-justified using <code>text-align: left !important</code> in CSS to override global centering.</li>
<li>Maintained centered alignment for survey title, divider labels, buttons, and other non-question elements for design consistency.</li>
</ul>
<h2>Version 2.10 - August 2025</h2>
<ul>
<li>Updated CSS to left-justify question text, comment text, and link descriptions in surveys, aligning with the business-style formatting of the introduction.</li>
<li>Preserved centered alignment for survey title, divider labels, and buttons.</li>
</ul>
<h2>Version 2.9 - August 2025</h2>
<ul>
<li>Changed survey introduction styling to left-justified, business-style format with paragraph indentations (2em) instead of centered text.</li>
<li>Updated <code>survey.php</code> to render introduction as multiple <code><p></code> tags, splitting by newlines, with CSS handling indentation.</li>
</ul>
<h2>Version 2.8 - August 2025</h2>
<ul>
<li>Added optional comment blocks after text, scale, and comments questions, controlled by a checkbox in survey creation/editing interfaces.</li>
<li>Introduced <code>has_comments</code> JSON field to store comment block preference, automatically inserting a "Any comments or questions?" comment question after selected questions.</li>
<li>Updated sequence handling to assign comment blocks a sequence number one greater than the parent question (e.g., 11 for a question at 10).</li>
</ul>
<h2>Version 2.7 - August 2025</h2>
<ul>
<li>Updated <code>admin.php</code> to accept password via an input form if not provided in the URL, improving security and accessibility.</li>
<li>Modified admin dashboard title "SurveyGram" to link to <code>index.php</code> for easier navigation.</li>
</ul>
<h2>Version 2.6 - August 2025</h2>
<ul>
<li>Replaced fixed 1-7 scale with user-specified variable scale for survey questions, allowing creators to set custom <code>scale_min</code> and <code>scale_max</code>.</li>
<li>Added "Skip" (value 0) as the default option for scale questions, automatically selected if no choice is made by the user.</li>
</ul>
<h2>Version 2.5 - August 2025</h2>
<ul>
<li>Created <code>setup.php</code> to generate all SurveyGram files and directories, streamlining deployment.</li>
<li>Updated sequence numbering to increment by 10 (e.g., 10, 20, 30) for easier reordering of survey questions.</li>
<li>Applied <code>nl2br()</code> to render carriage returns as <code><br></code> tags in survey titles, introductions, question text, and divider labels.</li>
</ul>
<h2>Version 1.13 - Initial Release</h2>
<ul>
<li>Initial release of SurveyGram with core functionality for creating, taking, and managing surveys.</li>
<li>Features included survey code validation, user ID generation, JSON-based storage, export to JSON/CSV, and admin dashboard with basic CRUD operations.</li>
<li>Styled with a monochrome orange-on-black theme using <code>brownhatsurvey.css</code>.</li>
</ul>
<p><a href="index.php" class="button-link">Return to SurveyGram</a></p>
</div>
</body>
</html>'
];
// Create all files
foreach ($files as $filename => $content) {
file_put_contents($filename, $content);
}
echo "Setup complete! SurveyGram structure has been created.";
?>