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."; ?>