nostolgagram/NostolgaGram/api/v1/accounts/upload_profile_pic.php
2026-06-24 21:33:55 +01:00

103 lines
No EOL
3.7 KiB
PHP

<?php
/**
* Module C: Profile Picture Ingestion via Unsigned Cloudinary Pipeline
* Target Path: htdocs/api/v1/accounts/upload_profile_pic.php
*/
// Inherit global server variables and database engine
require_once __DIR__ . '/../../../config.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
die(json_encode(["status" => "fail", "message" => "Method not allowed. Use POST pipeline."]));
}
// 1. Session Identification Verification
// Extract the custom cookie session string sent by the app
$sessionCookie = $_COOKIE['sessionid'] ?? '';
if (empty($sessionCookie) || strpos($sessionCookie, 'nostolga_sess_') !== 0) {
http_response_code(401);
die(json_encode(["status" => "fail", "message" => "Unauthorized client session context."]));
}
// Extract the raw primary key ID directly from the trailing string token
$userId = (int)str_replace('nostolga_sess_', '', $sessionCookie);
$db = getDB();
// 2. Locate the Binary File Array Payload
// 2014 Instagram uploads typically label image fields as 'profile_pic' or 'file'
$fileKey = isset($_FILES['profile_pic']) ? 'profile_pic' : (isset($_FILES['file']) ? 'file' : null);
if (!$fileKey || $_FILES[$fileKey]['error'] !== UPLOAD_ERR_OK) {
http_response_code(400);
die(json_encode(["status" => "fail", "message" => "No valid binary payload detected in file stream."]));
}
$tmpFilePath = $_FILES[$fileKey]['tmp_name'];
// 3. Handshake and Ship Binary Directly to Cloudinary Engine
$cloudinaryUrl = "https://api.cloudinary.com/v1_1/" . CLOUDINARY_CLOUD_NAME . "/image/upload";
// Create cURL Multipart Payload Fields
$payload = [
'file' => new CURLFile($tmpFilePath),
'upload_preset' => CLOUDINARY_UPLOAD_PRESET
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $cloudinaryUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Crucial for seamless connection processing under InfinityFree hosts
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200 || !$response) {
http_response_code(502);
die(json_encode(["status" => "fail", "message" => "Edge CDN ingestion system rejected payload processing."]));
}
$responseData = json_decode($response, true);
$secureCdnUrl = $responseData['secure_url'] ?? '';
if (empty($secureCdnUrl)) {
http_response_code(502);
die(json_encode(["status" => "fail", "message" => "Failed to extract valid secure resource asset locator."]));
}
try {
// 4. Persist Secure Asset Link to the User Database Row
$updateStmt = $db->prepare("UPDATE users SET profile_pic = ? WHERE id = ?");
$updateStmt->execute([$secureCdnUrl, $userId]);
// Fetch newly compiled profile state to populate the legacy response payload
$stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$userId]);
$user = $stmt->fetch();
if (!$user) {
http_response_code(404);
die(json_encode(["status" => "fail", "message" => "Target profile entity reference lost."]));
}
} catch (PDOException $e) {
http_response_code(500);
die(json_encode(["status" => "fail", "message" => "Database serialization mapping failed."]));
}
// 5. Structure legacy data block to update application state variables
http_response_code(200);
echo json_encode([
"user" => [
"pk" => (int)$user['id'],
"username" => $user['username'],
"full_name" => $user['full_name'],
"profile_pic_url" => $user['profile_pic'],
"is_private" => false
],
"status" => "ok"
]);
exit;