test

$success, 'errors' => array_values($errors)], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ); exit; } function value(string $key): string { $raw = $_POST[$key] ?? ''; return is_string($raw) ? trim($raw) : ''; } function cleanLine(string $text): string { return trim((string) preg_replace('/[\r\n]+/u', ' ', $text)); } function escapeHtml(string $text): string { return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } function textLength(string $text): int { return function_exists('mb_strlen') ? mb_strlen($text, 'UTF-8') : strlen($text); } function normalizeFiles(array $files): array { if (!isset($files['name']) || !is_array($files['name'])) { return []; } $result = []; foreach ($files['name'] as $index => $name) { $error = $files['error'][$index] ?? UPLOAD_ERR_NO_FILE; if ($error === UPLOAD_ERR_NO_FILE) { continue; } $result[] = [ 'name' => (string) $name, 'type' => (string) ($files['type'][$index] ?? ''), 'tmp_name' => (string) ($files['tmp_name'][$index] ?? ''), 'error' => (int) $error, 'size' => (int) ($files['size'][$index] ?? 0), ]; } return $result; } if (($_SERVER['REQUEST_METHOD'] ?? '') === 'GET' && isset($_GET['regulamin'])) { $pdf = base64_decode(EMBEDDED_REGULATIONS_PDF, true); if ($pdf === false) { http_response_code(500); exit('Nie udało się otworzyć regulaminu.'); } header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="regulamin-uslugi-projektowej-lubar.pdf"'); header('Content-Length: ' . strlen($pdf)); header('X-Content-Type-Options: nosniff'); echo $pdf; exit; } if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') { // Prosty honeypot przeciw automatom. if (value('website') !== '') { respond(200, true); } $errors = []; $submittedAt = value('submitted_at'); if ($submittedAt !== '' && ctype_digit($submittedAt)) { $elapsedMs = (int) round(microtime(true) * 1000) - (int) $submittedAt; if ($elapsedMs >= 0 && $elapsedMs < 1500) { $errors[] = 'Formularz został wysłany zbyt szybko. Odczekaj chwilę i spróbuj ponownie.'; } } $fullName = value('full_name'); $address = value('address'); $phone = value('phone'); $email = value('email'); $area = value('area'); $variant = value('variant'); $projectNotes = value('project_notes'); $photoConsent = value('photo_consent'); $regulationsAcceptance = value('regulations_acceptance'); $privacyAcceptance = value('privacy_acceptance'); if ($fullName === '') $errors[] = 'Uzupełnij imię i nazwisko.'; if ($address === '') $errors[] = 'Uzupełnij adres lub lokalizację inwestycji.'; if ($phone === '') $errors[] = 'Uzupełnij numer telefonu.'; if ($email === '' || filter_var($email, FILTER_VALIDATE_EMAIL) === false) $errors[] = 'Podaj poprawny adres e-mail.'; if (textLength($fullName) > 120) $errors[] = 'Imię i nazwisko jest zbyt długie.'; if (textLength($address) > 240) $errors[] = 'Adres jest zbyt długi.'; if (textLength($phone) > 30) $errors[] = 'Numer telefonu jest zbyt długi.'; if (textLength($email) > 160) $errors[] = 'Adres e-mail jest zbyt długi.'; if (textLength($projectNotes) > 4000) $errors[] = 'Treść uwag jest zbyt długa.'; if ($area !== '' && (!ctype_digit($area) || (int) $area < 1 || (int) $area > 99999)) { $errors[] = 'Powierzchnia musi być liczbą od 1 do 99999 m².'; } $allowedVariants = [ 'e-Projekt Koncepcja 2D - projekt za złotówkę', 'Koncepcja Plus', 'Koncepcja Premium 3D - PROMOCJA', ]; if (!in_array($variant, $allowedVariants, true)) { $errors[] = 'Wybierz wariant wykonania usługi.'; } $allowedConsents = ['Wyrażam zgodę', 'Nie wyrażam zgody']; if (!in_array($photoConsent, $allowedConsents, true)) { $errors[] = 'Wskaż decyzję dotyczącą wykorzystania fotografii lub filmów.'; } if ($regulationsAcceptance !== '1') $errors[] = 'Zaakceptuj regulamin usługi.'; if ($privacyAcceptance !== '1') $errors[] = 'Potwierdź zapoznanie się z Polityką prywatności.'; $files = normalizeFiles($_FILES['attachments'] ?? []); if (count($files) > MAX_FILES) { $errors[] = 'Można przesłać maksymalnie ' . MAX_FILES . ' plików.'; } $allowedTypes = [ 'pdf' => ['application/pdf'], 'jpg' => ['image/jpeg'], 'jpeg' => ['image/jpeg'], 'png' => ['image/png'], 'webp' => ['image/webp'], 'doc' => ['application/msword', 'application/CDFV2', 'application/x-ole-storage'], 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip'], 'xls' => ['application/vnd.ms-excel', 'application/CDFV2', 'application/x-ole-storage'], 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip'], 'dwg' => ['image/vnd.dwg', 'application/acad', 'application/x-acad', 'application/octet-stream'], 'dxf' => ['image/vnd.dxf', 'application/dxf', 'application/x-dxf', 'application/octet-stream', 'text/plain'], ]; $totalSize = 0; $preparedFiles = []; if (!class_exists('finfo')) { $errors[] = 'Na serwerze nie jest włączone rozszerzenie PHP fileinfo potrzebne do obsługi załączników.'; } else { $finfo = new finfo(FILEINFO_MIME_TYPE); foreach ($files as $file) { if ($file['error'] !== UPLOAD_ERR_OK) { $errors[] = 'Nie udało się przesłać pliku „' . cleanLine($file['name']) . '”. Kod błędu: ' . $file['error'] . '.'; continue; } if ($file['size'] <= 0 || $file['size'] > MAX_FILE_SIZE) { $errors[] = 'Plik „' . cleanLine($file['name']) . '” jest pusty albo przekracza limit 8 MB.'; continue; } $totalSize += $file['size']; $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); $detectedType = $finfo->file($file['tmp_name']) ?: 'application/octet-stream'; if (!array_key_exists($extension, $allowedTypes) || !in_array($detectedType, $allowedTypes[$extension], true)) { $errors[] = 'Niedozwolony typ pliku „' . cleanLine($file['name']) . '”.'; continue; } if (!is_uploaded_file($file['tmp_name']) || !is_readable($file['tmp_name'])) { $errors[] = 'Nie można odczytać pliku „' . cleanLine($file['name']) . '”.'; continue; } $safeName = preg_replace('/[^\pL\pN._() -]+/u', '_', basename($file['name'])); $safeName = trim((string) $safeName, '. '); if ($safeName === '') $safeName = 'zalacznik.' . $extension; $preparedFiles[] = [ 'name' => $safeName, 'type' => $detectedType, 'tmp_name' => $file['tmp_name'], ]; } } if ($totalSize > MAX_TOTAL_SIZE) { $errors[] = 'Łączny rozmiar załączników przekracza limit 20 MB.'; } if ($errors !== []) { respond(422, false, $errors); } $timestamp = new DateTimeImmutable('now', new DateTimeZone('Europe/Warsaw')); $subjectText = 'Nowe zgłoszenie projektu: ' . $fullName . ' - ' . $variant; $encodedSubject = '=?UTF-8?B?' . base64_encode($subjectText) . '?='; $ip = cleanLine((string) ($_SERVER['REMOTE_ADDR'] ?? 'brak danych')); $userAgent = cleanLine((string) ($_SERVER['HTTP_USER_AGENT'] ?? 'brak danych')); $rows = [ 'Data zgłoszenia' => $timestamp->format('d.m.Y H:i'), 'Imię i nazwisko' => $fullName, 'Telefon' => $phone, 'E-mail' => $email, 'Adres / lokalizacja' => $address, 'Powierzchnia' => $area !== '' ? $area . ' m²' : 'nie podano', 'Wariant usługi' => $variant, 'Zgoda na fotografie/filmy' => $photoConsent, 'Akceptacja regulaminu' => 'Tak', 'Polityka prywatności' => 'Potwierdzona', 'Adres IP' => $ip, ]; $htmlRows = ''; foreach ($rows as $label => $content) { $htmlRows .= '' . '' . escapeHtml($label) . '' . '' . nl2br(escapeHtml($content)) . '' . ''; } $htmlBody = '' . '
' . '
LUBAR

Nowe zgłoszenie usługi projektowej

' . '
' . '' . $htmlRows . '
' . '

Założenia projektu / uwagi

' . '
' . ($projectNotes !== '' ? nl2br(escapeHtml($projectNotes)) : 'Nie podano.') . '
' . '

Przeglądarka: ' . escapeHtml($userAgent) . '

' . '
'; $boundaryMixed = 'mixed_' . bin2hex(random_bytes(16)); $boundaryAlt = 'alt_' . bin2hex(random_bytes(16)); $eol = "\r\n"; $headers = [ 'MIME-Version: 1.0', 'From: ' . SENDER_NAME . ' <' . SENDER_EMAIL . '>', 'Reply-To: ' . cleanLine($fullName) . ' <' . $email . '>', 'Content-Type: multipart/mixed; boundary="' . $boundaryMixed . '"', 'X-Mailer: PHP/' . PHP_VERSION, ]; $message = '--' . $boundaryMixed . $eol; $message .= 'Content-Type: multipart/alternative; boundary="' . $boundaryAlt . '"' . $eol . $eol; $plainBody = "NOWE ZGŁOSZENIE USŁUGI PROJEKTOWEJ\n\n"; foreach ($rows as $label => $content) { $plainBody .= $label . ': ' . $content . "\n"; } $plainBody .= "\nZałożenia projektu / uwagi:\n" . ($projectNotes !== '' ? $projectNotes : 'Nie podano.') . "\n"; $message .= '--' . $boundaryAlt . $eol; $message .= 'Content-Type: text/plain; charset=UTF-8' . $eol; $message .= 'Content-Transfer-Encoding: base64' . $eol . $eol; $message .= chunk_split(base64_encode($plainBody)) . $eol; $message .= '--' . $boundaryAlt . $eol; $message .= 'Content-Type: text/html; charset=UTF-8' . $eol; $message .= 'Content-Transfer-Encoding: base64' . $eol . $eol; $message .= chunk_split(base64_encode($htmlBody)) . $eol; $message .= '--' . $boundaryAlt . '--' . $eol; foreach ($preparedFiles as $file) { $content = file_get_contents($file['tmp_name']); if ($content === false) { respond(500, false, ['Nie udało się odczytać jednego z załączników.']); } $encodedFilename = rawurlencode($file['name']); $message .= '--' . $boundaryMixed . $eol; $message .= 'Content-Type: ' . $file['type'] . '; name="attachment"' . $eol; $message .= 'Content-Transfer-Encoding: base64' . $eol; $message .= "Content-Disposition: attachment; filename*=UTF-8''" . $encodedFilename . $eol . $eol; $message .= chunk_split(base64_encode($content)) . $eol; } $message .= '--' . $boundaryMixed . '--' . $eol; if (!function_exists('mail')) { respond(500, false, ['Na serwerze nie jest dostępna funkcja mail(). Skonfiguruj wysyłkę poczty w PHP.']); } $sent = mail( RECIPIENT, $encodedSubject, $message, implode($eol, $headers) ); if (!$sent) { respond(500, false, ['Serwer nie przyjął wiadomości do wysyłki. Sprawdź konfigurację poczty PHP.']); } respond(200, true); } ?> Formularz usługi projektowej | LUBAR
LUBAR
Data zgłoszenia: —

Kostka brukowa / tarasy

Formularz usługi projektowej zagospodarowania terenu

Wypełnij dane, wybierz wariant usługi i dołącz zdjęcia lub dokumentację terenu. Zgłoszenie zostanie przesłane na adres [email protected].

1

Dane Klienta

Pola oznaczone gwiazdką są obowiązkowe.

Projektant prowadzący: Martyna Szczotka tel. 605 993 360 · [email protected]
2

Wariant wykonania usługi

Wybór wariantu jest obowiązkowy.

Wybierz jeden wariant *
3

Informacje i załączniki

Dołącz zdjęcia posesji, rzut budynku, plan działki lub inne materiały pomocne projektantowi.

Kliknij lub przeciągnij pliki tutaj
Maks. 8 plików, do 8 MB każdy i 20 MB łącznie. PDF, JPG, PNG, WEBP, DOC(X), XLS(X), DWG, DXF.
    4

    W każdym polu wyboru należy wskazać odpowiedź lub zaznaczyć wymagane potwierdzenie.

    Najważniejsze informacje o usłudze
    Usługa obejmuje przygotowanie koncepcji zagospodarowania terenu z wykorzystaniem produktów oferowanych przez LUBAR. Terminy, ceny, zakres wariantów, zasady poprawek i warunki promocji opisano w pełnym regulaminie.

    Otwórz pełny regulamin

    Zgoda na wykorzystanie fotografii lub filmów *
    Dane zostaną wykorzystane do kontaktu i realizacji usługi. Formularz wysyła zgłoszenie bezpośrednio na adres [email protected].