$value) { if (strstr($key, "|")) { $keys = explode("|", $key); foreach ($keys as $k) { array_push($mime_types, strtolower($k)); } } else { array_push($mime_types, strtolower($key)); } } return in_array(strtolower($needle), $mime_types); } function canto_curl_action($url, $echo, $token) { $header = array( 'Authorization' => 'Bearer ' . $token, 'user-agent' => 'Wordpress Plugin', 'Referer' => 'Wordpress Plugin', ); $response = wp_safe_remote_get( $url, array( 'method' => 'GET', 'headers' => $header, 'timeout' => 120, ) ); if (is_wp_error($response)) { return json_encode(array('error' => $response->get_error_message())); } return wp_remote_retrieve_body($response); } function canto_handle_copy_media() { if (!current_user_can('upload_files')) { wp_send_json_error('Unauthorized', 403); } if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'canto_copy_media')) { wp_send_json_error('Invalid nonce', 403); } if (!isset($_POST['fbc_id']) || !isset($_POST['fbc_scheme'])) { wp_send_json_error('Missing required POST parameters', 400); } // Include necessary WordPress files for media handling if (!function_exists('wp_handle_upload')) { include_once ABSPATH . 'wp-admin/includes/file.php'; } if (!function_exists('wp_generate_attachment_metadata')) { include_once ABSPATH . 'wp-admin/includes/image.php'; } if (!function_exists('media_handle_upload')) { include_once ABSPATH . 'wp-admin/includes/media.php'; } $error = null; // Data Must be Sanitized, Escaped, and Validated $post_description = isset($_POST['description']) ? sanitize_text_field($_POST['description']) : ''; $post_alt = isset($_POST['alt']) ? sanitize_text_field($_POST['alt']) : ''; $post_copyright = isset($_POST['copyright']) ? sanitize_text_field($_POST['copyright']) : ''; $post_terms = isset($_POST['terms']) ? sanitize_text_field($_POST['terms']) : ''; $post_fbc_id = sanitize_text_field($_POST['fbc_id']); $post_fbc_scheme = sanitize_text_field($_POST['fbc_scheme']); $send_id = isset($_POST['post_id']) ? sanitize_text_field($_POST['post_id']) : ''; $post_fbc_flight_domain = get_option('fbc_flight_domain'); $post_fbc_app_api = get_option('fbc_app_api'); $post_fbc_app_token = get_option('fbc_app_token'); $post_caption = isset($_POST['caption']) ? sanitize_text_field($_POST['caption']) : ''; $post_title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : ''; $post_size = isset($_POST['size']) ? sanitize_text_field($_POST['size']) : ''; $post_align = isset($_POST['align']) ? sanitize_text_field($_POST['align']) : ''; $post_link = isset($_POST['link']) ? sanitize_text_field($_POST['link']) : ''; $post_chromeless = isset($_POST['chromeless']) ? sanitize_text_field($_POST['chromeless']) : ''; global $post; $id = $send_id; //Go get the media item from Flight $flight['api_url'] = 'https://' . $post_fbc_flight_domain . '.' . $post_fbc_app_api . '/api/v1/'; $flight['req'] = $flight['api_url'] . $post_fbc_scheme . '/' . $post_fbc_id; $response = canto_curl_action($flight['req'], 0, $post_fbc_app_token); $response = (json_decode($response)); /* Check if mime_type is allowed */ $allowed_mime_types = get_allowed_mime_types(); $uploaded_file_type = pathinfo($response->name); if (!canto_check_mime_types($allowed_mime_types, $uploaded_file_type['extension'])) { $error = "This file type is not allowed by your Wordpress theme. Please contact your theme developer to allow support of this file type: '" . $uploaded_file_type['extension'] . "'"; } if ($error === null) : //Get the download url $detail = $response->url->download; $detail = $detail . '/directuri'; $detail = canto_curl_action($detail, 1, $post_fbc_app_token); $location = trim($detail); $tmp = download_url($location); $file_array = array( 'name' => $response->name, 'tmp_name' => $tmp ); // Check for download errors if (is_wp_error($tmp)) { error_log("error-----------" . json_encode($tmp->errors)); wp_send_json_error(array("error" => $tmp->errors)); } $post_data = array( 'post_content' => $post_description, 'post_excerpt' => $post_caption, ); if (!empty($post_title)) { $post_data['post_title'] = $post_title; } else { $post_data['post_title'] = basename($file_array['name']); } /** * Check for Duplicates (existing images imported from Canto) */ $args = array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'meta_query' => array( array( 'key' => 'fbc_id', 'value' => $post_fbc_id ) ) ); $query = new WP_Query($args); $posts = $query->posts; if ($posts && get_option('fbc_duplicates') === "true") { $id = $posts[0]->ID; // Update custom metadata fields update_post_meta($id, '_wp_attachment_image_alt', $post_alt); update_post_meta($id, 'description', $post_description); update_post_meta($id, 'copyright', $post_copyright); update_post_meta($id, 'terms', $post_terms); update_post_meta($id, 'fbc_id', $post_fbc_id); update_post_meta($id, 'fbc_scheme', $post_fbc_scheme); // Update post data (title and description) to sync with Canto metadata $post_update = array( 'ID' => $id, ); // Update title if provided if (!empty($post_title)) { $post_update['post_title'] = $post_title; } else { $post_update['post_title'] = pathinfo($response->name, PATHINFO_FILENAME); } // Update description (post_content) if provided if (!empty($post_description)) { $post_update['post_content'] = $post_description; } // Update caption (post_excerpt) if provided if (!empty($post_caption)) { $post_update['post_excerpt'] = $post_caption; } wp_update_post($post_update); // Get the new filename from Canto — basename() prevents path traversal $new_filename = basename($response->name); // Get old file info $guid = explode("/", $posts[0]->guid); $old_filename = basename(array_pop($guid)); $meta = wp_get_attachment_metadata($id); $uploads = wp_upload_dir(); $dir_path = $uploads['path']; $dir_path_file = $dir_path . '/' . $new_filename; // Delete old file if filename changed if ($old_filename !== $new_filename && file_exists($dir_path . '/' . $old_filename)) { wp_delete_file($dir_path . '/' . $old_filename); } // Delete file with new filename if it already exists if (file_exists($dir_path_file)) { wp_delete_file($dir_path_file); } // Delete old image size variations if (is_array($meta) && isset($meta["sizes"])) { foreach ($meta["sizes"] as $size) { $fileName = $size["file"]; // Look for files and delete them if (strlen($fileName)) { $fp = $dir_path . '/' . $size["file"]; if (file_exists($fp)) { wp_delete_file($fp); } } } } // Copy file for Wordpress media access with new filename global $wp_filesystem; if (empty($wp_filesystem)) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } $copy = $wp_filesystem->copy($tmp, $dir_path_file, true); $wp_filesystem->chmod($dir_path_file, FS_CHMOD_FILE); // Make thumb and/or update metadata wp_update_attachment_metadata($id, wp_generate_attachment_metadata($id, $dir_path_file)); update_attached_file($id, $dir_path_file); if (file_exists($file_array['tmp_name'])) { wp_delete_file($file_array['tmp_name']); } } else { $id = media_handle_sideload($file_array, $send_id, '', $post_data); if (is_wp_error($id)) { wp_delete_file($file_array['tmp_name']); wp_send_json_error(array("error" => $id->errors['upload_error'][0])); } add_post_meta($id, '_wp_attachment_image_alt', $post_alt); add_post_meta($id, 'description', $post_description); add_post_meta($id, 'copyright', $post_copyright); add_post_meta($id, 'terms', $post_terms); add_post_meta($id, 'fbc_id', $post_fbc_id); add_post_meta($id, 'fbc_scheme', $post_fbc_scheme); } $attachment_url = wp_get_attachment_url($id); $rel = $url = ''; $html = $title = $post_title ?? ''; $align = $post_align ?? 'none'; $size = $post_size ?? 'medium'; $alt = $post_alt ?? ''; $caption = $post_caption ?? ''; $title = ''; // We no longer insert title tags into tags, as they are redundant. // Check MIME type to determine how to render the media $mime_string = get_post_mime_type($id); $mime_type = explode('/', $mime_string); if ($mime_type[0] === 'image') { // For images, use the standard WordPress function $html = get_image_send_to_editor($id, $caption, $title, $align, $url, (bool)$rel, $size, $alt); } else { // For documents (PDFs, etc.), create a proper link $attachment_title = $post_title ? $post_title : basename(get_attached_file($id)); $link_html = '' . esc_html($attachment_title) . ''; $align_class = ''; if ($align && $align !== 'none') { $align_class = ' class="align' . esc_attr($align) . '"'; } if ($align_class) { $html = '' . $link_html . ''; } else { $html = $link_html; } if (!empty($caption)) { $caption_class = $align_class ? ' class="wp-caption align' . esc_attr($align) . '"' : ' class="wp-caption"'; $html = '' . $link_html . '

' . esc_html($caption) . '

'; } } $attachment = array(); $attachment['post_title'] = $post_title; $attachment['post_excerpt'] = $post_caption; $attachment['image-size'] = $post_size; $attachment['image_alt'] = $post_alt; $attachment['align'] = $post_align; $attachment['description'] = $post_description; $attachment['copyright'] = $post_copyright; $attachment['terms'] = $post_terms; if ($post_link != "none") { $attachment['url'] = $attachment_url; } else { $attachment['url'] = ''; } //This filter is documented in wp-admin/includes/media.php $html = apply_filters('media_send_to_editor', $html, $id, $attachment); // replace wp-image-, wp-att- and attachment_ $html = preg_replace( array( '#(caption id="attachment_)(\d+")#', // mind the quotes! '#(wp-image-|wp-att-)(\d+)#' ), array( sprintf('${1}nsm_%s_${2}', esc_attr($send_id)), sprintf('${1}nsm-%s-${2}', esc_attr($send_id)), ), $html ); $results = array( "attachment" => $html, "attachment_id" => $id, "attachment_url" => $attachment_url, "attachment_mime" => $mime_type[0], "attachment_filename" => $post_title ? $post_title : basename(get_attached_file($id)) ); endif; //End Error for $allowed_mime_types if ($error !== null) { wp_send_json_error(array("error" => $error)); } wp_send_json_success($results); } add_action('wp_ajax_canto_copy_media', 'canto_handle_copy_media');