diff --git a/final/config.php.example b/final/config.php.example index ae8ba12..bc4afbb 100644 --- a/final/config.php.example +++ b/final/config.php.example @@ -5,6 +5,11 @@ return [ 'ftp_pass' => "FTP_PASS", 'ftp_port' => "21", 'ftp_domain' => 'FTP_DOMAIN', + 'ftp_path' => 'FTP_PATH, + 'db_host' => 'DB_HOST', + 'db_user' => 'DB_USER', + 'db_pwd' => 'DB_PWD', + 'db_name' => 'DB_NAME', 'api_key' => 'API_KEY', 'api_secret' => 'API_SECRET' ]; \ No newline at end of file diff --git a/final/css/style.css b/final/css/style.css index bd7f321..8629457 100644 --- a/final/css/style.css +++ b/final/css/style.css @@ -15,6 +15,7 @@ body { color: #ffffff; float: right; text-decoration: none; + padding-right: 20px; } .container { margin-top: 70px; @@ -25,13 +26,16 @@ form { padding: 20px; border-radius: 5px; } -label, input, button { +label, +input, +button { display: block; width: 100%; margin-bottom: 10px; color: #ffffff; } -input, button { +input, +button { padding: 10px; background-color: #333333; border: none; @@ -57,20 +61,31 @@ button { margin: 0 auto; } @keyframes bounce { - 0%, 100% { + 0%, + 100% { transform: translateY(0); } 50% { transform: translateY(-20px); } } -.debug-window { +.debug-window, +.metadata-review, +#display-metadata-btn-container { background-color: #1f1f1f; padding: 10px; margin-top: 20px; - max-height: 200px; overflow-y: scroll; } + +.debug-window { + display: none; + max-height: 200px; +} + +.metadata-review { + max-height: 1000px; +} #tags-container { margin-top: 20px; } @@ -80,6 +95,8 @@ button { } .tag-list li { margin-bottom: 5px; + display: flex; + justify-content: space-between; } #drop-area { border: 2px dashed #ffffff; @@ -100,9 +117,98 @@ button { .image-preview { margin-top: 20px; text-align: center; + max-width: 100%; + width: 100%; } .image-preview img { max-width: 100%; height: auto; } + +#auth-actions { + display: flex; +} + +#auth-actions button { + margin: 0 5px; +} + +table { + width: 100%; + border-collapse: collapse; + margin-top: 20px; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); +} + +table th, +table td { + padding: 12px; + text-align: left; + border: 1px solid #ddd; + font-size: 1rem; +} + +.category-title { + background-color: #fafafa; + padding: 12px; + border-radius: 6px; + margin-top: 30px; + color: #333; + font-size: 1.3rem; +} + +.category-title::before { + content: "🔍"; + padding-right: 8px; +} + +.modal { + display: none; + position: fixed; + z-index: 1; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow: auto; + background-color: rgba(0, 0, 0, 0.4); +} + +.modal-content { + background-color: #1f1f1f; + margin: 15% auto; + padding: 20px; + border: 1px solid #888; + width: 80%; + max-width: 900px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + border-radius: 8px; +} + +.close { + color: #aaa; + font-size: 28px; + font-weight: bold; + position: absolute; + top: 100px; + right: 25px; + transition: 0.3s; +} + +.close:hover, +.close:focus { + color: black; + text-decoration: none; + cursor: pointer; +} + +#display-metadata-btn-container { + display: none; +} + +#displayMetadataBtn { + margin-top: 20px; +} diff --git a/final/db.php b/final/db.php new file mode 100644 index 0000000..291bbdf --- /dev/null +++ b/final/db.php @@ -0,0 +1,15 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } catch (PDOException $e) { + die("Connection failed: " . $e->getMessage()); + } +?> diff --git a/final/display_metadata.php b/final/display_metadata.php new file mode 100644 index 0000000..2c2e701 --- /dev/null +++ b/final/display_metadata.php @@ -0,0 +1,99 @@ +Error: Image path is not set in the session.
"; + exit; + } + + try { + $image_data = file_get_contents($image_url); + if ($image_data === false) { + throw new Exception('Failed to download the image file.'); + } + file_put_contents($temp_image_path, $image_data); + + if (!class_exists('Imagick')) { + throw new Exception('Imagick extension is not installed or enabled.'); + } + + $imagick = new Imagick($temp_image_path); + + if (!$imagick) { + echo "Error: Imagick failed to load the image.
"; + exit; + } + + $properties = $imagick->getImageProperties(); + + $categories = [ + 'EXIF' => [], + 'JPEG' => [], + 'IPTC' => [], + 'XMP' => [], + 'Other' => [] + ]; + + foreach ($properties as $key => $value) { + if (strpos($key, 'exif:') === 0) { + $categories['EXIF'][$key] = $value; + } elseif (strpos($key, 'jpeg:') === 0) { + $categories['JPEG'][$key] = $value; + } elseif (strpos($key, 'iptc:') === 0) { + $categories['IPTC'][$key] = $value; + } elseif (strpos($key, 'xmp:') === 0) { + $categories['XMP'][$key] = $value; + } else { + $categories['Other'][$key] = $value; + } + } + + echo "Property | +Value | +
---|---|
$formatted_key | $value |
Error using Imagick: " . $e->getMessage() . "
"; + if (file_exists($temp_image_path)) { + unlink($temp_image_path); + } + } +?> diff --git a/final/embed_metadata.php b/final/embed_metadata.php index 4be897e..c270ae1 100644 --- a/final/embed_metadata.php +++ b/final/embed_metadata.php @@ -1,58 +1,112 @@ setImageProperty('exif:ImageDescription', $tags_string); - - // Output the image - header('Content-Type: ' . $image_type); - header('Content-Disposition: attachment; filename="modified_image.' . strtolower($imagick->getImageFormat()) . '"'); - echo $imagick->getImagesBlob(); - - // Clean up - $imagick->clear(); - $imagick->destroy(); - unlink($image_path); - unset($_SESSION['image_path']); - unset($_SESSION['image_type']); -} catch (Exception $e) { - // Clean up - if (isset($imagick)) { - $imagick->clear(); - $imagick->destroy(); - } - if (file_exists($image_path)) { - unlink($image_path); - } - unset($_SESSION['image_path']); - unset($_SESSION['image_type']); + $remote_file = $ftp_path . $base_name . '_modified_image.jpg'; + + try { + if (!class_exists('Imagick')) { + throw new Exception('Imagick extension is not installed or enabled.'); + } + + $temp_image_path = sys_get_temp_dir() . '/' . basename($file_url); + $image_data = file_get_contents($file_url); + if ($image_data === false) { + throw new Exception('Failed to download the remote image file.'); + } + file_put_contents($temp_image_path, $image_data); + + $imagick = new Imagick($temp_image_path); + + $tags_string = implode(', ', $selected_tags); + // Imagick only supports writing comments to jpegs, modifying exif data does not persist + // https://github.com/Imagick/imagick/issues/124 + // https://stackoverflow.com/questions/5384962/writing-exif-data-in-php + $imagick->setImageProperty('comment', $tags_string); + + // Debug: Output all properties + foreach ($imagick->getImageProperties() as $key => $value) { + error_log("Key: $key, Value: $value"); + } + + $imagick->setImageFormat('jpeg'); - // Log the error - error_log('Error in embed_metadata.php: ' . $e->getMessage()); + $temp_output_path = sys_get_temp_dir() . '/output_image.jpg'; + $imagick->writeImage($temp_output_path); - // Display error in debug window - echo 'Error processing image: ' . htmlspecialchars($e->getMessage()); -} -?> + $image_type = mime_content_type($temp_output_path); + header('Content-Type: ' . $image_type); + header('Content-Disposition: attachment; filename="' . $file_name . '_modified_image.jpg"'); + readfile($temp_output_path); + + $temp_output_path = sys_get_temp_dir() . '/output_image.jpg'; + $imagick->writeImage($temp_output_path); + + $ftp_conn = ftp_connect($ftp_server, $ftp_port); + if ($ftp_conn) { + $debug[] = "Connected to FTP server: $ftp_server:$ftp_port"; + } else { + echo json_encode(['message' => 'Could not connect to FTP server', 'debug' => $debug]); + exit; + } + + $login = ftp_login($ftp_conn, $ftp_user, $ftp_pass); + if ($login) { + $debug[] = "FTP login successful for user: $ftp_user"; + ftp_pasv($ftp_conn, true); // Enable passive mode + } else { + $ftp_response = ftp_raw($ftp_conn, 'NOOP'); + $debug[] = "FTP login failed for user: $ftp_user"; + $debug[] = "FTP Server Response: " . implode(" | ", $ftp_response); + ftp_close($ftp_conn); + echo json_encode(['message' => 'FTP login failed', 'debug' => $debug]); + exit; + } + + if (ftp_put($ftp_conn, $remote_file, $temp_output_path, FTP_BINARY)) { + $debug[] = "File uploaded successfully to: $remote_file"; + } + + if (file_exists($temp_image_path)) { + unlink($temp_image_path); + } + + if (file_exists($temp_output_path)) { + unlink($temp_output_path); + } + + if (!file_exists($temp_output_path)) { + echo "Error: Image file does not exist at $temp_output_path
"; + exit; + } + + } catch (Exception $e) { + if (isset($imagick)) { + $imagick->destroy(); + $imagick->clear(); + } + if (isset($temp_image_path) && file_exists($temp_image_path)) { + unlink($temp_image_path); + } + echo 'Error processing image: ' . htmlspecialchars($e->getMessage()); + } +?> \ No newline at end of file diff --git a/final/ftp_upload.php b/final/ftp_upload.php index e1328fa..186b552 100644 --- a/final/ftp_upload.php +++ b/final/ftp_upload.php @@ -15,11 +15,13 @@ $ftp_port = $config['ftp_port']; $ftp_user = $config['ftp_user']; $ftp_pass = $config['ftp_pass']; +$ftp_path = $config['ftp_path']; if (isset($_FILES['file'])) { $file = $_FILES['file']['tmp_name']; $file_name = basename($_FILES['file']['name']); - $remote_file = "uploads/" . $file_name; + $_SESSION['file_name'] = $file_name; + $remote_file = $ftp_path . $file_name; // Step 1: Connect to FTP server $ftp_conn = ftp_connect($ftp_server, $ftp_port); @@ -47,33 +49,61 @@ // Step 3: Upload the file if (ftp_put($ftp_conn, $remote_file, $file, FTP_BINARY)) { $debug[] = "File uploaded successfully to: $remote_file"; - - // Step 4: Call API with FTP file URL $file_url = $config['ftp_domain'] . "/uploads/" . urlencode($file_name); - $api_key = $config['api_key']; - $api_secret = $config['api_secret']; - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, "https://api.imagga.com/v2/tags?image_url=" . urlencode($file_url)); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_USERPWD, "$api_key:$api_secret"); + // Step 4: Mock API Response + $mock_api_response = [ + 'result' => [ + 'tags' => [ + ['confidence' => 72.304817199707, 'tag' => ['en' => 'star']], + ['confidence' => 67.556610107422, 'tag' => ['en' => 'sun']], + ['confidence' => 60.43567276001, 'tag' => ['en' => 'celestial body']], + ['confidence' => 43.794635772705, 'tag' => ['en' => 'sky']], + ['confidence' => 41.704250335693, 'tag' => ['en' => 'landscape']], + ] + ], + 'status' => ['text' => 'success'] + ]; - $response = curl_exec($ch); - $curl_error = curl_error($ch); - curl_close($ch); + $response = json_encode($mock_api_response); + $debug[] = "Mock API response used for file: $file_url"; if ($response) { $debug[] = "API call successful for file: $file_url"; $data = json_decode($response, true); } else { - $debug[] = "API call failed: $curl_error"; + $debug[] = "API call failed"; echo json_encode(['message' => 'API call failed', 'debug' => $debug]); ftp_close($ftp_conn); exit; } + // Step 4: Call API with FTP file URL + // $api_key = $config['api_key']; + // $api_secret = $config['api_secret']; + + // $ch = curl_init(); + // curl_setopt($ch, CURLOPT_URL, "https://api.imagga.com/v2/tags?image_url=" . urlencode($file_url)); + // curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + // curl_setopt($ch, CURLOPT_USERPWD, "$api_key:$api_secret"); + + // $response = curl_exec($ch); + // $curl_error = curl_error($ch); + // curl_close($ch); + + // if ($response) { + // $debug[] = "API call successful for file: $file_url"; + // $data = json_decode($response, true); + // } else { + // $debug[] = "API call failed: $curl_error"; + // echo json_encode(['message' => 'API call failed', 'debug' => $debug]); + // ftp_close($ftp_conn); + // exit; + // } + // Step 5: Write metadata based on API response - if (isset($data['result']['tags'])) { + if (isset($data['result']['tags']) && count($data['result']['tags']) > 0) { + $tags = []; foreach ($data['result']['tags'] as $tag) { if ($tag['confidence'] >= $threshold) { $tags[] = [ @@ -83,34 +113,57 @@ } } - $description = implode(", ", $tags); - $metadata_content = "Image Description: " . $description . "\nUploaded File Name: " . $file_name; - - $remote_file = "uploads/" . pathinfo($file_name, PATHINFO_FILENAME) . "_metadata.txt"; - $local_upload = './uploads/'; - $metadata_file = $local_upload . pathinfo($file_name, PATHINFO_FILENAME) . "_metadata.txt"; + if (count($tags) > 0) { + // Prepare the description from valid tags + $tag_names = array_map(function ($tag) { + return $tag['tag']; + }, $tags); + $description = implode(", ", $tag_names); - if (file_put_contents($metadata_file, $metadata_content) !== false) { - $debug[] = "Metadata file created successfully locally at: " . $metadata_file; - - if (ftp_put($ftp_conn, $remote_file, $metadata_file, FTP_ASCII)) { - $debug[] = "Metadata file uploaded successfully remotely to: $remote_file, deleting local copy"; + // Create metadata content + $metadata_content = "Image Description: " . $description . "\nUploaded File Name: " . $file_name; + + // Prepare metadata file paths + $remote_file = $ftp_path . pathinfo($file_name, PATHINFO_FILENAME) . "_metadata.txt"; + $local_upload = './uploads/'; + $metadata_file = $local_upload . pathinfo($file_name, PATHINFO_FILENAME) . "_metadata.txt"; + + // Write metadata content to local file + if (file_put_contents($metadata_file, $metadata_content) !== false) { + $debug[] = "Metadata file created successfully locally at: " . $metadata_file; + + // Upload metadata file to FTP server + if (ftp_put($ftp_conn, $remote_file, $metadata_file, FTP_ASCII)) { + $debug[] = "Metadata file uploaded successfully remotely to: $remote_file, deleting local copy"; + $_SESSION['image_path'] = $file_url; + echo json_encode([ + 'message' => 'File and metadata uploaded successfully', + 'tags' => $tags, + 'description' => $description, + 'debug' => $debug + ]); + } else { + $debug[] = "Failed to remotely upload metadata file to: $remote_file"; + echo json_encode(['message' => 'Failed to upload metadata file', 'debug' => $debug]); + } + } else { + $debug[] = "Failed to create metadata file."; echo json_encode([ - 'message' => 'File and metadata uploaded successfully', - 'tags' => $tags, - 'description' => $description, + 'message' => 'Failed to create metadata file.', 'debug' => $debug ]); - } else { - $debug[] = "Failed to remotely upload metadata file to: $remote_file"; - echo json_encode(['message' => 'Failed to upload metadata file', 'debug' => $debug]); } } else { - $debug[] = "Failed to create metadata file."; + // Case when no tags meet the threshold + $firstTagConfidence = floor($data['result']['tags'][0]['confidence']); + $debug[] = "No tags found that meet the threshold of $threshold%"; + $debug[] = "Minimum confidence score of $firstTagConfidence is needed to yield results."; echo json_encode([ - 'message' => 'Failed to create metadata file.', + 'message' => 'No tags met the threshold value.', 'debug' => $debug ]); + ftp_close($ftp_conn); + exit; } } else { $debug[] = "No tags found in API response."; diff --git a/final/index.php b/final/index.php index 2d89262..4f81aef 100644 --- a/final/index.php +++ b/final/index.php @@ -1,9 +1,9 @@ @@ -109,18 +109,54 @@Loading metadata...
"; + + fetch("display_metadata.php") + .then((response) => { + if (!response.ok) { + return response.text().then((text) => { + throw new Error(text); + }); + } + return response.text(); + }) + .then((data) => { + metadataReview.innerHTML = data; + modal.style.display = "block"; + }) + .catch((error) => { + console.error("Error:", error); + metadataReview.innerHTML = `Error: ${error.message}
`; + }); +} + +btn.onclick = function () { + displayMetadata(); +}; + +closeModalBtn.onclick = function () { + modal.style.display = "none"; +}; + +window.onclick = function (event) { + if (event.target === modal) { + modal.style.display = "none"; + } +}; diff --git a/final/logout.php b/final/logout.php index e5ab4b6..3425691 100644 --- a/final/logout.php +++ b/final/logout.php @@ -1,6 +1,8 @@ diff --git a/final/main.php b/final/main.php index fbba619..dd284d6 100644 --- a/final/main.php +++ b/final/main.php @@ -169,6 +169,11 @@ Logoutdiff --git a/final/register.php b/final/register.php new file mode 100644 index 0000000..609c416 --- /dev/null +++ b/final/register.php @@ -0,0 +1,164 @@ + + +
+ +
+ + + +
+ +