Compare commits
11 Commits
350b391aee
...
cffa3f1d7b
| Author | SHA1 | Date | |
|---|---|---|---|
| cffa3f1d7b | |||
|
|
16a856a944 | ||
|
|
ffcb263131 | ||
|
|
e008000aa6 | ||
|
|
711e694673 | ||
|
|
e8bfdd3306 | ||
|
|
23c66952db | ||
|
|
a8f30018e8 | ||
|
|
b2ffd1b2dc | ||
|
|
fdf6a6e809 | ||
|
|
15dcc3e09d |
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
.idea
|
||||||
|
.idea/*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
*.swp
|
*.swp
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
// Returns a JSON list of images currently present in /img
|
// Returns a JSON list of images currently present in /img
|
||||||
|
require_once __DIR__ . '/../auth/auth.php';
|
||||||
|
dreamgirl_require_login_json();
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
$imgDir = realpath(__DIR__ . '/../img');
|
$imgDir = realpath(__DIR__ . '/../img');
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
// Upload handler: saves an uploaded image into /img and returns JSON.
|
// Upload handler: saves an uploaded image into /img and returns JSON.
|
||||||
|
require_once __DIR__ . '/../auth/auth.php';
|
||||||
|
dreamgirl_require_login_json();
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
// Limit: 10MB
|
// Limit: 10MB
|
||||||
|
|||||||
159
auth/auth.php
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session-based auth gate (no DB).
|
||||||
|
* Required credentials:
|
||||||
|
* - username: admin
|
||||||
|
* - password: admin5004!
|
||||||
|
*
|
||||||
|
* NOTE: Password is stored as SHA-256 hash here (not plaintext).
|
||||||
|
*/
|
||||||
|
|
||||||
|
function dreamgirl_session_start(): void {
|
||||||
|
if (session_status() === PHP_SESSION_ACTIVE) return;
|
||||||
|
|
||||||
|
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off');
|
||||||
|
|
||||||
|
// PHP 7.3+ supports samesite via array; older versions may ignore unknown keys.
|
||||||
|
session_set_cookie_params([
|
||||||
|
'lifetime' => 0,
|
||||||
|
'path' => '/',
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Lax',
|
||||||
|
'secure' => $secure,
|
||||||
|
]);
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dreamgirl_is_logged_in(): bool {
|
||||||
|
dreamgirl_session_start();
|
||||||
|
// Try NCue SSO once per session (if available)
|
||||||
|
if (!isset($_SESSION['dreamgirl_sso_checked'])) {
|
||||||
|
$_SESSION['dreamgirl_sso_checked'] = true;
|
||||||
|
dreamgirl_try_ncue_sso_login();
|
||||||
|
}
|
||||||
|
return isset($_SESSION['dreamgirl_user']) && $_SESSION['dreamgirl_user'] === 'admin';
|
||||||
|
}
|
||||||
|
|
||||||
|
function dreamgirl_check_credentials(string $username, string $password): bool {
|
||||||
|
if ($username !== 'admin') return false;
|
||||||
|
|
||||||
|
// sha256("admin5004!")
|
||||||
|
$expectedSha256 = 'adcda104b73b73f8cddf5c8047a6bc0e5e1388265ed4bf0f31f704c13cbc11b7';
|
||||||
|
$gotSha256 = hash('sha256', $password);
|
||||||
|
|
||||||
|
return hash_equals($expectedSha256, $gotSha256);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dreamgirl_base_path(): string {
|
||||||
|
// If deployed under /dreamgirl, SCRIPT_NAME is like /dreamgirl/index.php
|
||||||
|
// If at web root, SCRIPT_NAME is like /index.php
|
||||||
|
$script = isset($_SERVER['SCRIPT_NAME']) ? (string)$_SERVER['SCRIPT_NAME'] : '';
|
||||||
|
$dir = rtrim(str_replace('\\', '/', dirname($script)), '/');
|
||||||
|
return ($dir === '' || $dir === '.') ? '' : $dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dreamgirl_url(string $path): string {
|
||||||
|
$base = dreamgirl_base_path();
|
||||||
|
$p = ltrim($path, '/');
|
||||||
|
return $base . '/' . $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dreamgirl_try_ncue_sso_login(): bool {
|
||||||
|
// If already logged in, nothing to do.
|
||||||
|
if (isset($_SESSION['dreamgirl_user']) && $_SESSION['dreamgirl_user'] === 'admin') return true;
|
||||||
|
|
||||||
|
// Only accept SSO for the known NCue account (Google login).
|
||||||
|
$allowedEmails = ['dosangyoon2@gmail.com'];
|
||||||
|
|
||||||
|
// Endpoint commonly provided by NextAuth/Auth.js style setups.
|
||||||
|
$endpointPath = '/api/auth/session';
|
||||||
|
|
||||||
|
$host = isset($_SERVER['HTTP_HOST']) ? (string)$_SERVER['HTTP_HOST'] : '';
|
||||||
|
if ($host === '') return false;
|
||||||
|
|
||||||
|
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
||||||
|
$url = $scheme . '://' . $host . $endpointPath;
|
||||||
|
|
||||||
|
$cookieHeader = isset($_SERVER['HTTP_COOKIE']) ? (string)$_SERVER['HTTP_COOKIE'] : '';
|
||||||
|
if ($cookieHeader === '') return false;
|
||||||
|
|
||||||
|
$json = null;
|
||||||
|
|
||||||
|
// Prefer cURL if available
|
||||||
|
if (function_exists('curl_init')) {
|
||||||
|
$ch = curl_init();
|
||||||
|
if ($ch === false) return false;
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 1);
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
'Accept: application/json',
|
||||||
|
'Cookie: ' . $cookieHeader,
|
||||||
|
]);
|
||||||
|
// Do not follow redirects to avoid loops
|
||||||
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
|
||||||
|
|
||||||
|
$resp = curl_exec($ch);
|
||||||
|
$code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
if ($resp !== false && $code >= 200 && $code < 300) {
|
||||||
|
$json = $resp;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback using stream context
|
||||||
|
$ctx = stream_context_create([
|
||||||
|
'http' => [
|
||||||
|
'method' => 'GET',
|
||||||
|
'header' => "Accept: application/json\r\nCookie: {$cookieHeader}\r\n",
|
||||||
|
'timeout' => 2,
|
||||||
|
'ignore_errors' => true,
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
$resp = @file_get_contents($url, false, $ctx);
|
||||||
|
if ($resp !== false) $json = $resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($json === null) return false;
|
||||||
|
|
||||||
|
$data = json_decode($json, true);
|
||||||
|
if (!is_array($data)) return false;
|
||||||
|
|
||||||
|
// NextAuth shape: { user: { email: ... }, expires: ... }
|
||||||
|
$email = '';
|
||||||
|
if (isset($data['user']) && is_array($data['user']) && isset($data['user']['email'])) {
|
||||||
|
$email = (string)$data['user']['email'];
|
||||||
|
} elseif (isset($data['email'])) {
|
||||||
|
// Alternate shape
|
||||||
|
$email = (string)$data['email'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($email === '' || !in_array($email, $allowedEmails, true)) return false;
|
||||||
|
|
||||||
|
// SSO accepted: mark session as logged-in for DreamGirl.
|
||||||
|
$_SESSION['dreamgirl_user'] = 'admin';
|
||||||
|
$_SESSION['dreamgirl_sso_email'] = $email;
|
||||||
|
$_SESSION['dreamgirl_sso_at'] = time();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dreamgirl_require_login_page(): void {
|
||||||
|
if (dreamgirl_is_logged_in()) return;
|
||||||
|
header('Location: ' . dreamgirl_url('login.php'));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dreamgirl_require_login_json(): void {
|
||||||
|
if (dreamgirl_is_logged_in()) return;
|
||||||
|
http_response_code(401);
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
echo json_encode(['ok' => false, 'error' => 'Unauthorized'], JSON_UNESCAPED_UNICODE);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -186,6 +186,56 @@ div.navigation {
|
|||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fullscreen lightbox */
|
||||||
|
.lightbox {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 99999;
|
||||||
|
}
|
||||||
|
.lightbox-backdrop {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0, 0, 0, 0.85);
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
.lightbox-content {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.lightbox-content img {
|
||||||
|
/* Fill the dark area as much as possible while keeping aspect ratio */
|
||||||
|
width: 98vw;
|
||||||
|
height: 98vh;
|
||||||
|
object-fit: contain;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
.lightbox-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 14px;
|
||||||
|
right: 14px;
|
||||||
|
z-index: 2; /* ensure clickable above .lightbox-content */
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 999px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||||
|
background: rgba(0, 0, 0, 0.35);
|
||||||
|
color: #fff;
|
||||||
|
font-size: 28px;
|
||||||
|
line-height: 42px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.lightbox-close:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- Layout: slideshow (left) + thumbs (right), full width ---- */
|
/* ---- Layout: slideshow (left) + thumbs (right), full width ---- */
|
||||||
.gallery-wrap {
|
.gallery-wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
BIN
favicon.ico
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
img/upload_20251227_161807_21ae894c.png
Normal file
|
After Width: | Height: | Size: 3.5 MiB |
BIN
img/upload_20260208_094657_4163a395.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
img/upload_20260208_095526_2a24ad50.png
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
img/upload_20260208_095642_504d53eb.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
img/upload_20260208_100149_eada50b5.png
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
BIN
img/upload_20260208_100259_89d6959a.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
img/upload_20260208_100419_fa0d84e0.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
img/upload_20260208_100529_f0d79e2e.png
Normal file
|
After Width: | Height: | Size: 1017 KiB |
BIN
img/upload_20260208_100630_8c6a8e62.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
img/upload_20260208_100723_1e43a6ce.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
BIN
img/upload_20260208_100823_d606cd2c.png
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
img/upload_20260208_204054_dc382fd5.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
img/upload_20260214_113121_26be4ce8.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
img/upload_20260214_113244_04d444f6.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
img/upload_20260214_123220_619246a1.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
img/upload_20260214_123919_9ffa059d.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
img/upload_20260214_124131_63a70e9c.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
img/upload_20260214_211101_065895a5.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
img/upload_20260214_215432_62af454f.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
img/upload_20260214_224206_a37be705.png
Normal file
|
After Width: | Height: | Size: 3.0 MiB |
BIN
img/upload_20260215_041401_1d1e2699.png
Normal file
|
After Width: | Height: | Size: 3.3 MiB |
BIN
img/upload_20260215_041457_3ce21e30.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
img/upload_20260216_100513_c08fe579.png
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
img/upload_20260216_100643_603e1485.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
img/upload_20260216_100738_970784e8.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
img/upload_20260216_100906_5f08cab5.png
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
img/upload_20260216_100948_4b21d9d4.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
img/upload_20260216_101032_689f041f.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
img/upload_20260216_101155_9a92692c.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
img/upload_20260216_101457_48de6274.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
img/upload_20260216_101603_2eb3a2bb.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
img/upload_20260216_102128_10a968c5.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
img/upload_20260216_102338_69f7a31c.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
img/upload_20260219_093131_15a59b33.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
img/upload_20260219_093404_6e1ceebf.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
81
index.html
@@ -2,83 +2,14 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta http-equiv="refresh" content="0; url=index.php" />
|
||||||
<link rel="stylesheet" href="css/basic.css" type="text/css" />
|
<title>Redirecting...</title>
|
||||||
<link rel="stylesheet" href="css/galleriffic-2.css" type="text/css" />
|
|
||||||
|
|
||||||
<!--<script src="http://martn.ncue.net/common/js/jquery.min.js?20150610101404"></script>-->
|
|
||||||
<script type="text/javascript" src="js/jquery.min.js"></script>
|
|
||||||
<script type="text/javascript" src="js/jquery.galleriffic.js"></script>
|
|
||||||
<script type="text/javascript" src="js/jquery.opacityrollover.js"></script>
|
|
||||||
<script type="text/javascript" src="js/bestpic.js"></script>
|
|
||||||
<script type="text/javascript" src="js/image_manifest.js"></script>
|
|
||||||
<script type="text/javascript" src="js/uploader.js"></script>
|
|
||||||
|
|
||||||
<!-- We only want the thunbnails to display when javascript is disabled -->
|
|
||||||
<script type="text/javascript">
|
|
||||||
document.write('<style>.noscript { display: none; }</style>');
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<audio id="betoven" controls autoplay loop autostart="0" src="music/betoven.mp3">
|
<script>
|
||||||
HTML5 Audio 를 지원하지 않는 브라우저 입니다
|
window.location.replace('index.php');
|
||||||
</audio> <a id="toggle" href="javascript:toggle()">stop</a>
|
|
||||||
|
|
||||||
<div id="page">
|
|
||||||
<div id="container">
|
|
||||||
<h1><a href="index.html">My DreamGirl</a></h1>
|
|
||||||
<!-- <h2>Thumbnail rollover effects and slideshow crossfades</h2> -->
|
|
||||||
|
|
||||||
<!-- Start Advanced Gallery Html Containers -->
|
|
||||||
<div class="gallery-wrap">
|
|
||||||
<div id="gallery" class="content">
|
|
||||||
<div id="controls" class="controls"></div>
|
|
||||||
<div class="slideshow-container">
|
|
||||||
<div id="loading" class="loader"></div>
|
|
||||||
<div id="slideshow" class="slideshow"></div>
|
|
||||||
</div>
|
|
||||||
<div id="caption" class="caption-container"></div>
|
|
||||||
</div>
|
|
||||||
<div id="thumbs" class="navigation">
|
|
||||||
<div id="thumbs-list">
|
|
||||||
<ul class="thumbs noscript">
|
|
||||||
<li>
|
|
||||||
<a class="thumb" name="leaf" href="http://dreamgirl.ncue.net/img/0.jpg" title="Title #0">
|
|
||||||
<!-- <img src="http://dreamgirl.ncue.net/img/0.jpg" alt="Title #0" width='75' height='75'/> -->
|
|
||||||
</a>
|
|
||||||
<div class="caption"></div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="upload-panel" class="upload-panel">
|
|
||||||
<div class="upload-title">이미지 추가</div>
|
|
||||||
<div id="dropzone" class="dropzone" tabindex="0">
|
|
||||||
<div class="dropzone-text">
|
|
||||||
드래그&드랍 또는 파일 선택
|
|
||||||
</div>
|
|
||||||
<input id="file-input" class="file-input" type="file" accept="image/*" />
|
|
||||||
</div>
|
|
||||||
<div id="upload-preview" class="upload-preview" style="display:none;">
|
|
||||||
<img id="preview-img" alt="preview" />
|
|
||||||
<div id="preview-meta" class="preview-meta"></div>
|
|
||||||
</div>
|
|
||||||
<div class="upload-actions">
|
|
||||||
<button id="upload-btn" type="button" disabled>업로드</button>
|
|
||||||
<span id="upload-status" class="upload-status"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="footer">© 2009 Trent Foley</div>
|
|
||||||
<script type="text/javascript">
|
|
||||||
// Build thumbs + init gallery after DOM is ready (and after bestpic.js runs).
|
|
||||||
jQuery(function() {
|
|
||||||
if (typeof onLoad === 'function') onLoad();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
<a href="index.php">Continue</a>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
93
index.php
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
require_once __DIR__ . '/auth/auth.php';
|
||||||
|
dreamgirl_require_login_page();
|
||||||
|
?><!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/basic.css" type="text/css" />
|
||||||
|
<link rel="stylesheet" href="css/galleriffic-2.css" type="text/css" />
|
||||||
|
|
||||||
|
<!--<script src="http://martn.ncue.net/common/js/jquery.min.js?20150610101404"></script>-->
|
||||||
|
<script type="text/javascript" src="js/jquery.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js/jquery.galleriffic.js"></script>
|
||||||
|
<script type="text/javascript" src="js/jquery.opacityrollover.js"></script>
|
||||||
|
<script type="text/javascript" src="js/bestpic.js"></script>
|
||||||
|
<script type="text/javascript" src="js/image_manifest.js"></script>
|
||||||
|
<script type="text/javascript" src="js/uploader.js"></script>
|
||||||
|
<script type="text/javascript" src="js/lightbox.js"></script>
|
||||||
|
|
||||||
|
<!-- We only want the thunbnails to display when javascript is disabled -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.write('<style>.noscript { display: none; }</style>');
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<audio id="betoven" controls autoplay loop autostart="0" src="music/betoven.mp3">
|
||||||
|
HTML5 Audio 를 지원하지 않는 브라우저 입니다
|
||||||
|
</audio> <a id="toggle" href="javascript:toggle()">stop</a>
|
||||||
|
|
||||||
|
<div id="page">
|
||||||
|
<div id="container">
|
||||||
|
<div style="display:flex; align-items:baseline; justify-content:space-between; gap:12px;">
|
||||||
|
<h1 style="margin:0;"><a href="https://ncue.net" target="_blank" rel="noopener noreferrer">NCue</a></h1>
|
||||||
|
<div style="font-size:12px;"><a href="<?php echo htmlspecialchars(dreamgirl_url('logout.php'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>">Logout</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gallery-wrap">
|
||||||
|
<div id="gallery" class="content">
|
||||||
|
<div id="controls" class="controls"></div>
|
||||||
|
<div class="slideshow-container">
|
||||||
|
<div id="loading" class="loader"></div>
|
||||||
|
<div id="slideshow" class="slideshow"></div>
|
||||||
|
</div>
|
||||||
|
<div id="caption" class="caption-container"></div>
|
||||||
|
</div>
|
||||||
|
<div id="thumbs" class="navigation">
|
||||||
|
<div id="thumbs-list">
|
||||||
|
<ul class="thumbs noscript">
|
||||||
|
<li>
|
||||||
|
<a class="thumb" name="leaf" href="http://dreamgirl.ncue.net/img/0.jpg" title="Title #0"></a>
|
||||||
|
<div class="caption"></div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="upload-panel" class="upload-panel">
|
||||||
|
<div class="upload-title">이미지 추가</div>
|
||||||
|
<div id="dropzone" class="dropzone" tabindex="0">
|
||||||
|
<div class="dropzone-text">드래그&드랍 또는 파일 선택</div>
|
||||||
|
<input id="file-input" class="file-input" type="file" accept="image/*" />
|
||||||
|
</div>
|
||||||
|
<div id="upload-preview" class="upload-preview" style="display:none;">
|
||||||
|
<img id="preview-img" alt="preview" />
|
||||||
|
<div id="preview-meta" class="preview-meta"></div>
|
||||||
|
</div>
|
||||||
|
<div class="upload-actions">
|
||||||
|
<button id="upload-btn" type="button" disabled>업로드</button>
|
||||||
|
<span id="upload-status" class="upload-status"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="footer">© 2009 Trent Foley</div>
|
||||||
|
<div id="lightbox" class="lightbox" style="display:none;" aria-hidden="true">
|
||||||
|
<div class="lightbox-backdrop"></div>
|
||||||
|
<button id="lightbox-close" class="lightbox-close" type="button" aria-label="Close">×</button>
|
||||||
|
<div class="lightbox-content" role="dialog" aria-modal="true">
|
||||||
|
<img id="lightbox-img" alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
jQuery(function() {
|
||||||
|
if (typeof onLoad === 'function') onLoad();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
51
js/lightbox.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// Fullscreen lightbox for the main slideshow image
|
||||||
|
(function ($) {
|
||||||
|
function openLightbox(src, alt) {
|
||||||
|
var $lb = $('#lightbox');
|
||||||
|
var $img = $('#lightbox-img');
|
||||||
|
if (!$lb.length || !$img.length) return;
|
||||||
|
|
||||||
|
$img.attr('src', src || '').attr('alt', alt || '');
|
||||||
|
$('body').css('overflow', 'hidden');
|
||||||
|
$lb.show().attr('aria-hidden', 'false');
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeLightbox() {
|
||||||
|
var $lb = $('#lightbox');
|
||||||
|
var $img = $('#lightbox-img');
|
||||||
|
if (!$lb.length) return;
|
||||||
|
|
||||||
|
$lb.hide().attr('aria-hidden', 'true');
|
||||||
|
if ($img.length) $img.attr('src', '');
|
||||||
|
$('body').css('overflow', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
// Clicking the big image opens the lightbox. Use delegation because slideshow content is rebuilt.
|
||||||
|
$('#slideshow').on('click', 'img', function (e) {
|
||||||
|
// Prevent galleriffic's advance-link click handler from firing
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
var src = $(this).attr('src');
|
||||||
|
var alt = $(this).attr('alt') || '';
|
||||||
|
openLightbox(src, alt);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close controls
|
||||||
|
$(document).on('click', '#lightbox-close, #lightbox .lightbox-backdrop', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
closeLightbox();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('keydown', function (e) {
|
||||||
|
if (e.keyCode === 27) { // ESC
|
||||||
|
closeLightbox();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})(jQuery);
|
||||||
|
|
||||||
|
|
||||||
65
login.php
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
require_once __DIR__ . '/auth/auth.php';
|
||||||
|
|
||||||
|
dreamgirl_session_start();
|
||||||
|
|
||||||
|
$didSso = false;
|
||||||
|
// If the user is already logged-in to NCue (Google), auto-login to DreamGirl.
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||||
|
$didSso = dreamgirl_try_ncue_sso_login();
|
||||||
|
if ($didSso) {
|
||||||
|
header('Location: ' . dreamgirl_url('index.php'));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$error = '';
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$username = isset($_POST['username']) ? (string)$_POST['username'] : '';
|
||||||
|
$password = isset($_POST['password']) ? (string)$_POST['password'] : '';
|
||||||
|
|
||||||
|
if (dreamgirl_check_credentials($username, $password)) {
|
||||||
|
$_SESSION['dreamgirl_user'] = 'admin';
|
||||||
|
header('Location: ' . dreamgirl_url('index.php'));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$error = '아이디 또는 비밀번호가 올바르지 않습니다.';
|
||||||
|
}
|
||||||
|
?><!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Login</title>
|
||||||
|
<style>
|
||||||
|
html, body { height: 100%; margin: 0; font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; background:#111; color:#eee; }
|
||||||
|
.wrap { min-height: 100%; display:flex; align-items:center; justify-content:center; padding:24px; box-sizing:border-box; }
|
||||||
|
.card { width: min(420px, 100%); background:#1b1b1b; border:1px solid #2a2a2a; border-radius:12px; padding:18px; }
|
||||||
|
h1 { font-size:18px; margin:0 0 12px; }
|
||||||
|
label { display:block; font-size:12px; color:#bbb; margin:10px 0 6px; }
|
||||||
|
input { width:100%; padding:10px 12px; border-radius:10px; border:1px solid #333; background:#0f0f0f; color:#eee; box-sizing:border-box; }
|
||||||
|
button { width:100%; margin-top:14px; padding:10px 12px; border-radius:10px; border:1px solid #3b82f6; background:#2563eb; color:#fff; cursor:pointer; }
|
||||||
|
.error { margin-top:10px; color:#ff7b7b; font-size:13px; }
|
||||||
|
.hint { margin-top:10px; color:#888; font-size:12px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="wrap">
|
||||||
|
<form class="card" method="post" action="<?php echo htmlspecialchars(dreamgirl_url('login.php'), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?>" autocomplete="off">
|
||||||
|
<h1>로그인</h1>
|
||||||
|
<label for="username">아이디</label>
|
||||||
|
<input id="username" name="username" type="text" required autofocus />
|
||||||
|
<label for="password">비밀번호</label>
|
||||||
|
<input id="password" name="password" type="password" required />
|
||||||
|
<button type="submit">접속</button>
|
||||||
|
<?php if ($error): ?>
|
||||||
|
<div class="error"><?php echo htmlspecialchars($error, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<div class="hint">인증 성공 시 페이지가 표시됩니다.</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
24
logout.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
require_once __DIR__ . '/auth/auth.php';
|
||||||
|
|
||||||
|
dreamgirl_session_start();
|
||||||
|
$_SESSION = [];
|
||||||
|
|
||||||
|
if (ini_get('session.use_cookies')) {
|
||||||
|
$params = session_get_cookie_params();
|
||||||
|
setcookie(
|
||||||
|
session_name(),
|
||||||
|
'',
|
||||||
|
time() - 42000,
|
||||||
|
$params['path'] ?? '/',
|
||||||
|
$params['domain'] ?? '',
|
||||||
|
(bool)($params['secure'] ?? false),
|
||||||
|
(bool)($params['httponly'] ?? true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
session_destroy();
|
||||||
|
header('Location: ' . dreamgirl_url('login.php'));
|
||||||
|
exit;
|
||||||
|
|
||||||