Compare commits
24 Commits
28d30e3359
...
752bbf3a63
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
752bbf3a63 | ||
|
|
a8748cf4c9 | ||
|
|
3543fdd2cd | ||
|
|
50a5308f43 | ||
|
|
2d607d9e90 | ||
|
|
790d58aaa2 | ||
|
|
72eeb24cd7 | ||
|
|
e51d266a0f | ||
|
|
f528e1d3c5 | ||
|
|
0e28814e7d | ||
|
|
16331bd35d | ||
|
|
623d66a3d8 | ||
|
|
1a9619f9f8 | ||
|
|
70c06edd71 | ||
|
|
75aeb73f27 | ||
|
|
1d3ea597f4 | ||
|
|
3dad979eb5 | ||
|
|
81376a2245 | ||
|
|
c82b0071bb | ||
|
|
0ceb67ee56 | ||
|
|
8c6dea5d96 | ||
|
|
d6f29802e0 | ||
|
|
4a9e6b22c5 | ||
|
|
9bbda24d4a |
97
.gitignore
vendored
Normal file
97
.gitignore
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
# ============================================================
|
||||
# Siro Project - .gitignore
|
||||
# ============================================================
|
||||
|
||||
# --- Environment & Secrets ---
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
**/*.env
|
||||
**/private_key.pem
|
||||
**/public_key.pem
|
||||
*.pem
|
||||
service-account.json
|
||||
**/service-account.json
|
||||
|
||||
# --- IDE & OS ---
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.vscode/
|
||||
.idea/
|
||||
*.iml
|
||||
.ruby-lsp/
|
||||
.kilo/
|
||||
|
||||
# --- Build Artifacts ---
|
||||
node_modules/
|
||||
vendor/
|
||||
**/vendor/
|
||||
build/
|
||||
dist/
|
||||
*.js.map
|
||||
*.css.map
|
||||
|
||||
# --- Flutter/Dart ---
|
||||
.dart_tool/
|
||||
.packages
|
||||
.pub-cache/
|
||||
pubspec.lock
|
||||
*.g.dart
|
||||
**/env.g.dart
|
||||
*.freezed.dart
|
||||
*.config.dart
|
||||
|
||||
# --- Android ---
|
||||
*.apk
|
||||
*.aab
|
||||
*.dex
|
||||
*.class
|
||||
*.keystore
|
||||
local.properties
|
||||
android/.gradle/
|
||||
android/captures/
|
||||
|
||||
# --- iOS ---
|
||||
*.ipa
|
||||
*.dSYM.zip
|
||||
*.dSYM
|
||||
Pods/
|
||||
DerivedData/
|
||||
*.xcworkspace
|
||||
xcuserdata/
|
||||
|
||||
# --- Composer / PHP ---
|
||||
/composer.lock
|
||||
**/composer.lock
|
||||
|
||||
# --- Logs ---
|
||||
*.log
|
||||
logs/
|
||||
**/logs/
|
||||
|
||||
# --- Uploads ---
|
||||
uploads/
|
||||
**/uploads/
|
||||
portrate_captain_image/
|
||||
card_image/
|
||||
imageForUsingApp/
|
||||
new_driver_car/
|
||||
upload_audio/
|
||||
|
||||
# --- Python ---
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.venv/
|
||||
venv/
|
||||
|
||||
# --- Firebase ---
|
||||
google-services.json
|
||||
.google-services.json
|
||||
GoogleService-Info.plist
|
||||
|
||||
# --- Audit/Scan Output ---
|
||||
semgrep_*.json
|
||||
nuclei_results.txt
|
||||
@@ -1,6 +1,12 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
`driver`.`id`,
|
||||
`driver`.`phone`,
|
||||
@@ -48,9 +54,14 @@ $sql = "SELECT
|
||||
) AS passengerToken
|
||||
FROM `driver`
|
||||
ORDER BY passengerAverageRating DESC
|
||||
LIMIT 10";
|
||||
LIMIT :lim OFFSET :off";
|
||||
|
||||
$stmt = $con->prepare($sql);
|
||||
$page = max(1, (int) filterRequest('page'));
|
||||
$limit = 10;
|
||||
$offset = ($page - 1) * $limit;
|
||||
$stmt->bindValue(':lim', $limit, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':off', $offset, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
@@ -67,8 +78,16 @@ foreach ($result as &$row) {
|
||||
$row['maritalStatus'] = $encryptionHelper->decryptData($row['maritalStatus']);
|
||||
}
|
||||
|
||||
$countStmt = $con->query("SELECT COUNT(*) FROM `driver`");
|
||||
$total = $countStmt->fetchColumn();
|
||||
|
||||
if (count($result) > 0) {
|
||||
jsonSuccess($result);
|
||||
jsonSuccess([
|
||||
'data' => $result,
|
||||
'total' => (int) $total,
|
||||
'page' => $page,
|
||||
'pages' => (int) ceil($total / $limit),
|
||||
]);
|
||||
} else {
|
||||
jsonError("No records found");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$page = max(1, (int) filterRequest('page'));
|
||||
$limit = 50;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$sql = "
|
||||
SELECT
|
||||
d.phone,
|
||||
@@ -11,13 +21,18 @@ FROM
|
||||
`driver` d
|
||||
LEFT JOIN driverToken dt ON
|
||||
dt.captain_id = d.id
|
||||
LIMIT :lim OFFSET :off
|
||||
";
|
||||
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindValue(':lim', $limit, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':off', $offset, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// فك التشفير للحقول الحساسة
|
||||
$countStmt = $con->query("SELECT COUNT(*) FROM `driver`");
|
||||
$total = $countStmt->fetchColumn();
|
||||
|
||||
foreach ($result as &$row) {
|
||||
$row['phone'] = $encryptionHelper->decryptData($row['phone']);
|
||||
if (!empty($row['token'])) {
|
||||
@@ -26,8 +41,12 @@ foreach ($result as &$row) {
|
||||
}
|
||||
|
||||
if ($stmt->rowCount() > 0) {
|
||||
jsonSuccess($result);
|
||||
jsonSuccess([
|
||||
'data' => $result,
|
||||
'total' => (int) $total,
|
||||
'page' => $page,
|
||||
'pages' => (int) ceil($total / $limit),
|
||||
]);
|
||||
} else {
|
||||
jsonError("No records found");
|
||||
}
|
||||
?>
|
||||
@@ -49,6 +49,6 @@ try {
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("[Staff Activate Error] " . $e->getMessage());
|
||||
jsonError("خطأ في السيرفر: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
exit();
|
||||
|
||||
@@ -96,5 +96,5 @@ try {
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("[Staff Add Error] " . $e->getMessage());
|
||||
jsonError("Server error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
|
||||
@@ -37,6 +37,6 @@ try {
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("[Staff Pending Error] " . $e->getMessage());
|
||||
jsonError("خطأ في السيرفر: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
exit();
|
||||
|
||||
@@ -61,5 +61,5 @@ try {
|
||||
}
|
||||
echo "<h1>Initialization Successful</h1>";
|
||||
} catch (Exception $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
echo "An internal error occurred";
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ try {
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("[Admin Add Error] " . $e->getMessage());
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
// عرض كافة الأخطاء
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_errors', 0);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
@@ -83,6 +83,6 @@ try {
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => "Database error: $errorMsg"
|
||||
'message' => "Database error occurred"
|
||||
]);
|
||||
}
|
||||
@@ -22,7 +22,7 @@ try {
|
||||
} catch (PDOException $e) {
|
||||
echo json_encode([
|
||||
"status" => "error",
|
||||
"message" => "Database error: " . $e->getMessage()
|
||||
"message" => "An internal error occurred"
|
||||
]);
|
||||
}
|
||||
?>
|
||||
@@ -44,5 +44,5 @@ try {
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("[Approve Admin Error] " . $e->getMessage());
|
||||
jsonError("Server Error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
|
||||
@@ -29,5 +29,5 @@ try {
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("[List Pending Admins Error] " . $e->getMessage());
|
||||
jsonError("Server Error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
|
||||
@@ -140,11 +140,12 @@ try {
|
||||
$success = sendWhatsAppFromServer($phone, $messageBody);
|
||||
|
||||
if ($success) {
|
||||
// حفظ الرمز كما هو في قاعدة البيانات (بدون تشفير)
|
||||
// تخزين هاش للـ OTP بدلاً من النص الصريح
|
||||
$otpHash = hash('sha256', (string)$otp);
|
||||
$stmt = $con->prepare("INSERT INTO token_verification_admin (phone_number, token, expiration_time)
|
||||
VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 10 MINUTE))
|
||||
ON DUPLICATE KEY UPDATE token = VALUES(token), expiration_time = VALUES(expiration_time)");
|
||||
$stmt->execute([$encryptedPhone, $otp]);
|
||||
$stmt->execute([$encryptedPhone, $otpHash]);
|
||||
|
||||
// إخفاء جزء من الرقم في الاستجابة للأمان
|
||||
$maskedPhone = substr($phone, 0, 4) . '****' . substr($phone, -3);
|
||||
|
||||
@@ -22,12 +22,13 @@ if ($admin->role !== 'admin' && $admin->role !== 'super_admin') {
|
||||
}
|
||||
|
||||
try {
|
||||
// جلب المفتاح المشترك لسيرفر المحفظة
|
||||
$payKeyPath = '/home/siro-api/.secret_key_pay';
|
||||
$payKey = file_exists($payKeyPath) ? trim(file_get_contents($payKeyPath)) : getenv('SECRET_KEY_PAY');
|
||||
// جلب المفتاح المشترك لسيرفر المحفظة من متغير البيئة أو الملف
|
||||
$payKeyPath = getenv('SECRET_KEY_PAY_PATH');
|
||||
$payKey = ($payKeyPath && file_exists($payKeyPath)) ? trim(file_get_contents($payKeyPath)) : getenv('SECRET_KEY_PAY');
|
||||
|
||||
if (empty($payKey)) {
|
||||
$payKey = trim(@file_get_contents('/home/siro-api/.secret_key'));
|
||||
$fallbackPath = getenv('SECRET_KEY_PATH');
|
||||
$payKey = ($fallbackPath && file_exists($fallbackPath)) ? trim(file_get_contents($fallbackPath)) : null;
|
||||
}
|
||||
|
||||
if (empty($payKey)) {
|
||||
@@ -89,5 +90,5 @@ try {
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("[Admin Wallet SSO Error] " . $e->getMessage());
|
||||
jsonError("Server Error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
|
||||
@@ -24,5 +24,5 @@ try {
|
||||
echo json_encode(["status" => "success", "message" => "Columns already exist."]);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(["status" => "error", "message" => $e->getMessage()]);
|
||||
echo json_encode(["status" => "error", "message" => "An internal error occurred"]);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ foreach ($tables as $table => $columns) {
|
||||
}
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch (Exception $e) {
|
||||
echo "Skipped $table due to error: " . $e->getMessage() . "\n";
|
||||
echo "An internal error occurred" . "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,12 +53,6 @@ try {
|
||||
$encPhone = $encPhoneInput;
|
||||
$encFp = $encryptionHelper->encryptData($fingerprint);
|
||||
|
||||
// التأكد من وجود عمود phone و status في الجدول
|
||||
try {
|
||||
$con->exec("ALTER TABLE adminUser ADD COLUMN phone VARCHAR(255) NULL AFTER name");
|
||||
$con->exec("ALTER TABLE adminUser ADD COLUMN status VARCHAR(50) DEFAULT 'pending' AFTER role");
|
||||
} catch (Exception $e) { /* الأعمدة موجودة مسبقاً */ }
|
||||
|
||||
// 4. الإدخال في قاعدة البيانات بحالة pending
|
||||
$sql = "INSERT INTO adminUser (id, fingerprint, fingerprint_hash, name, phone, password, role, status, created_at)
|
||||
VALUES (:id, :fp, :fp_hash, :name, :phone, :pass, 'admin', 'pending', NOW())";
|
||||
@@ -80,7 +74,7 @@ try {
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("[Admin Register Error] " . $e->getMessage());
|
||||
jsonError("خطأ في السيرفر: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
|
||||
exit();
|
||||
|
||||
@@ -39,14 +39,14 @@ try {
|
||||
// فك تشفيره لو احتجنا إرساله أو عرضه، لكن هنا نحن نحتاج المشفر للبحث
|
||||
// $phone = $encryptionHelper->decryptData($encryptedPhone);
|
||||
|
||||
// تشفير الرمز (OTP) القادم من التطبيق للمقارنة
|
||||
$encryptedOtp = $encryptionHelper->encryptData((string)$otp);
|
||||
// هاش الرمز (OTP) القادم من التطبيق للمقارنة
|
||||
$otpHash = hash('sha256', (string)$otp);
|
||||
|
||||
// 3. التحقق من الـ OTP (باستخدام القيم المشفرة)
|
||||
// 3. التحقق من الـ OTP
|
||||
$stmt = $con->prepare("SELECT * FROM token_verification_admin
|
||||
WHERE phone_number = ? AND token = ?
|
||||
AND expiration_time >= NOW()");
|
||||
$stmt->execute([$encryptedPhone, $encryptedOtp]);
|
||||
$stmt->execute([$encryptedPhone, $otpHash]);
|
||||
|
||||
if ($stmt->rowCount() === 0) {
|
||||
jsonError("رمز التحقق غير صالح أو منتهي الصلاحية.");
|
||||
@@ -83,5 +83,5 @@ try {
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("[Admin Verify OTP Error] " . $e->getMessage());
|
||||
jsonError("خطأ في السيرفر: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# 🔒 SECURITY: Block all access to debug files
|
||||
# This directory contains sensitive debugging scripts
|
||||
# DO NOT remove this file in production
|
||||
|
||||
<RequireAll>
|
||||
Require all denied
|
||||
</RequireAll>
|
||||
|
||||
# Alternative for older Apache:
|
||||
# Deny from all
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
require_once 'connect.php';
|
||||
|
||||
try {
|
||||
$stmt = $con->query("SELECT phone FROM driver LIMIT 10");
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($rows as $row) {
|
||||
echo "Raw: " . $row['phone'] . " | Decrypted: " . $encryptionHelper->decryptData($row['phone']) . "\n";
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
echo "An error occurred.";
|
||||
}
|
||||
?>
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
require_once 'connect.php';
|
||||
|
||||
try {
|
||||
$stmt = $con->query("DESCRIBE users");
|
||||
$cols = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
echo json_encode($cols, JSON_PRETTY_PRINT);
|
||||
} catch (Exception $e) {
|
||||
echo "An error occurred.";
|
||||
}
|
||||
?>
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/connect.php';
|
||||
|
||||
$searchPhone = '0992952235';
|
||||
echo "Searching for: $searchPhone\n";
|
||||
|
||||
$variants = [$searchPhone, '963' . substr($searchPhone, 1), '+963' . substr($searchPhone, 1)];
|
||||
|
||||
foreach ($variants as $v) {
|
||||
echo "Checking variant: $v\n";
|
||||
$enc = $encryptionHelper->encryptData($v);
|
||||
|
||||
$stmt = $con->prepare("SELECT id, phone, first_name FROM driver WHERE phone = ? OR phone = ?");
|
||||
$stmt->execute([$v, $enc]);
|
||||
$res = $stmt->fetch();
|
||||
|
||||
if ($res) {
|
||||
echo "FOUND! ID: {$res['id']}, Name: {$res['first_name']}, Phone in DB: {$res['phone']}\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
echo "NOT FOUND in driver table.\n";
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
// env_test.php - أداة مخصصة لاختبار جميع متغيرات البيئة
|
||||
require_once __DIR__ . '/core/bootstrap.php'; // لتحميل الـ .env
|
||||
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
|
||||
echo "=== فحص متغيرات البيئة (Environment Variables) ===\n\n";
|
||||
|
||||
$keysToCheck = [
|
||||
'PASSENGER_SOCKET_URL',
|
||||
'LOCATION_SOCKET_URL',
|
||||
'INTERNAL_SOCKET_KEY_PATH',
|
||||
'SECRET_KEY_PAY_PATH',
|
||||
'SECRET_KEY_HMAC',
|
||||
'allowed1',
|
||||
'allowed2',
|
||||
'passwordnewpassenger',
|
||||
'FP_PEPPER'
|
||||
];
|
||||
|
||||
foreach ($keysToCheck as $key) {
|
||||
$val = getenv($key);
|
||||
if ($val !== false && $val !== '') {
|
||||
// إخفاء جزء من القيم الحساسة مثل كلمات المرور
|
||||
if (strpos(strtolower($key), 'password') !== false || strpos(strtolower($key), 'secret') !== false || strpos(strtolower($key), 'hmac') !== false) {
|
||||
$hiddenVal = substr($val, 0, 3) . '***' . substr($val, -3);
|
||||
echo "[OK] $key = $hiddenVal\n";
|
||||
} else {
|
||||
echo "[OK] $key = $val\n";
|
||||
}
|
||||
} else {
|
||||
echo "[ERROR] $key = (مفقود أو فارغ!)\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n\n=== فحص الملفات المباشرة ===\n\n";
|
||||
|
||||
$filesToCheck = [
|
||||
'/home/siro-api/.internal_socket_key',
|
||||
'/home/siro-api/.secret_key_pay'
|
||||
];
|
||||
|
||||
foreach ($filesToCheck as $file) {
|
||||
if (file_exists($file)) {
|
||||
$content = trim(file_get_contents($file));
|
||||
if (!empty($content)) {
|
||||
$hidden = substr($content, 0, 3) . '***' . substr($content, -3);
|
||||
echo "[OK] File ($file) exists and has content: $hidden\n";
|
||||
} else {
|
||||
echo "[WARNING] File ($file) exists but is EMPTY!\n";
|
||||
}
|
||||
} else {
|
||||
echo "[ERROR] File ($file) DOES NOT EXIST!\n";
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n=== انتهى الفحص ===\n";
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
include 'connect.php';
|
||||
|
||||
// نضمن أن الرد دائماً JSON
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// 1) قراءة الـ body كـ JSON (من Flutter)
|
||||
$raw = file_get_contents('php://input');
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
if (!is_array($data)) {
|
||||
// fallback لو أرسلت form-data أو x-www-form-urlencoded
|
||||
$data = $_POST;
|
||||
}
|
||||
|
||||
// 2) التحقق من رقم هاتف الأدمن المصرّح له
|
||||
|
||||
// قراءة الأرقام المسموح لها من الـ ENV
|
||||
$phonesRaw = getenv('ADMIN_PHONE_NUMBERS') ?: '';
|
||||
$ALLOWED_TOOL_PHONES = array_values(
|
||||
array_filter(
|
||||
array_map(function ($p) {
|
||||
// إزالة أي رموز غير رقمية (مسافات، +، - إلخ)
|
||||
return preg_replace('/\D+/', '', $p);
|
||||
}, explode(',', $phonesRaw))
|
||||
)
|
||||
);
|
||||
|
||||
// رقم الهاتف القادم من Flutter (parameter جديد)
|
||||
$adminPhoneParam = isset($data['admin_phone'])
|
||||
? preg_replace('/\D+/', '', $data['admin_phone'])
|
||||
: '';
|
||||
|
||||
// إذا لم يُرسل رقم أو لم يكن ضمن القائمة → منع الوصول
|
||||
if ($adminPhoneParam === '' || !in_array($adminPhoneParam, $ALLOWED_TOOL_PHONES, true)) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'Access denied for this admin phone.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 3) التحقق من بقية المدخلات (action + text)
|
||||
$action = $data['action'] ?? '';
|
||||
$text = trim($data['text'] ?? '');
|
||||
|
||||
if ($text === '' || ($action !== 'encrypt' && $action !== 'decrypt')) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'Invalid input: need action=encrypt|decrypt and non-empty text.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 4) تنفيذ التشفير / الفك
|
||||
try {
|
||||
// require_once __DIR__ . '/encrypt_decrypt.php';
|
||||
|
||||
if ($action === 'encrypt') {
|
||||
$result = $encryptionHelper->encryptData($text);
|
||||
} else { // decrypt
|
||||
$result = $encryptionHelper->decryptData($text);
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'action' => $action,
|
||||
'result' => (string) $result,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'Operation failed.',
|
||||
]);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
require_once 'connect.php';
|
||||
|
||||
echo "--- ADMIN TABLE ---\n";
|
||||
try {
|
||||
$stmt = $con->prepare("SELECT id, name, role FROM admin");
|
||||
$stmt->execute();
|
||||
$admins = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
print_r($admins);
|
||||
} catch (Exception $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
echo "\n--- DATABASES ---\n";
|
||||
try {
|
||||
$stmt = $con->prepare("SHOW DATABASES");
|
||||
$stmt->execute();
|
||||
$dbs = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
print_r($dbs);
|
||||
} catch (Exception $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
}
|
||||
?>
|
||||
@@ -1,2 +0,0 @@
|
||||
<?php
|
||||
echo ini_get('error_log');
|
||||
@@ -1,13 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../core/bootstrap.php';
|
||||
require_once __DIR__ . '/../functions.php';
|
||||
|
||||
$con = Database::get('main');
|
||||
$lat = 32.11171;
|
||||
$lng = 36.06737;
|
||||
$carType = 'Fixed Price';
|
||||
|
||||
echo "Testing findBestDrivers...\n";
|
||||
$drivers = findBestDrivers($con, $lat, $lng, $carType);
|
||||
print_r($drivers);
|
||||
echo "Done.\n";
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../core/bootstrap.php';
|
||||
$redis = getRedis(); // or however it's connected in bootstrap
|
||||
if (!$redis) {
|
||||
echo "No redis\n"; exit;
|
||||
}
|
||||
$redis->geoadd('geo:rides:waiting', 36.0, 32.0, 'test_ride');
|
||||
$res = $redis->georadius('geo:rides:waiting', 36.0, 32.0, 10, 'km', ['WITHDIST' => true]);
|
||||
print_r($res);
|
||||
echo json_encode($res) . "\n";
|
||||
@@ -37,5 +37,6 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Error: " . $e->getMessage());
|
||||
error_log("[deleteCaptain.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
@@ -24,7 +24,7 @@ try {
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// Handle any SQL errors
|
||||
jsonError("Error deleting records: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -51,5 +51,6 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Error searching driver: " . $e->getMessage());
|
||||
error_log("[find_driver_by_phone.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
@@ -23,5 +23,6 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Error removing from blacklist: " . $e->getMessage());
|
||||
error_log("[remove_from_blacklist.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
@@ -72,6 +72,7 @@ try {
|
||||
jsonError("No records updated or driver not found.");
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Error updating record: " . $e->getMessage());
|
||||
error_log("[updateDriverFromAdmin.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../connect.php';
|
||||
|
||||
// استلام البيانات من الطلب
|
||||
// Allow any authenticated user to report errors, but validate input
|
||||
$error = filterRequest("error");
|
||||
$userId = filterRequest("userId");
|
||||
$userType = filterRequest("userType");
|
||||
@@ -9,8 +9,14 @@ $phone = filterRequest("phone");
|
||||
$device = filterRequest("device");
|
||||
$details = filterRequest("details");
|
||||
|
||||
// تسجيل الخطأ في ملف logs/app.log للمتابعة السريعة
|
||||
$logMsg = "[$userType ID: $userId] Error: $error | Where: $device | Details: $details";
|
||||
// Sanitize log input to prevent log injection
|
||||
$safeError = str_replace(["\r", "\n"], ' ', substr($error ?? '', 0, 500));
|
||||
$safeUserId = str_replace(["\r", "\n"], ' ', substr($userId ?? '', 0, 50));
|
||||
$safeUserType = str_replace(["\r", "\n"], ' ', substr($userType ?? '', 0, 50));
|
||||
$safeDevice = str_replace(["\r", "\n"], ' ', substr($device ?? '', 0, 200));
|
||||
$safeDetails = str_replace(["\r", "\n"], ' ', substr($details ?? '', 0, 1000));
|
||||
|
||||
$logMsg = "[$safeUserType ID: $safeUserId] Error: $safeError | Where: $safeDevice | Details: $safeDetails";
|
||||
appLog($logMsg, "APP_ERROR");
|
||||
|
||||
// جملة SQL لإدخال البيانات، مع إضافة الحقل الجديد
|
||||
|
||||
@@ -31,7 +31,9 @@ try {
|
||||
echo "The token does not have an expiration time.\n";
|
||||
}
|
||||
} catch (Facebook\Exceptions\FacebookResponseException $e) {
|
||||
echo 'Graph API Error: ' . $e->getMessage();
|
||||
error_log("[facebook.php] Graph API Error: " . $e->getMessage());
|
||||
echo 'An error occurred while fetching Facebook data';
|
||||
} catch (Facebook\Exceptions\FacebookSDKException $e) {
|
||||
echo 'SDK Error: ' . $e->getMessage();
|
||||
error_log("[facebook.php] SDK Error: " . $e->getMessage());
|
||||
echo 'An error occurred while processing Facebook data';
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
function normalize_phone($s) { return preg_replace('/\D+/', '', (string)$s); }
|
||||
|
||||
$id = filterRequest("id"); // أو
|
||||
@@ -48,5 +54,5 @@ try {
|
||||
jsonSuccess(null, "Passenger deleted and blacklisted");
|
||||
} catch (Throwable $e) {
|
||||
$con->rollBack();
|
||||
jsonError("Failed: ".$e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = filterRequest("id"); // مفضّل
|
||||
|
||||
@@ -9,38 +13,41 @@ $first_name = filterRequest("first_name");
|
||||
$last_name = filterRequest("last_name");
|
||||
$new_phone = filterRequest("phone");
|
||||
|
||||
if (empty($id) ) { jsonError("Provide id or phone_lookup"); exit; }
|
||||
if (empty($id)) { jsonError("Passenger ID is required"); exit; }
|
||||
if ($first_name === null && $last_name === null && $new_phone === null) {
|
||||
jsonError("Nothing to update"); exit;
|
||||
}
|
||||
|
||||
$sets = [];
|
||||
$params = [];
|
||||
$new_phone = $encryptionHelper->encryptData($new_phone);
|
||||
$first_name = $encryptionHelper->encryptData($first_name);
|
||||
$last_name = $encryptionHelper->encryptData($last_name);
|
||||
|
||||
$enc_norm = $encryptionHelper->encryptData($norm);
|
||||
if ($first_name !== null) { $sets[] = "first_name = :first_name"; $params['first_name'] = trim($first_name); }
|
||||
if ($last_name !== null) { $sets[] = "last_name = :last_name"; $params['last_name'] = trim($last_name); }
|
||||
if ($first_name !== null) {
|
||||
$encFirst = $encryptionHelper->encryptData($first_name);
|
||||
$sets[] = "first_name = :first_name";
|
||||
$params['first_name'] = trim($encFirst);
|
||||
}
|
||||
if ($last_name !== null) {
|
||||
$encLast = $encryptionHelper->encryptData($last_name);
|
||||
$sets[] = "last_name = :last_name";
|
||||
$params['last_name'] = trim($encLast);
|
||||
}
|
||||
if ($new_phone !== null) {
|
||||
$encPhone = $encryptionHelper->encryptData($new_phone);
|
||||
$sets[] = "phone = :phone";
|
||||
$params['phone'] = trim($new_phone);
|
||||
$params['phone'] = trim($encPhone);
|
||||
|
||||
// منع تكرار الهاتف على راكب آخر
|
||||
$q = $con->prepare("SELECT id FROM passengers WHERE phone = :ph LIMIT 1");
|
||||
$q->execute(['ph' => $params['phone']]);
|
||||
$row = $q->fetch(PDO::FETCH_ASSOC);
|
||||
if ($row) {
|
||||
if (!empty($id) && $row['id'] != $id) { jsonError("Phone already used by another passenger"); exit; }
|
||||
if (empty($id) && $row['id'] != $phoneLookup) { jsonError("Phone already used by another passenger"); exit; }
|
||||
if ($row && $row['id'] != $id) {
|
||||
jsonError("Phone already used by another passenger");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$whereSql = "";
|
||||
$whereParams = [];
|
||||
if (!empty($id)) { $whereSql = "id = :pid"; $whereParams['pid'] = $id; }
|
||||
else { $whereSql = "phone = :plk"; $whereParams['plk'] = $phoneLookup; }
|
||||
$whereSql = "id = :pid";
|
||||
$whereParams = ['pid' => $id];
|
||||
|
||||
$sql = "UPDATE passengers SET ".implode(", ", $sets).", updated_at = CURRENT_TIMESTAMP WHERE $whereSql";
|
||||
$stmt = $con->prepare($sql);
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* تطبيع رقم الهاتف ليتوافق مع التخزين في قاعدة البيانات
|
||||
*/
|
||||
@@ -174,5 +180,5 @@ try {
|
||||
|
||||
} catch (Throwable $e) {
|
||||
error_log("[get_last_ride] Exception: " . $e->getMessage());
|
||||
jsonError("Error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
@@ -84,5 +84,5 @@ try {
|
||||
jsonSuccess(['ride' => $ride, 'message' => 'Status updated']);
|
||||
} catch (Throwable $e) {
|
||||
if ($con->inTransaction()) $con->rollBack();
|
||||
jsonError("Error: ".$e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
@@ -45,6 +45,7 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database Error: " . $e->getMessage());
|
||||
error_log("[get_driver_live_pos.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
@@ -104,6 +104,7 @@ try {
|
||||
jsonSuccess($data);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database Error: " . $e->getMessage());
|
||||
error_log("[get_rides_by_status.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
@@ -1,6 +1,12 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* تطبيع رقم الهاتف ليتوافق مع التخزين في قاعدة البيانات
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
// File: send_whatsapp_message.php
|
||||
// هذا السكربت يرسل رسالة واتساب فقط باستخدام RaseelPlus API
|
||||
|
||||
require_once __DIR__ . '/../connect.php'; // فقط إذا كنت تحتاج للوصول إلى environment
|
||||
require_once __DIR__ . '/../connect.php';
|
||||
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
error_log("--- [send_whatsapp_message.php] Script execution started ---");
|
||||
|
||||
@@ -16,6 +22,18 @@ if (empty($receiver) || empty($message)) {
|
||||
exit();
|
||||
}
|
||||
|
||||
// Validate phone number format (basic international format)
|
||||
if (!preg_match('/^\+?[1-9]\d{6,14}$/', $receiver)) {
|
||||
jsonError('Invalid phone number format.');
|
||||
exit();
|
||||
}
|
||||
|
||||
// Limit message length to prevent abuse
|
||||
if (strlen($message) > 4096) {
|
||||
jsonError('Message too long. Maximum 4096 characters.');
|
||||
exit();
|
||||
}
|
||||
|
||||
// بيانات Raseel
|
||||
$instanceId = getenv("RASEEL_DRIVER_INSTANCE_ID");
|
||||
$accessToken = getenv("RASEEL_DRIVER_ACCESS_TOKEN");
|
||||
|
||||
@@ -38,6 +38,7 @@ try {
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
error_log("[driver_ranking.php] " . $e->getMessage());
|
||||
echo json_encode(['status' => 'error', 'message' => 'An internal error occurred']);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -53,6 +53,7 @@ try {
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
error_log("[growth.php] " . $e->getMessage());
|
||||
echo json_encode(['status' => 'error', 'message' => 'An internal error occurred']);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -47,6 +47,7 @@ try {
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
error_log("[revenue.php] " . $e->getMessage());
|
||||
echo json_encode(['status' => 'error', 'message' => 'An internal error occurred']);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -39,6 +39,7 @@ try {
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
error_log("[settlements.php] " . $e->getMessage());
|
||||
echo json_encode(['status' => 'error', 'message' => 'An internal error occurred']);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -29,6 +29,7 @@ try {
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
error_log("[stats.php] " . $e->getMessage());
|
||||
echo json_encode(['status' => 'error', 'message' => 'An internal error occurred']);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -97,6 +97,7 @@ try {
|
||||
jsonError("Invalid action_type", 400);
|
||||
|
||||
} catch (Exception $e) {
|
||||
jsonError("Blacklist action failed: " . $e->getMessage(), 500);
|
||||
error_log("[blacklist_manager.php] " . $e->getMessage());
|
||||
jsonError("Blacklist action failed. Please try again later.", 500);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -100,6 +100,7 @@ try {
|
||||
jsonSuccess($scorecard);
|
||||
|
||||
} catch (Exception $e) {
|
||||
jsonError("Failed to fetch scorecard: " . $e->getMessage(), 500);
|
||||
error_log("[driver_scorecard.php] " . $e->getMessage());
|
||||
jsonError("Failed to fetch scorecard. Please try again later.", 500);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -57,6 +57,7 @@ try {
|
||||
echo json_encode($response);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
error_log("[realtime_dashboard.php] " . $e->getMessage());
|
||||
echo json_encode(['status' => 'error', 'message' => 'An internal error occurred']);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -72,6 +72,7 @@ try {
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
error_log("[smart_alerts.php] " . $e->getMessage());
|
||||
echo json_encode(['status' => 'error', 'message' => 'An internal error occurred']);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -5,13 +5,16 @@ header('Content-Type: application/json');
|
||||
|
||||
uploadLog("🚀 [EgyptDocuments/uploadEgyptIdBack.php] Egyptian ID back upload started.");
|
||||
|
||||
$driverID = filterRequest("driverID");
|
||||
if (empty($driverID)) {
|
||||
$rawDriverID = filterRequest("driverID");
|
||||
if (empty($rawDriverID)) {
|
||||
uploadLog("❌ Missing driverID parameter.", 'ERROR');
|
||||
jsonError("driverID is required.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// منع path traversal
|
||||
$driverID = basename($rawDriverID);
|
||||
|
||||
if (isset($_FILES['image'])) {
|
||||
uploadLog("$_FILES['image'] metadata", 'INFO', [
|
||||
'name' => $_FILES['image']['name'] ?? 'unknown',
|
||||
@@ -33,19 +36,16 @@ if (!isset($_FILES['image']) || $_FILES['image']['error'] !== UPLOAD_ERR_OK) {
|
||||
$image_file = $_FILES['image'];
|
||||
$allowed_extensions = ['jpg', 'jpeg', 'png'];
|
||||
|
||||
// Get file information
|
||||
$image_name = $image_file['name'];
|
||||
$image_size = $image_file['size'];
|
||||
$image_extension = strtolower(pathinfo($image_name, PATHINFO_EXTENSION));
|
||||
|
||||
// Validate file extension
|
||||
if (!in_array($image_extension, $allowed_extensions, true)) {
|
||||
uploadLog("❌ Invalid image format extension: .$image_extension", 'ERROR');
|
||||
jsonError("Invalid image format");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validate MIME type
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime_type = finfo_file($finfo, $image_file['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
@@ -57,29 +57,25 @@ if (!in_array($mime_type, $allowed_mime_types, true)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Generate a unique filename using driverID
|
||||
$new_filename = $driverID . '.' . $image_extension;
|
||||
|
||||
// Set target directory for uploads
|
||||
$target_dir = __DIR__ . "/card_image/";
|
||||
if (!is_dir($target_dir)) {
|
||||
mkdir($target_dir, 0755, true);
|
||||
}
|
||||
|
||||
// Construct target file path
|
||||
$target_file = $target_dir . $new_filename;
|
||||
|
||||
// Move the image file to the target location
|
||||
if (!move_uploaded_file($image_file['tmp_name'], $target_file)) {
|
||||
uploadLog("❌ Failed to save image to target file: $target_file", 'ERROR');
|
||||
jsonError("Failed to save image");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Resolve dynamic URL
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'api.siromove.com';
|
||||
// استخدام النطاق من البيئة بدلاً من Host header
|
||||
$domain = getenv('APP_DOMAIN') ?: 'api.siromove.com';
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http";
|
||||
$image_url = "$protocol://$host/siro/EgyptDocuments/card_image/" . $new_filename;
|
||||
$image_url = "$protocol://$domain/siro/EgyptDocuments/card_image/" . $new_filename;
|
||||
|
||||
uploadLog("✅ Egypt ID back uploaded successfully. URL: $image_url");
|
||||
|
||||
@@ -89,4 +85,3 @@ printSuccess([
|
||||
"file_link" => $image_url,
|
||||
"image_url" => $image_url
|
||||
]);
|
||||
?>
|
||||
|
||||
@@ -5,13 +5,16 @@ header('Content-Type: application/json');
|
||||
|
||||
uploadLog("🚀 [EgyptDocuments/uploadEgyptidFront.php] Egyptian ID front upload started.");
|
||||
|
||||
$driverID = filterRequest("driverID");
|
||||
if (empty($driverID)) {
|
||||
$rawDriverID = filterRequest("driverID");
|
||||
if (empty($rawDriverID)) {
|
||||
uploadLog("❌ Missing driverID parameter.", 'ERROR');
|
||||
jsonError("driverID is required.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// منع path traversal
|
||||
$driverID = basename($rawDriverID);
|
||||
|
||||
if (isset($_FILES['image'])) {
|
||||
uploadLog("$_FILES['image'] metadata", 'INFO', [
|
||||
'name' => $_FILES['image']['name'] ?? 'unknown',
|
||||
@@ -33,19 +36,16 @@ if (!isset($_FILES['image']) || $_FILES['image']['error'] !== UPLOAD_ERR_OK) {
|
||||
$image_file = $_FILES['image'];
|
||||
$allowed_extensions = ['jpg', 'jpeg', 'png'];
|
||||
|
||||
// Get file information
|
||||
$image_name = $image_file['name'];
|
||||
$image_size = $image_file['size'];
|
||||
$image_extension = strtolower(pathinfo($image_name, PATHINFO_EXTENSION));
|
||||
|
||||
// Validate file extension
|
||||
if (!in_array($image_extension, $allowed_extensions, true)) {
|
||||
uploadLog("❌ Invalid image format extension: .$image_extension", 'ERROR');
|
||||
jsonError("Invalid image format");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validate MIME type
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mime_type = finfo_file($finfo, $image_file['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
@@ -57,29 +57,25 @@ if (!in_array($mime_type, $allowed_mime_types, true)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Generate a unique filename using driverID
|
||||
$new_filename = $driverID . '.' . $image_extension;
|
||||
|
||||
// Set target directory for uploads
|
||||
$target_dir = __DIR__ . "/egypt/idFront/";
|
||||
if (!is_dir($target_dir)) {
|
||||
mkdir($target_dir, 0755, true);
|
||||
}
|
||||
|
||||
// Construct target file path
|
||||
$target_file = $target_dir . $new_filename;
|
||||
|
||||
// Move the image file to the target location
|
||||
if (!move_uploaded_file($image_file['tmp_name'], $target_file)) {
|
||||
uploadLog("❌ Failed to save image to target file: $target_file", 'ERROR');
|
||||
jsonError("Failed to save image");
|
||||
exit;
|
||||
}
|
||||
|
||||
// Resolve dynamic URL
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'api.siromove.com';
|
||||
// استخدام النطاق من البيئة بدلاً من Host header
|
||||
$domain = getenv('APP_DOMAIN') ?: 'api.siromove.com';
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http";
|
||||
$image_url = "$protocol://$host/siro/EgyptDocuments/egypt/idFront/" . $new_filename;
|
||||
$image_url = "$protocol://$domain/siro/EgyptDocuments/egypt/idFront/" . $new_filename;
|
||||
|
||||
uploadLog("✅ Egypt ID front uploaded successfully. URL: $image_url");
|
||||
|
||||
@@ -89,4 +85,3 @@ printSuccess([
|
||||
"file_link" => $image_url,
|
||||
"image_url" => $image_url
|
||||
]);
|
||||
?>
|
||||
|
||||
@@ -46,7 +46,7 @@ if (!move_uploaded_file($file['tmp_name'], $uploadPath)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'api-syria.siromove.com';
|
||||
$host = getenv('APP_DOMAIN') ?: 'api-syria.siromove.com';
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http";
|
||||
$imageUrl = "$protocol://$host/siro/auth/uploads/documents/" . $uniqueName ;
|
||||
$imageData = file_get_contents($uploadPath);
|
||||
|
||||
@@ -6,8 +6,23 @@ $email = filterRequest('email');
|
||||
$phone = filterRequest('phone');
|
||||
$password = filterRequest('password');
|
||||
|
||||
// Hash the password
|
||||
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
|
||||
if (empty($phone) && empty($email)) {
|
||||
echo json_encode(["status" => "Failure", "data" => "Phone or email is required."]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Build WHERE dynamically: support phone-only, email-only, or both
|
||||
$conditions = [];
|
||||
$params = [':password' => $password];
|
||||
if (!empty($phone)) {
|
||||
$conditions[] = "passengers.phone = :phone";
|
||||
$params[':phone'] = $phone;
|
||||
}
|
||||
if (!empty($email)) {
|
||||
$conditions[] = "passengers.email = :email";
|
||||
$params[':email'] = $email;
|
||||
}
|
||||
$where = implode(' OR ', $conditions);
|
||||
|
||||
$sql = "SELECT
|
||||
passengers.`id`,
|
||||
@@ -29,11 +44,9 @@ FROM
|
||||
`passengers`
|
||||
LEFT JOIN email_verifications ON email_verifications.email = passengers.email
|
||||
WHERE
|
||||
passengers.phone = :phone AND passengers.email = :email ";
|
||||
$where";
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindParam(':email', $email);
|
||||
$stmt->bindParam(':phone', $phone);
|
||||
$stmt->execute();
|
||||
$stmt->execute($params);
|
||||
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$count = $stmt->rowCount();
|
||||
|
||||
@@ -55,13 +68,11 @@ if ($count > 0) {
|
||||
// jsonError("Incorrect password.");
|
||||
}
|
||||
} else {
|
||||
// The user does not exist
|
||||
echo json_encode([
|
||||
"status" => "Failure",
|
||||
"data" => "User does not exist."
|
||||
"data" => "Invalid credentials."
|
||||
]);
|
||||
// jsonError("User does not exist.");
|
||||
}
|
||||
$conn->close();
|
||||
$con = null;
|
||||
|
||||
?>
|
||||
|
||||
@@ -18,17 +18,7 @@ if (empty($receiver)) {
|
||||
|
||||
$user_type = filterRequest("user_type");
|
||||
|
||||
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? (function_exists('apache_request_headers') ? (apache_request_headers()['Authorization'] ?? null) : null);
|
||||
if (!empty($authHeader) && preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
|
||||
$jwtToken = $matches[1];
|
||||
$tokenParts = explode('.', $jwtToken);
|
||||
if (count($tokenParts) === 3) {
|
||||
$payload = json_decode(base64_decode($tokenParts[1]), true);
|
||||
if (isset($payload['role'])) {
|
||||
$user_type = $payload['role'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// user_type is taken from request only (JWT not trusted without signature verification)
|
||||
|
||||
$country = filterRequest("country"); // Egypt | Syria | Jordan
|
||||
$method = filterRequest("method"); // whatsapp | sms | voice | flash_call | bearer_send
|
||||
|
||||
@@ -7,7 +7,7 @@ require_once __DIR__ . '/../../functions.php';
|
||||
|
||||
// 0. Rate Limiting: 3 محاولات OTP كل 5 دقائق لكل IP
|
||||
$rateLimiter = new RateLimiter($redis);
|
||||
$rateLimiter->enforce(RateLimiter::identifier(), 'otp');
|
||||
$rateLimiter->enforce(RateLimiter::identifier(), 'otp_verify');
|
||||
|
||||
// 1. Fetch input parameters
|
||||
$phone_number = filterRequest("phone_number");
|
||||
@@ -23,17 +23,7 @@ if (empty($token_code)) {
|
||||
$user_type = filterRequest("user_type");
|
||||
$context = filterRequest("context"); // token_change | login (default)
|
||||
|
||||
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? (function_exists('apache_request_headers') ? (apache_request_headers()['Authorization'] ?? null) : null);
|
||||
if (!empty($authHeader) && preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
|
||||
$jwtToken = $matches[1];
|
||||
$tokenParts = explode('.', $jwtToken);
|
||||
if (count($tokenParts) === 3) {
|
||||
$payload = json_decode(base64_decode($tokenParts[1]), true);
|
||||
if (isset($payload['role'])) {
|
||||
$user_type = $payload['role'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// user_type is taken from request only (JWT not trusted without signature verification)
|
||||
|
||||
if (empty($phone_number)) {
|
||||
jsonError("Phone number is required.");
|
||||
@@ -75,7 +65,7 @@ try {
|
||||
if ($user_type === 'admin') {
|
||||
$sql = "SELECT * FROM token_verification_admin
|
||||
WHERE phone_number = :phone AND token = :token
|
||||
AND expiration_time >= NOW()";
|
||||
AND expiration_time >= NOW() AND verified = 0";
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':token', $encryptedToken, PDO::PARAM_STR);
|
||||
@@ -103,7 +93,7 @@ try {
|
||||
} elseif ($user_type === 'service') {
|
||||
$sql = "SELECT `id` FROM `phone_verification_service`
|
||||
WHERE `phone_number` = :phone AND `token_code` = :token
|
||||
AND `expiration_time` > NOW()";
|
||||
AND `expiration_time` > NOW() AND `is_verified` = 0";
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||
$stmt->bindParam(':token', $encryptedToken, PDO::PARAM_STR);
|
||||
@@ -124,7 +114,7 @@ try {
|
||||
$sql = "SELECT `id` FROM `token_verification_driver`
|
||||
WHERE `phone_number` = :phone
|
||||
AND `token` = :token
|
||||
AND `expiration_time` > NOW()";
|
||||
AND `expiration_time` > NOW() AND `verified` = 0";
|
||||
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||
@@ -147,7 +137,7 @@ try {
|
||||
$sql = "SELECT `id` FROM `phone_verification`
|
||||
WHERE `phone_number` = :phone
|
||||
AND `token_code` = :token
|
||||
AND `expiration_time` > NOW()";
|
||||
AND `expiration_time` > NOW() AND `is_verified` = 0";
|
||||
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||
@@ -172,7 +162,7 @@ try {
|
||||
$sql = "SELECT `id` FROM `token_verification`
|
||||
WHERE `phone_number` = :phone
|
||||
AND `token` = :token
|
||||
AND `expiration_time` > NOW()";
|
||||
AND `expiration_time` > NOW() AND `verified` = 0";
|
||||
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||
@@ -195,7 +185,7 @@ try {
|
||||
$sql = "SELECT `id` FROM `phone_verification_passenger`
|
||||
WHERE `phone_number` = :phone
|
||||
AND `token` = :token
|
||||
AND `expiration_time` > NOW()";
|
||||
AND `expiration_time` > NOW() AND `verified` = 0";
|
||||
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||
|
||||
@@ -11,7 +11,24 @@ $password = filterRequest("password");
|
||||
$gender = filterRequest("gender");
|
||||
$birthdate = filterRequest("birthdate");
|
||||
$site = filterRequest("site");
|
||||
$id = filterRequest("id");
|
||||
|
||||
// --- Input Validation ---
|
||||
if (empty($phone) || strlen(preg_replace('/\D+/', '', $phone)) < 8) {
|
||||
jsonError("Valid phone number is required.");
|
||||
exit;
|
||||
}
|
||||
if (!empty($email) && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
jsonError("Valid email address is required.");
|
||||
exit;
|
||||
}
|
||||
if (empty($password) || strlen($password) < 6) {
|
||||
jsonError("Password must be at least 6 characters.");
|
||||
exit;
|
||||
}
|
||||
if (empty($first_name) || empty($last_name)) {
|
||||
jsonError("First name and last name are required.");
|
||||
exit;
|
||||
}
|
||||
|
||||
// تشفير البيانات الحساسة
|
||||
$phone = $encryptionHelper->encryptData($phone);
|
||||
@@ -39,14 +56,13 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
// إدخال البيانات الجديدة
|
||||
// إدخال البيانات الجديدة (مع ID تلقائي)
|
||||
$sql = "INSERT INTO passengers (
|
||||
id, phone, email, password, gender, birthdate, site, first_name, last_name
|
||||
) VALUES (
|
||||
:id, :phone, :email, :password, :gender, :birthdate, :site, :first_name, :last_name
|
||||
UUID_SHORT(), :phone, :email, :password, :gender, :birthdate, :site, :first_name, :last_name
|
||||
)";
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindParam(":id", $id);
|
||||
$stmt->bindParam(":phone", $phone);
|
||||
$stmt->bindParam(":email", $email);
|
||||
$stmt->bindParam(":password", $hashedPassword);
|
||||
|
||||
@@ -16,7 +16,7 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'api-syria.siromove.com';
|
||||
$host = getenv('APP_DOMAIN') ?: 'api-syria.siromove.com';
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http";
|
||||
$PUBLIC_BASE = "$protocol://$host/siro/auth/uploads/documents";
|
||||
|
||||
@@ -230,7 +230,7 @@ Therefore, do NOT assume a specific field is on the front or the back of a card.
|
||||
$urlHost = parse_url($url, PHP_URL_HOST);
|
||||
$allowed = false;
|
||||
foreach ($allowedHosts as $host) {
|
||||
if ($host && str_ends_with($urlHost, $host)) {
|
||||
if ($host && $urlHost === $host) {
|
||||
$allowed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ const MAX_FILE_MB = 5;
|
||||
const ALLOWED_MIMES = ['image/jpeg','image/png','image/webp']; // فقط صور
|
||||
const UPLOAD_ROOT = __DIR__ . "/../../private_uploads"; // مجلد خاص (غير عام)
|
||||
const SIGN_SECRET = getenv('SECRET_KEY_HMAC'); // غيّرها واقرأها من .env
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'api-syria.siromove.com';
|
||||
$host = getenv('APP_DOMAIN') ?: 'api-syria.siromove.com';
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http";
|
||||
define('PUBLIC_BASE', "$protocol://$host/siro");
|
||||
const SIGNED_TTL_SEC = 172800; // 2 days = 60*60*24
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
require_once __DIR__ . '/../../../connect.php';
|
||||
|
||||
/* 1) توليد رمز التحقق (3 خانات) --------------------------------------------------- */
|
||||
$otp = (string)rand(100, 999);
|
||||
$otp = (string)random_int(100, 999);
|
||||
$receiver = filterRequest("receiver");
|
||||
|
||||
if (empty($receiver)) {
|
||||
@@ -69,19 +69,19 @@ if ($sentOK) {
|
||||
");
|
||||
$stmt->execute([$receiver_enc, $otp_enc, $exp, $now]);
|
||||
|
||||
// Also save to Redis for verify_otp compatibility
|
||||
if ($redis) {
|
||||
$redis->setex("otp:driver:$receiver", 300, $otp);
|
||||
}
|
||||
|
||||
jsonSuccess(null, 'OTP sent and saved successfully');
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_log("[send_otp_driver.php] " . $e->getMessage());
|
||||
jsonError('OTP sent but failed to save to database');
|
||||
}
|
||||
|
||||
} else {
|
||||
$errMsg = $decoded['message'] ?? 'Unknown error';
|
||||
jsonError('Failed to send OTP: ' . $errMsg);
|
||||
jsonError('Failed to send OTP');
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
* أبقينا callAPI() فقط إذا كان يُستخدم في ملفات أخرى – احذفه إن شئت.
|
||||
* --------------------------------------------------------------------- */
|
||||
function callAPI($method, $url, $data) { /* … */ }
|
||||
?>
|
||||
@@ -77,5 +77,6 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_log("[verify_otp_driver.php] " . $e->getMessage());
|
||||
jsonError("Database error occurred.");
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
/* 1) توليد رمز التحقق (3 خانات) */
|
||||
$otp = (string)rand(100, 999);
|
||||
$otp = (string)random_int(100, 999);
|
||||
$receiver = filterRequest("receiver");
|
||||
|
||||
if (empty($receiver)) {
|
||||
@@ -50,7 +50,7 @@ $decoded = json_decode((string)$res, true);
|
||||
$sentOK = ($httpCode === 200 && ($decoded['success'] ?? false));
|
||||
|
||||
if ($sentOK) {
|
||||
/* 3) تشفير البيانات وحفظ الرمز في قاعدة البيانات */
|
||||
/* 3) حفظ الرمز في Redis + قاعدة البيانات */
|
||||
$receiver_enc = $encryptionHelper->encryptData($receiver);
|
||||
$otp_enc = $encryptionHelper->encryptData($otp);
|
||||
|
||||
@@ -58,6 +58,7 @@ if ($sentOK) {
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
try {
|
||||
// Save to MySQL
|
||||
$con->prepare("DELETE FROM token_verification WHERE phone_number = ?")
|
||||
->execute([$receiver_enc]);
|
||||
|
||||
@@ -68,19 +69,20 @@ if ($sentOK) {
|
||||
");
|
||||
$stmt->execute([$receiver_enc, $otp_enc, $exp, $now]);
|
||||
|
||||
// Also save to Redis for verify_otp.php compatibility
|
||||
if ($redis) {
|
||||
$redis->setex("otp:passenger:$receiver", 300, $otp);
|
||||
}
|
||||
|
||||
jsonSuccess(null, 'OTP sent and saved successfully');
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_log("[send_otp.php] " . $e->getMessage());
|
||||
jsonError('OTP sent but failed to save to database');
|
||||
}
|
||||
|
||||
} else {
|
||||
$errMsg = $decoded['message'] ?? 'Unknown error';
|
||||
jsonError('Failed to send OTP: ' . $errMsg);
|
||||
jsonError('Failed to send OTP');
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------
|
||||
* يمكن حذف callAPI() تمامًا إن لم يعد مستخدمًا في أي ملف آخر.
|
||||
* ---------------------------------------------------------------- */
|
||||
function callAPI($method, $url, $data) { /* … (أبقِها أو احذفها) */ }
|
||||
?>
|
||||
@@ -30,7 +30,7 @@ try {
|
||||
|
||||
$cachedOtp = $redis->get("otp:passenger:$phoneNumber");
|
||||
|
||||
if ($cachedOtp && $cachedOtp == $otp) {
|
||||
if ($cachedOtp && $cachedOtp === $otp) {
|
||||
// ننجح في التحقق ونحذف المفتاح من Redis لمنع استخدامه مرة أخرى (One-time use)
|
||||
$redis->del("otp:passenger:$phoneNumber");
|
||||
|
||||
|
||||
@@ -64,14 +64,25 @@ class EncryptionHelper
|
||||
}
|
||||
|
||||
// ─── تشفير/فك تشفير Binary (صور، ملفات) ───────────────
|
||||
// تُستخدم الـ GCM مع IV عشوائي (كما في encryptData)
|
||||
public function encryptBinary(string $data): string
|
||||
{
|
||||
return openssl_encrypt($data, self::ALGO_CBC, $this->key, OPENSSL_RAW_DATA, $this->cbcIv);
|
||||
$iv = random_bytes(self::IV_LEN_GCM);
|
||||
$tag = '';
|
||||
$encrypted = openssl_encrypt($data, self::ALGO_GCM, $this->key, OPENSSL_RAW_DATA, $iv, $tag, "", self::TAG_LEN);
|
||||
return base64_encode($iv . $tag . $encrypted);
|
||||
}
|
||||
|
||||
public function decryptBinary(string $data): string|false
|
||||
{
|
||||
return openssl_decrypt($data, self::ALGO_CBC, $this->key, OPENSSL_RAW_DATA, $this->cbcIv);
|
||||
$raw = base64_decode($data, true);
|
||||
if ($raw === false || strlen($raw) < self::IV_LEN_GCM + self::TAG_LEN) return false;
|
||||
|
||||
$iv = substr($raw, 0, self::IV_LEN_GCM);
|
||||
$tag = substr($raw, self::IV_LEN_GCM, self::TAG_LEN);
|
||||
$cipher = substr($raw, self::IV_LEN_GCM + self::TAG_LEN);
|
||||
|
||||
return openssl_decrypt($cipher, self::ALGO_GCM, $this->key, OPENSSL_RAW_DATA, $iv, $tag);
|
||||
}
|
||||
|
||||
// --------- دوال الـ Padding للـ CBC ----------
|
||||
|
||||
@@ -20,10 +20,7 @@ if ($debugMode) {
|
||||
ini_set('log_errors', '1');
|
||||
|
||||
// تحديد مسار اللوج بشكل ديناميكي (محلياً أو سيرفر)
|
||||
$logPath = '/home/siro-api/logs/php_errors.log';
|
||||
if (!file_exists(dirname($logPath)) || !is_writable(dirname($logPath))) {
|
||||
$logPath = __DIR__ . '/../logs/php_errors.log';
|
||||
}
|
||||
$logPath = getenv('ERROR_LOG_PATH') ?: (__DIR__ . '/../logs/php_errors.log');
|
||||
ini_set('error_log', $logPath);
|
||||
|
||||
header_remove('X-Powered-By');
|
||||
@@ -37,7 +34,13 @@ header("Permissions-Policy: geolocation=(), microphone=(), camera=()");
|
||||
header("X-XSS-Protection: 1; mode=block");
|
||||
|
||||
|
||||
// CORS (يجب تخصيصه في endpoints مخصصة إن لزم، لكن هذا افتراضي)
|
||||
// CORS مع التحقق من المصدر المسموح
|
||||
$allowedOrigins = array_map('trim', explode(',', getenv('CORS_ALLOWED_ORIGINS') ?: 'https://siromove.com,https://admin.siromove.com'));
|
||||
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
|
||||
if (in_array($origin, $allowedOrigins)) {
|
||||
header("Access-Control-Allow-Origin: $origin");
|
||||
header('Access-Control-Allow-Credentials: true');
|
||||
}
|
||||
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Device-FP, X-HMAC-Auth, X-Internal-Key');
|
||||
|
||||
@@ -54,10 +57,7 @@ if ($vendorPath) require_once $vendorPath;
|
||||
require_once __DIR__ . '/helpers.php';
|
||||
|
||||
// تحديد مسار الـ .env بشكل ديناميكي
|
||||
$envFile = '/home/siro-api/env/.env';
|
||||
if (!file_exists($envFile)) {
|
||||
$envFile = __DIR__ . '/../.env'; // مسار محلي افتراضي
|
||||
}
|
||||
$envFile = getenv('ENV_FILE_PATH') ?: (__DIR__ . '/../.env');
|
||||
loadEnvironment($envFile);
|
||||
|
||||
// 4. Redis Connection (Singleton)
|
||||
|
||||
@@ -227,7 +227,7 @@ function getInternalSocketKey(): string
|
||||
if ($key) {
|
||||
return trim($key);
|
||||
}
|
||||
$path = getenv('INTERNAL_SOCKET_KEY_PATH') ?: '/home/siro-api/.internal_socket_key';
|
||||
$path = getenv('INTERNAL_SOCKET_KEY_PATH') ?: '';
|
||||
if (file_exists($path)) {
|
||||
return trim((string)@file_get_contents($path));
|
||||
}
|
||||
|
||||
@@ -115,5 +115,6 @@ try {
|
||||
$mail->send();
|
||||
jsonSuccess(null, "Email sent successfully");
|
||||
} catch (Exception $e) {
|
||||
error_log("[sendTripEmail.php] " . $e->getMessage());
|
||||
jsonError("Failed to send email: " . $mail->ErrorInfo);
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
require_once realpath(__DIR__ . '/../vendor/autoload.php');
|
||||
|
||||
require_once 'load_env.php';
|
||||
$env_file = '/home/siro-api/env/.env';
|
||||
$env_file = getenv('ENV_FILE_PATH') ?: (__DIR__ . '/../../../env/.env');
|
||||
loadEnvironment($env_file);
|
||||
|
||||
// ✅ FIX C-02: استخدام getenv بدلاً من file_get_contents الثابت
|
||||
@@ -49,8 +49,9 @@ class EncryptionHelper {
|
||||
public function encryptData($plainText) {
|
||||
$plainText = mb_convert_encoding($plainText, 'UTF-8');
|
||||
$paddedText = $this->addPadding($plainText);
|
||||
$encrypted = openssl_encrypt($paddedText, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $this->iv);
|
||||
return base64_encode($encrypted);
|
||||
$iv = random_bytes(16);
|
||||
$encrypted = openssl_encrypt($paddedText, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $iv);
|
||||
return base64_encode($iv . $encrypted);
|
||||
}
|
||||
|
||||
public function decryptData($encryptedText) {
|
||||
@@ -61,6 +62,22 @@ class EncryptionHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
// محاولة أولى: استخراج IV عشوائي من أول 16 بايت
|
||||
if (strlen($decoded) >= 16) {
|
||||
$iv = substr($decoded, 0, 16);
|
||||
$payload = substr($decoded, 16);
|
||||
|
||||
$decrypted = openssl_decrypt($payload, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $iv);
|
||||
|
||||
if ($decrypted !== false) {
|
||||
$pad = ord($decrypted[strlen($decrypted) - 1]);
|
||||
if ($pad >= 1 && $pad <= 16) {
|
||||
return substr($decrypted, 0, -$pad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// محاولة ثانية: IV ثابت (للبيانات القديمة)
|
||||
$decrypted = openssl_decrypt($decoded, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $this->iv);
|
||||
|
||||
if ($decrypted === false) {
|
||||
@@ -68,7 +85,6 @@ class EncryptionHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify padding is valid before removal
|
||||
$pad = ord($decrypted[strlen($decrypted) - 1]);
|
||||
if ($pad < 1 || $pad > 16) {
|
||||
error_log("[ERROR] Invalid padding value ($pad) for decrypted input: $encryptedText");
|
||||
@@ -95,13 +111,23 @@ class EncryptionHelper {
|
||||
return true;
|
||||
}
|
||||
public function encryptBinary($data) {
|
||||
$encrypted = openssl_encrypt($data, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $this->iv);
|
||||
return $encrypted;
|
||||
$iv = random_bytes(16);
|
||||
$encrypted = openssl_encrypt($data, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $iv);
|
||||
return $iv . $encrypted;
|
||||
}
|
||||
|
||||
public function decryptBinary($data) {
|
||||
if (strlen($data) >= 16) {
|
||||
$iv = substr($data, 0, 16);
|
||||
$payload = substr($data, 16);
|
||||
$decrypted = openssl_decrypt($payload, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $iv);
|
||||
if ($decrypted !== false) {
|
||||
return $decrypted;
|
||||
}
|
||||
}
|
||||
|
||||
// للبيانات القديمة ذات IV الثابت
|
||||
$decrypted = openssl_decrypt($data, 'AES-256-CBC', $this->key, OPENSSL_RAW_DATA, $this->iv);
|
||||
// CRIT-07 FIX: التحقق من فشل openssl_decrypt
|
||||
if ($decrypted === false) {
|
||||
error_log('[CRIT-07] openssl_decrypt failed in decryptBinary');
|
||||
throw new Exception('Decryption failed');
|
||||
|
||||
@@ -44,8 +44,7 @@ function isAllowedSocketUrl(string $url): bool {
|
||||
}
|
||||
|
||||
function sendToLocationServer($action, $data) {
|
||||
// رابط سيرفر اللوكيشن الداخلي أو العام
|
||||
$url = "http://188.68.36.205:2021";
|
||||
$url = getenv('LOCATION_SERVER_URL') ?: 'http://188.68.36.205:2021';
|
||||
if (!isAllowedSocketUrl($url)) {
|
||||
error_log("[SSRF_BLOCKED] Attempted connection to: $url");
|
||||
return;
|
||||
@@ -269,7 +268,7 @@ function notifyPassengerOnRideServer($passenger_id, $payload) {
|
||||
$INTERNAL_KEY = function_exists('getInternalSocketKey') ? getInternalSocketKey() : '';
|
||||
|
||||
if (empty($INTERNAL_KEY)) {
|
||||
error_log("[SOCKET_CRITICAL] Internal key missing at /home/siro-api/.internal_socket_key");
|
||||
error_log("[SOCKET_CRITICAL] Internal socket key missing");
|
||||
}
|
||||
|
||||
$postData = [
|
||||
|
||||
@@ -1,47 +1,24 @@
|
||||
<?php
|
||||
include 'connect.php';
|
||||
require_once __DIR__ . '/core/bootstrap.php';
|
||||
|
||||
// نضمن أن الرد دائماً JSON
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// 1) قراءة الـ body كـ JSON (من Flutter)
|
||||
// التحقق من صلاحية الأدمن عبر JWT
|
||||
$jwtService = new JwtService($redis ?? null);
|
||||
$admin = $jwtService->authenticate();
|
||||
if ($admin->role !== 'admin' && $admin->role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Unauthorized. Admin access required.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$raw = file_get_contents('php://input');
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
if (!is_array($data)) {
|
||||
// fallback لو أرسلت form-data أو x-www-form-urlencoded
|
||||
$data = $_POST;
|
||||
}
|
||||
|
||||
// 2) التحقق من رقم هاتف الأدمن المصرّح له
|
||||
|
||||
// قراءة الأرقام المسموح لها من الـ ENV
|
||||
$phonesRaw = getenv('ADMIN_PHONE_NUMBERS') ?: '';
|
||||
$ALLOWED_TOOL_PHONES = array_values(
|
||||
array_filter(
|
||||
array_map(function ($p) {
|
||||
// إزالة أي رموز غير رقمية (مسافات، +، - إلخ)
|
||||
return preg_replace('/\D+/', '', $p);
|
||||
}, explode(',', $phonesRaw))
|
||||
)
|
||||
);
|
||||
|
||||
// رقم الهاتف القادم من Flutter (parameter جديد)
|
||||
$adminPhoneParam = isset($data['admin_phone'])
|
||||
? preg_replace('/\D+/', '', $data['admin_phone'])
|
||||
: '';
|
||||
|
||||
// إذا لم يُرسل رقم أو لم يكن ضمن القائمة → منع الوصول
|
||||
if ($adminPhoneParam === '' || !in_array($adminPhoneParam, $ALLOWED_TOOL_PHONES, true)) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => 'Access denied for this admin phone.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 3) التحقق من بقية المدخلات (action + text)
|
||||
$action = $data['action'] ?? '';
|
||||
$text = trim($data['text'] ?? '');
|
||||
|
||||
@@ -54,13 +31,10 @@ if ($text === '' || ($action !== 'encrypt' && $action !== 'decrypt')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// 4) تنفيذ التشفير / الفك
|
||||
try {
|
||||
// require_once __DIR__ . '/encrypt_decrypt.php';
|
||||
|
||||
if ($action === 'encrypt') {
|
||||
$result = $encryptionHelper->encryptData($text);
|
||||
} else { // decrypt
|
||||
} else {
|
||||
$result = $encryptionHelper->decryptData($text);
|
||||
}
|
||||
|
||||
@@ -70,6 +44,7 @@ try {
|
||||
'result' => (string) $result,
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
error_log("[ggg.php] " . $e->getMessage());
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
|
||||
@@ -15,7 +15,6 @@ function loadEnvironment($env_file) {
|
||||
$value = trim($value, "\"'");
|
||||
putenv("$keyName=$value");
|
||||
$_ENV[$keyName] = $value;
|
||||
$_SERVER[$keyName] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,5 +19,6 @@ try {
|
||||
jsonSuccess(null, "Logged out successfully");
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log("[logout.php] " . $e->getMessage());
|
||||
jsonError("Logout failed", 500);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ ini_set('memory_limit', '512M');
|
||||
require_once realpath(__DIR__ . '/../vendor/autoload.php');
|
||||
require_once 'load_env.php';
|
||||
|
||||
$env_file = '/home/siro-api/env/.env';
|
||||
$env_file = getenv('ENV_FILE_PATH') ?: (__DIR__ . '/../../../env/.env');
|
||||
loadEnvironment($env_file);
|
||||
|
||||
include "encrypt_decrypt.php"; // لاستخدام $encryptionHelper
|
||||
|
||||
@@ -16,6 +16,6 @@ try {
|
||||
$con->exec($sql);
|
||||
echo "SUCCESS: passenger_opening_locations table created successfully.\n";
|
||||
} catch (Exception $e) {
|
||||
echo "ERROR: " . $e->getMessage() . "\n";
|
||||
echo "An internal error occurred" . "\n";
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -119,7 +119,9 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[selectDriverAndCarForMishwariTrip.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
} catch (Exception $e) {
|
||||
jsonError("Error: " . $e->getMessage());
|
||||
error_log("[selectDriverAndCarForMishwariTrip.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
@@ -1,12 +1,19 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
// استقبال المتغيرات
|
||||
$driverID = filterRequest("driverID");
|
||||
$passengerID = filterRequest("passengerID");
|
||||
// استقبال المتغيرات — force user IDs from JWT based on role
|
||||
$rideID = filterRequest("rideID");
|
||||
$note = filterRequest("note");
|
||||
|
||||
// Force driverID/passengerID from JWT based on user role
|
||||
if ($role === 'driver') {
|
||||
$driverID = $user_id;
|
||||
$passengerID = filterRequest("passengerID");
|
||||
} else {
|
||||
$passengerID = $user_id;
|
||||
$driverID = filterRequest("driverID");
|
||||
}
|
||||
|
||||
// تنفيذ الإدخال بطريقة آمنة
|
||||
$sql = "INSERT INTO `canecl` (`driverID`, `passengerID`, `rideID`, `note`)
|
||||
VALUES (:driverID, :passengerID, :rideID, :note)";
|
||||
|
||||
@@ -95,7 +95,7 @@ try {
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_log("❌ [cancelRideAndLog.php] Database Error: " . $e->getMessage());
|
||||
jsonError("Database Error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
*/
|
||||
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
@@ -144,7 +144,8 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("DB Error: " . $e->getMessage());
|
||||
error_log("[addCancelTripFromDriverAfterApplied.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
?>
|
||||
@@ -1,6 +1,12 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
// التحقق من أن المستخدم يملك هذا المعرف
|
||||
if ($role !== 'admin' && $role !== 'super_admin' && (string)$user_id !== (string)$driverID) {
|
||||
jsonError("Unauthorized: You can only add cars to your own account");
|
||||
exit;
|
||||
}
|
||||
|
||||
// استقبال القيم
|
||||
$driverID = filterRequest("driverID");
|
||||
$vin = $encryptionHelper->encryptData(filterRequest("vin"));
|
||||
|
||||
@@ -4,6 +4,23 @@ require_once __DIR__ . '/../../connect.php';
|
||||
// استقبال ID السجل
|
||||
$id = filterRequest("id");
|
||||
|
||||
// التحقق من أن السجل يخص المستخدم الحالي أو هو أدمن
|
||||
$checkSql = "SELECT driverID FROM captains_car WHERE id = :id LIMIT 1";
|
||||
$checkStmt = $con->prepare($checkSql);
|
||||
$checkStmt->bindParam(':id', $id, PDO::PARAM_INT);
|
||||
$checkStmt->execute();
|
||||
$record = $checkStmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$record) {
|
||||
jsonError("Record not found");
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($role !== 'admin' && $role !== 'super_admin' && (string)$user_id !== $record['driverID']) {
|
||||
jsonError("Unauthorized: You can only delete your own car registrations");
|
||||
exit;
|
||||
}
|
||||
|
||||
// حذف السجل من جدول captains_car (أو CarRegistration لو هو الصحيح فعلاً)
|
||||
$sql = "DELETE FROM captains_car WHERE id = :id";
|
||||
$stmt = $con->prepare($sql);
|
||||
|
||||
@@ -35,6 +35,7 @@ try {
|
||||
jsonSuccess($response);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[get_driver_behavior.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
@@ -43,6 +43,7 @@ try {
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database Error: " . $e->getMessage());
|
||||
error_log("[get.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
@@ -35,6 +35,7 @@ try {
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// Print error message
|
||||
jsonError($message = "Database error: " . $e->getMessage());
|
||||
error_log("[add.php] " . $e->getMessage());
|
||||
jsonError($message = "Database error occurred");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -32,6 +32,6 @@ try {
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
// إرجاع رسالة خطأ في حال حدوث مشكلة في قاعدة البيانات
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,21 +1,38 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
$sql = "SELECT * FROM `driverToken`";
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$page = max(1, (int) filterRequest('page'));
|
||||
$limit = 50;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$sql = "SELECT * FROM `driverToken` LIMIT :lim OFFSET :off";
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindValue(':lim', $limit, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':off', $offset, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// الحصول على العدد الإجمالي للصفحات
|
||||
$countStmt = $con->query("SELECT COUNT(*) FROM `driverToken`");
|
||||
$total = $countStmt->fetchColumn();
|
||||
|
||||
if ($data) {
|
||||
// فك تشفير token فقط لكل سجل
|
||||
foreach ($data as &$item) {
|
||||
$item['token'] = $encryptionHelper->decryptData($item['token']);
|
||||
// لا يتم فك تشفير fingerPrint لأنه مشفّر من Flutter
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'data' => $data
|
||||
'data' => $data,
|
||||
'total' => (int) $total,
|
||||
'page' => $page,
|
||||
'pages' => (int) ceil($total / $limit),
|
||||
]);
|
||||
} else {
|
||||
jsonError("No driver tokens found");
|
||||
|
||||
@@ -1,21 +1,37 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../../connect.php';
|
||||
|
||||
$sql = "SELECT * FROM `tokens`";
|
||||
if ($role !== 'admin' && $role !== 'super_admin') {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Unauthorized: Admin access required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$page = max(1, (int) filterRequest('page'));
|
||||
$limit = 50;
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$sql = "SELECT * FROM `tokens` LIMIT :lim OFFSET :off";
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->bindValue(':lim', $limit, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':off', $offset, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$countStmt = $con->query("SELECT COUNT(*) FROM `tokens`");
|
||||
$total = $countStmt->fetchColumn();
|
||||
|
||||
if ($data) {
|
||||
// فك تشفير token فقط
|
||||
foreach ($data as &$item) {
|
||||
$item['token'] = $encryptionHelper->decryptData($item['token']);
|
||||
// fingerPrint يبقى كما هو (مشفّر من التطبيق)
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'data' => $data
|
||||
'data' => $data,
|
||||
'total' => (int) $total,
|
||||
'page' => $page,
|
||||
'pages' => (int) ceil($total / $limit),
|
||||
]);
|
||||
} else {
|
||||
jsonError("No token records found");
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
<?php
|
||||
// send_fcm.php - FCM HTTP v1 Sender
|
||||
// send_fcm.php - FCM HTTP v1 Sender (Internal use only)
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// 🔐 Require internal API key for authentication
|
||||
$apiKey = $_SERVER['HTTP_X_API_KEY'] ?? '';
|
||||
$expectedKey = getenv('FCM_INTERNAL_API_KEY');
|
||||
if (empty($expectedKey) || !hash_equals($expectedKey, $apiKey)) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$serviceAccountFile = __DIR__ . '/service-account.json';
|
||||
|
||||
// السماح فقط بـ POST
|
||||
|
||||
@@ -99,6 +99,6 @@ try {
|
||||
$con->rollBack();
|
||||
}
|
||||
error_log("claimChallengeReward Error: " . $e->getMessage());
|
||||
jsonError("Failed to claim reward: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -115,6 +115,6 @@ try {
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_log("getGamificationDashboard Error: " . $e->getMessage());
|
||||
jsonError("Database error occurred: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -17,7 +17,12 @@ function generateUniqueCode($con) {
|
||||
}
|
||||
}
|
||||
|
||||
$driverId = filterRequest("driverId");
|
||||
// Force driverId from JWT — only drivers can manage invitations
|
||||
if ($role !== 'driver') {
|
||||
jsonError("Only drivers can create invitations");
|
||||
exit;
|
||||
}
|
||||
$driverId = $user_id;
|
||||
$inviterDriverPhone = filterRequest("inviterDriverPhone");
|
||||
|
||||
// 🔐 تشفير رقم الهاتف
|
||||
@@ -52,7 +57,8 @@ if ($checkStmt->rowCount() > 0) {
|
||||
"expirationTime" => $expirationTime
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[invitor/add] DB Error: " . $e->getMessage());
|
||||
jsonError("Database error occurred");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +89,8 @@ if ($checkStmt->rowCount() > 0) {
|
||||
jsonError("Failed to save invite data");
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[invitor/add] DB Error: " . $e->getMessage());
|
||||
jsonError("Database error occurred");
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -58,7 +58,8 @@ if ($checkStmt->rowCount() > 0) {
|
||||
"expirationTime" => $expirationTime
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[addInvitationPassenger.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -91,7 +92,8 @@ if ($checkStmt->rowCount() > 0) {
|
||||
jsonError("Failed to save invite data");
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[addInvitationPassenger.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -32,6 +32,7 @@ try {
|
||||
$insertStmt->execute([$inviterCode, $user_id, $role]);
|
||||
printSuccess(["message" => "Referral linked successfully"]);
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[add_unified_invite.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -7,8 +7,17 @@ header('Content-Type: application/json');
|
||||
|
||||
try {
|
||||
$inviteId = filterRequest("invite_id");
|
||||
$driverId = filterRequest("driver_id");
|
||||
$passengerId = filterRequest("passenger_id");
|
||||
// Force user ID from JWT based on role
|
||||
if ($role === 'driver') {
|
||||
$driverId = $user_id;
|
||||
$passengerId = null;
|
||||
} elseif ($role === 'passenger') {
|
||||
$passengerId = $user_id;
|
||||
$driverId = null;
|
||||
} else {
|
||||
echo json_encode(["status" => "failure", "message" => "Invalid user role."]);
|
||||
exit;
|
||||
}
|
||||
$countryCode = filterRequest("country_code"); // Expected: Jordan, Syria, Egypt
|
||||
|
||||
if (empty($inviteId)) {
|
||||
@@ -88,6 +97,7 @@ try {
|
||||
}
|
||||
|
||||
function addWalletBalance($url, $userId, $userType, $amount) {
|
||||
$s2sKey = getenv('S2S_SHARED_KEY');
|
||||
$data = [
|
||||
"user_id" => $userId,
|
||||
"user_type" => $userType,
|
||||
@@ -100,6 +110,11 @@ function addWalletBalance($url, $userId, $userType, $amount) {
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
|
||||
if ($s2sKey) {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-Auth-Token: $s2sKey"]);
|
||||
}
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $response;
|
||||
|
||||
@@ -145,6 +145,6 @@ try {
|
||||
if ($con->inTransaction()) {
|
||||
$con->rollBack();
|
||||
}
|
||||
jsonError("Failed to claim reward: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -35,7 +35,8 @@ if ($stmt->rowCount() > 0) {
|
||||
$insertStmt->execute([$user_id, $role, $newCode]);
|
||||
printSuccess(["referral_code" => $newCode]);
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[get_unified_code.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -54,6 +54,6 @@ try {
|
||||
|
||||
} catch (PDOException $e) {
|
||||
error_log("DB Error: " . $e->getMessage());
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
@@ -39,6 +39,7 @@ try {
|
||||
jsonError("Invalid invite code, already installed, or expired.");
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[updateInvitationCodeFromRegister.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
@@ -40,6 +40,7 @@ try {
|
||||
jsonError("Invalid invite code, already used, or marked as gift.");
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
jsonError("Database error: " . $e->getMessage());
|
||||
error_log("[updatePassengersInvitation.php] " . $e->getMessage());
|
||||
jsonError("An internal error occurred. Please try again later.");
|
||||
}
|
||||
?>
|
||||
@@ -5,10 +5,10 @@ require_once __DIR__ . '/../../connect.php';
|
||||
// $promo_code = filterRequest("promo_code");
|
||||
$driverID = filterRequest("driverID");
|
||||
|
||||
$sql = "SELECT * FROM `lisenceDetails`WHERE`driverID`='$driverID'";
|
||||
$sql = "SELECT * FROM `lisenceDetails` WHERE `driverID` = :driverID";
|
||||
|
||||
$stmt = $con->prepare($sql);
|
||||
$stmt->execute();
|
||||
$stmt->execute([':driverID' => $driverID]);
|
||||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($result) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user