-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.php
More file actions
307 lines (267 loc) · 10.5 KB
/
Copy pathconfig.php
File metadata and controls
307 lines (267 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
<?php
/**
* MAS-CAR AUTO — Genel Yapılandırma Dosyası (Enhanced)
* -----------------------------------------------------------------------
* Bu dosyayı sunucunuza yüklemeden önce aşağıdaki veritabanı bilgilerini
* kendi hosting / phpMyAdmin bilgilerinizle güncelleyin.
* -----------------------------------------------------------------------
*/
// Bu dosyaya doğrudan tarayıcıdan erişimi engelle
if (basename($_SERVER['SCRIPT_FILENAME'] ?? '') === basename(__FILE__)) {
http_response_code(403);
exit('Forbidden');
}
// =====================================================================
// VERİTABANI BİLGİLERİ (kendi bilgilerinizle değiştirin)
// =====================================================================
define('DB_HOST', 'localhost');
define('DB_NAME', 'mascar_auto');
define('DB_USER', 'root');
define('DB_PASS', 'mysql');
define('DB_CHARSET', 'utf8mb4');
// =====================================================================
// SİTE BİLGİLERİ
// =====================================================================
define('SITE_URL', 'localhost');
define('SITE_NAME', 'Mas-Car Auto Özel Servis Kocaali');
define('SITE_PHONE', '+905424495454');
define('SITE_PHONE_DISPLAY', '0 (542) 449 5454');
define('SITE_EMAIL', 'info@mascarauto.com.tr');
define('SITE_ADDRESS', 'Yayla Mah. Gaffar Okkan Cad. No:1, Kocaali / Sakarya');
// =====================================================================
// DOSYA YÜKLEME AYARLARI
// =====================================================================
define('UPLOAD_DIR_VEHICLES', __DIR__ . '/uploads/vehicles/');
define('UPLOAD_URL_VEHICLES', '/uploads/vehicles/');
define('UPLOAD_DIR_GALLERY', __DIR__ . '/uploads/gallery/');
define('UPLOAD_URL_GALLERY', '/uploads/gallery/');
define('MAX_UPLOAD_SIZE', 5 * 1024 * 1024); // 5 MB
define('ALLOWED_IMAGE_TYPES', ['image/jpeg', 'image/png', 'image/webp']);
// =====================================================================
// GÖRSEL İŞLEME AYARLARI
// =====================================================================
define('MAX_OUTPUT_SIZE', 200 * 1024); // 200 KB — maksimum optimize edilmiş görüntü boyutu
define('WEBP_QUALITY', 80); // WebP dönüşüm kalitesi (0-100)
define('THUMBNAIL_MAX_WIDTH', 400); // Küçük resim maksimum genişlik (px)
// =====================================================================
// ZAMAN DİLİMİ
// =====================================================================
date_default_timezone_set('Europe/Istanbul');
// =====================================================================
// OTURUM (SESSION)
// =====================================================================
if (session_status() === PHP_SESSION_NONE) {
session_set_cookie_params([
'lifetime' => 60 * 60 * 8, // 8 saat
'path' => '/',
'httponly' => true,
'samesite' => 'Lax',
]);
session_start();
}
// =====================================================================
// HATA GÖSTERİMİ (canlıya almadan önce false yapın)
// =====================================================================
define('APP_DEBUG', false);
if (APP_DEBUG) {
ini_set('display_errors', 1);
error_reporting(E_ALL);
} else {
ini_set('display_errors', 0);
error_reporting(0);
}
// =====================================================================
// DATABASE CONNECTION
// =====================================================================
/**
* PDO veritabanı bağlantısı döndürür (tekil / singleton).
*/
function db(): PDO
{
static $pdo = null;
if ($pdo === null) {
$dsn = 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=' . DB_CHARSET;
try {
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
} catch (PDOException $e) {
http_response_code(500);
die('Veritabanı bağlantısı kurulamadı. Lütfen config.php dosyasındaki bilgileri kontrol edin.');
}
}
return $pdo;
}
// =====================================================================
// HELPER FUNCTIONS
// =====================================================================
/**
* Basit XSS koruması için kısayol.
*/
function h(?string $value): string
{
return htmlspecialchars($value ?? '', ENT_QUOTES, 'UTF-8');
}
// =====================================================================
// CSRF PROTECTION (form + AJAX)
// =====================================================================
/**
* CSRF token üret (oturumda saklanır).
*/
function csrf_token(): string
{
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf_token'];
}
/**
* CSRF token doğrula — form POST istekleri için.
* Başarısız olursa 400 döndürür ve betik durur.
*/
function csrf_check(): void
{
$token = $_POST['csrf_token'] ?? '';
if (!hash_equals($_SESSION['csrf_token'] ?? '', $token)) {
http_response_code(400);
die('Geçersiz istek (CSRF doğrulaması başarısız). Lütfen sayfayı yenileyip tekrar deneyin.');
}
}
/**
* Gizli <input> alanı olarak CSRF token HTML çıktısı üretir.
* Formların içine echo generateCsrfField(); şeklinde eklenir.
*/
function generateCsrfField(): string
{
$token = csrf_token();
return '<input type="hidden" name="csrf_token" value="' . htmlspecialchars($token, ENT_QUOTES, 'UTF-8') . '">';
}
/**
* AJAX isteklerinde CSRF token doğrulaması.
* JSON gövdesindeki "csrf_token" alanını okur ve doğrular.
*
* @return bool true ise token geçerli
*/
function validateCsrfAjax(): bool
{
$input = json_decode(file_get_contents('php://input'), true);
$token = $input['csrf_token'] ?? '';
return hash_equals($_SESSION['csrf_token'] ?? '', $token);
}
// =====================================================================
// IMAGE UPLOAD PROCESSING
// =====================================================================
/**
* Yüklenen bir görüntüyü güvenli şekilde işler:
* 1. MIME tipi doğrulama (finfo)
* 2. Dosya uzantısı doğrulama
* 3. PHP kodu bulaşması kontrolü
* 4. Benzersiz dosya adı üretme
* 5. WebP dönüşümü + kalite sıkıştırma (max 200 KB)
* 6. Küçük resim (thumbnail) oluşturma
*
* @param string $tempPath Geçici yükleme yolu ($_FILES[x]['tmp_name'])
* @param string $destDir Hedef klasör (mutlak yol, sonuna / ekleyin)
* @return array{
* original_name: string,
* webp_path: string,
* thumbnail_path: string,
* file_size: int
* }
*
* @throws RuntimeException Herhangi bir doğrulama veya GD hatası
*/
function processImageUpload(string $tempPath, string $destDir): array
{
// ---- 1. MIME Tipi Doğrulama ----
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($tempPath);
$allowedMimes = ['image/jpeg', 'image/png', 'image/webp'];
if (!in_array($mime, $allowedMimes, true)) {
throw new RuntimeException('Geçersiz dosya türü. Sadece JPEG, PNG ve WebP dosyaları yüklenebilir.');
}
// ---- 2. Dosya Uzantısı Doğrulama ----
$originalName = basename($tempPath);
$ext = strtolower(pathinfo($tempPath, PATHINFO_EXTENSION));
$allowedExts = ['jpg', 'jpeg', 'png', 'webp'];
// tmp_name genelde uzantısızdır; MIME → varsayılan uzantı haritalaması
$mimeToExt = [
'image/jpeg' => 'jpg',
'image/png' => 'png',
'image/webp' => 'webp',
];
$ext = $mimeToExt[$mime] ?? $ext;
if (!in_array($ext, $allowedExts, true)) {
throw new RuntimeException('Geçersiz dosya uzantısı. Sadece jpg, png, webp dosyaları yüklenebilir.');
}
// ---- 3. PHP Kodu Bulaşması Kontrolü ----
$content = file_get_contents($tempPath);
if (strpos($content, '<?') !== false) {
throw new RuntimeException('Dosya içinde güvenlik tehdidi tespit edildi. Yükleme reddedildi.');
}
unset($content); // belleği temizle
// ---- 4. Benzersiz Dosya Adı Üretme ----
$prefix = bin2hex(random_bytes(8)); // 16 karakterlik rastgele önek
$webpFilename = $prefix . '.webp';
$thumbFilename = $prefix . '_thumb.webp';
$webpPath = rtrim($destDir, '/') . '/' . $webpFilename;
$thumbPath = rtrim($destDir, '/') . '/' . $thumbFilename;
// Hedef dizin yoksa oluştur
if (!is_dir($destDir)) {
if (!mkdir($destDir, 0755, true)) {
throw new RuntimeException('Hedef klasör oluşturulamadı: ' . $destDir);
}
}
// ---- 5. GD ile Görüntüyü Yükle ----
switch ($mime) {
case 'image/jpeg':
$source = imagecreatefromjpeg($tempPath);
break;
case 'image/png':
$source = imagecreatefrompng($tempPath);
break;
case 'image/webp':
$source = imagecreatefromwebp($tempPath);
break;
default:
throw new RuntimeException('Desteklenmeyen görüntü biçimi.');
}
if ($source === false) {
throw new RuntimeException('Görüntü GD kütüphanesiyle açılamadı.');
}
// ---- 6. WebP Dönüşümü + Kalite Sıkıştırma (max 200 KB) ----
$quality = WEBP_QUALITY;
$success = false;
for ($q = $quality; $q >= 10; $q -= 5) {
// Thumbnail'ı önce oluştur (kaynak görüntüyü bozmamak için kopyala)
$thumbCopy = imagescale($source, THUMBNAIL_MAX_WIDTH);
if ($thumbCopy === false) {
imagedestroy($source);
throw new RuntimeException('Küçük resim oluşturulamadı.');
}
imagewebp($thumbCopy, $thumbPath, $q);
imagedestroy($thumbCopy);
// Ana WebP dosyasını kaydet
$saved = imagewebp($source, $webpPath, $q);
if ($saved && file_exists($webpPath) && filesize($webpPath) <= MAX_OUTPUT_SIZE) {
$success = true;
break;
}
}
imagedestroy($source);
if (!$success) {
// Temizlik
@unlink($webpPath);
@unlink($thumbPath);
throw new RuntimeException('Görüntü 200 KB altına sıkıştırılamadı. Lütfen daha küçük bir dosya yükleyin.');
}
// ---- 7. Sonuç Dizisi ----
return [
'original_name' => $originalName,
'webp_path' => $webpFilename, // sadece dosya adı (veritabanına kaydetmek için)
'thumbnail_path' => $thumbFilename,
'file_size' => filesize($webpPath),
];
}