HEX
Server: Apache
System: Linux WWW 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64
User: web11 (1011)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/intranet.kauko.lt/wp-content/plugins/document-library-pro/src/Util/Media.php
<?php
namespace Barn2\Plugin\Document_Library_Pro\Util;

use Imagick;

defined( 'ABSPATH' ) || exit;

/**
 * Media Library Utilities
 *
 * @package   Barn2\document-library-pro
 * @author    Barn2 Plugins <support@barn2.com>
 * @license   GPL-3.0
 * @copyright Barn2 Media Ltd
 */
final class Media {

	/**
	 * Removes extension from a filename
	 *
	 * @param string $file_name
	 * @return string
	 */
	public static function get_filename_without_extension( $file_name ) {
		return substr( $file_name, 0, strrpos( $file_name, '.' ) );
	}

	/**
	 * Downloads a file from a URL and attaches it to the document
	 *
	 * @param  string   $url        Attachment URL.
	 * @param  int      $document_id Document ID
	 * @return int
	 * @throws \Exception If attachment cannot be loaded.
	 */
	public static function attach_file_from_url( $url, $document_id ) {
		if ( empty( $url ) ) {
			return 0;
		}

		$file_id    = 0;
		$upload_dir = wp_upload_dir( null, false );
		$base_url   = $upload_dir['baseurl'] . '/';

		// Check if the file could already be in the Media Library
		if ( strpos( $url, $base_url ) === 0 ) {
			$file_id = self::get_attachment_id_from_url( $url );
		}

		if ( ! $file_id ) {
			// This is an external URL or not in the media library, so compare to source.
			$args = [
				'post_type'   => 'attachment',
				'post_status' => 'any',
				'fields'      => 'ids',
				'meta_query'  => [
					[
						'value' => $url,
						'key'   => '_dlp_attachment_source',
					],
				],
			];

			$file_ids = get_posts( $args );

			if ( $file_ids ) {
				$file_id = current( $file_ids );
			}
		}

		// Upload if attachment does not exists.
		if ( ! $file_id && stristr( $url, '://' ) ) {
			$upload = self::upload_document_from_url( $url );

			if ( is_wp_error( $upload ) ) {
				throw new \Exception( esc_html( $upload->get_error_message() ), 400 );
			}

			$file_id = self::set_uploaded_document_as_attachment( $upload, $document_id );

			// Save attachment source for future reference.
			update_post_meta( $file_id, '_dlp_attachment_source', $url );
		}

		if ( ! $file_id ) {
			/* translators: %s: document URL */
			throw new \Exception( sprintf( esc_html__( 'Unable to use document "%s".', 'document-library-pro' ), esc_url( $url ) ), 400 );
		}

		return $file_id;
	}

	/**
	 * Upload document from URL.
	 *
	 * @param   string              $document_url File URL.
	 * @return  array|\WP_Error     Attachment data or error message.
	 */
	private static function upload_document_from_url( $document_url ) {
		$parsed_url = wp_parse_url( $document_url );

		// Check parsed URL.
		if ( ! $parsed_url || ! is_array( $parsed_url ) ) {
			return new \WP_Error(
				'document_library_import_invalid_url',
				/* translators: %s: image URL */
				sprintf( __( 'Invalid URL %s.', 'document-library-pro' ), $document_url ),
				[ 'status' => 400 ]
			);
		}

		// Ensure url and filename is valid.
		$document_url   = esc_url_raw( $document_url );
		$safe_file_name = sanitize_file_name( urldecode( basename( current( explode( '?', $document_url ) ) ) ) );

		// download_url function is part of wp-admin.
		if ( ! function_exists( 'download_url' ) ) {
			include_once ABSPATH . 'wp-admin/includes/file.php';
		}

		/**
		 * Update imported File URL for specific file storage clouds
		 *
		 * @param string $document_url URL of file to be downloaded
		 *
		 * @hooked [ 'Barn2\Plugin\Document_Library_Pro\Util\Media', 'maybe_sanitize_dropbox_link' ]
		 * @hooked [ 'Barn2\Plugin\Document_Library_Pro\Util\Media', 'maybe_get_google_drive_download_link' ]
		 */
		$document_url = apply_filters( 'document_library_pro_import_document_url', $document_url );

		$file_array         = [];
		$file_array['name'] = $safe_file_name;

		// Download file to temp location.
		$file_array['tmp_name'] = download_url( $document_url );

		/**
		 * Filter mime types allowed to be brought into Document Library Pro
		 *
		 * @param array $mime_types in format provided by wp_get_mime_types()
		 */
		$mimes_allowed = apply_filters( 'document_library_pro_import_mimes_allowed', wp_get_mime_types() );

		// If error storing temporarily, return the error.
		if ( is_wp_error( $file_array['tmp_name'] ) ) {
			return new \WP_Error(
				'document_library_import_invalid_remote_url',
				/* translators: %s: image URL */
				sprintf( __( 'Error getting remote document %s.', 'document-library-pro' ), $document_url ) . ' '
				/* translators: %s: error message */
				. sprintf( __( 'Error: %s', 'document-library-pro' ), $file_array['tmp_name']->get_error_message() ),
				[ 'status' => 400 ]
			);
		}

		// Get the file type of the temporary file
		$tmp_file_type = wp_check_filetype( $file_array['tmp_name'] );

		// Ensure the filename has the correct extension
		if ($tmp_file_type['ext'] && !preg_match('/\.' . $tmp_file_type['ext'] . '$/', $file_array['name'])) {
			$file_array['name'] .= '.' . $tmp_file_type['ext'];
		}

		/**
		 * Update file name of imported file
		 *
		 * @param array $file_array [ name, tmp_name ]
		 * @param string $document_url the sanitized File URL being imported
		 *
		 * @hooked [ 'Barn2\Plugin\Document_Library_Pro\Util\Media', 'maybe_update_imported_google_drive_file_name' ], 10, 2
		 */
		$file_array    = apply_filters( 'document_library_pro_import_file_array', $file_array, $document_url );

		// Do the validation and storage stuff.
		$file = wp_handle_sideload(
			$file_array,
			[
				'test_form' => false,
				'mimes'     => $mimes_allowed,
			],
			current_time( 'Y/m' )
		);

		if ( isset( $file['error'] ) ) {
			// phpcs:disable WordPress.WP.AlternativeFunctions.unlink_unlink
			// phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged
			@unlink( $file_array['tmp_name'] );
			// phpcs:enable WordPress.WP.AlternativeFunctions.unlink_unlink
			// phpcs:enable WordPress.PHP.NoSilencedErrors.Discouraged

			return new \WP_Error(
				'document_library_pro_import_invalid_document',
				sprintf(
					/* translators: %s: error message */
					__( 'Invalid document: %s', 'document-library-pro' ),
					$file['error']
				),
				[ 'status' => 400 ]
			);
		}

		return $file;
	}

	/**
	 * Set uploaded document as attachment.
	 *
	 * @param   array   $upload Upload information from wp_upload_bits.
	 * @param   int     $id Post ID. Default to 0.
	 * @return  int     Attachment ID
	 */
	private static function set_uploaded_document_as_attachment( $upload, $id = 0 ) {
		$info = wp_check_filetype( $upload['file'] );

		$attachment = [
			'post_mime_type' => $info['type'],
			'guid'           => $upload['url'],
			'post_parent'    => $id,
			'post_title'     => basename( $upload['file'] ),
			'post_content'   => '',
		];

		$attachment_id = wp_insert_attachment( $attachment, $upload['file'], $id );
		if ( ! is_wp_error( $attachment_id ) ) {
			wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $upload['file'] ) );
		}

		return $attachment_id;
	}

	/**
	 * Retrieves an attachment object based on a URL
	 *
	 * @param string $attachment_url
	 * @return mixed
	 */
	private static function get_attachment_id_from_url( $attachment_url ) {
		global $wpdb;

		$attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid=%s;", $attachment_url ) );

		if ( ! $attachment ) {
			return null;
		}

		return $attachment[0];
	}

	/**
	 * Cleans dropbox preview URLs for downloading.
	 *
	 * @param string $document_url
	 * @return string
	 */
	public static function maybe_sanitize_dropbox_link( $document_url ) {
		// check if potentially dropbox url
		if ( self::is_dropbox_link( $document_url ) === false ) {
			return $document_url;
		}

		// Check if we have a dropbox direct url
		if ( self::is_dropbox_direct_link( $document_url ) ) {
			return $document_url;
		}

		// Check if we have a dropbox normal url
		if ( self::is_dropbox_site_link( $document_url ) === false ) {
			return $document_url;
		}

		// ensure dl=1
		$document_url = add_query_arg( 'dl', '1', $document_url );

		return $document_url;
	}

	/**
	 * Get raw dropbox link for direct linking.
	 *
	 * @param string $document_url
	 *
	 * @return string
	 */
	public static function maybe_get_dropbox_direct_link( $document_url ) {
		// already a direct link
		if ( self::is_dropbox_direct_link( $document_url ) ) {
			return $document_url;
		}

		// ensure we have a dropbox link
		if ( self::is_dropbox_site_link( $document_url ) === false ) {
			return $document_url;
		}

		// remove any dl parameter
		$document_url = remove_query_arg( 'dl', $document_url );

		// add raw=1
		$document_url = add_query_arg( 'raw', '1', $document_url );

		return $document_url;
	}

	/**
	 * Get raw google drive link for direct downloading (primarily used by importer).
	 *
	 * @param string $document_url
	 *
	 * @return string
	 */
	public static function maybe_get_google_drive_download_link( $document_url ) {
		// already a direct link
		if ( self::is_google_drive_download_link( $document_url ) ) {
			return $document_url;
		}

		// ensure we have a google share link
		if ( self::is_google_drive_share_link( $document_url ) === false ) {
			return $document_url;
		}

		// replace /file/d path with /uc and export query parameter
		$document_url = str_replace( '/file/d/', '/uc?export=download&id=', $document_url );

		// find everything after the id and delete it
		$leftovers_pos = strpos( $document_url, '/', strpos( $document_url, '&id=' ) );
		$document_url  = substr( $document_url, 0, $leftovers_pos );

		return $document_url;
	}

	/**
	 * Check if a URL is a Dropbox link
	 *
	 * @param string $url
	 * @return bool
	 */
	public static function is_dropbox_link( $url ) {
		if ( strpos( $url, 'dropbox.com' ) !== false || strpos( $url, 'dropboxusercontent.com' ) !== false ) {
			return true;
		}

		return false;
	}

	/**
	 * Check if a URL is a Dropbox link
	 *
	 * @param string $url
	 * @return bool
	 */
	public static function is_dropbox_site_link( $url ) {
		$dropbox_urls = [
			'//dropbox.com/',
			'//www.dropbox.com/',
		];

		$is_dropbox = array_filter(
			$dropbox_urls,
			function ( $domain ) use ( $url ) {
				return stripos( $url, $domain ) !== false;
			}
		);

		return count( $is_dropbox ) > 0;
	}

	/**
	 * Check if a URL is a Google Drive preview link
	 *
	 * @param string $url
	 * @return bool
	 */
	public static function is_google_drive_share_link( $url ) {
		$share_urls = [
			'//drive.google.com/file/d',
		];

		$is_gdrive = array_filter(
			$share_urls,
			function ( $domain ) use ( $url ) {
				return stripos( $url, $domain ) !== false;
			}
		);

		return count( $is_gdrive ) > 0;
	}

	/**
	 * Check if a URL is a direct link to a Dropbox file
	 *
	 * @param string $url
	 * @return bool
	 */
	public static function is_dropbox_direct_link( $url ) {
		$direct_urls = [
			'//dl.dropbox.com/',
			'//dl.dropboxusercontent.com/',
		];

		$is_dropbox_direct_link = array_filter(
			$direct_urls,
			function ( $domain ) use ( $url ) {
				return stripos( $url, $domain ) !== false;
			}
		);

		return count( $is_dropbox_direct_link ) > 0;
	}

	/**
	 * Check if a URL is a direct link to a Google Drive file
	 *
	 * @param string $url
	 * @return bool
	 */
	public static function is_google_drive_download_link( $url ) {
		$direct_urls = [
			'https://drive.google.com/uc',
		];

		$is_google_drive_direct_domain = array_filter(
			$direct_urls,
			function ( $domain ) use ( $url ) {
				return stripos( $url, $domain ) !== false;
			}
		);

		return count( $is_google_drive_direct_domain ) > 0 && str_contains( $url, 'export=download' );
	}

	/**
	 * Google Drive download URLs don't include the original filename, so we extract it from the temporary file
	 *
	 * @param array $file_array [ name, tmp_name ]
	 * @param string $download_url
	 *
	 * @return array [ name, tmp_name ]
	 */
	public static function maybe_update_imported_google_drive_file_name( $file_array, $download_url ) {

		if ( ! self::is_google_drive_download_link( $download_url ) ) {
			return $file_array;
		}

		$file_array['name'] = basename( $file_array['tmp_name'] );

		return $file_array;

	}

	/**
	 * Convert file url to full path.
	 *
	 * @param string $url url of the file.
	 * @return string|bool
	 */
	public static function get_file_url( $url ) {

		if ( strpos( $url, '/../' ) !== false ) {
			return false;
		}

		$upload_dir = wp_get_upload_dir();

		$file = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $url );

		if ( file_exists( $file ) ) {
			return $file;
		}

		return false;
	}

	/**
	 * Get the file extension from a file name
	 *
	 * @param string $url
	 * @return string|null
	 */
	public static function maybe_get_filename_from_url( $url ) {
		$path = wp_parse_url( $url, PHP_URL_PATH );

		if ( ! $path ) {
			return null;
		}

		$potential_file_name = basename( $path );

		// Check if the file name has an extension
		if ( strpos( $potential_file_name, '.' ) === false ) {
			return null;
		}

		return $potential_file_name;
	}

	/**
	 * Determine the mime type of an external file
	 *
	 * Accepts a full URL to a file and returns the mime type
	 *
	 * @param string $filename
	 * @return string
	 */
	public static function infer_external_file_mime_type( $filename ) {
		$file_type = wp_check_filetype( $filename );

		if ( ! $file_type['type'] ) {
			$file_type['type'] = 'application/octet-stream';
		}

		return $file_type['type'];
	}

	/**
	 * Get allowed preview mime_types
	 */
	public static function get_allowed_preview_mime_types() {
		$mimes = [
			'application/pdf',
			'application/x-pdf',
			'image/jpeg',
			'image/gif',
			'image/png',
			'image/webp',
			'image/svg+xml',
			'video/mp4',
			'video/ogg',
			'audio/mp3',
			'audio/mp4',
			'audio/mpeg',
			'audio/ogg',
			'audio/aac',
			'audio/aacp',
			'audio/flac',
			'audio/wav',
			'audio/webm',
		];

		/**
		 * Filter Whether to allow Word, Excel and Powerpoint documents to be previewed with the Office Web Viewer.
		 *
		 * @param bool $enabled
		 */
		if ( apply_filters( 'document_library_pro_enable_ms_office_preview', true ) ) {
			$mimes = array_merge(
				$mimes,
				self::get_office_mime_types()
			);
		}

		return $mimes;
	}

	/**
	 * Returns the Office mime types for the Office Web Viewer.
	 *
	 * Specifically, this is Excel, Word, and PowerPoint.
	 *
	 * @return string[]
	 */
	public static function get_office_mime_types() {
		return array_merge(
			self::get_ms_word_mime_types(),
			self::get_ms_excel_mime_types(),
			self::get_ms_powerpoint_mime_types()
		);
	}

	/**
	 * Get the MS Word mime types
	 *
	 * @return string[]
	 */
	public static function get_ms_word_mime_types() {
		return [
			'application/msword',
			'application/vnd.ms-write',
			'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
			'application/vnd.ms-word.document.macroEnabled.12',
			'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
			'application/vnd.ms-word.template.macroEnabled.12',
		];
	}

	/**
	 * Get the MS Excel mime types
	 *
	 * @return string[]
	 */
	public static function get_ms_excel_mime_types() {
		return [
			'application/vnd.ms-excel',
			'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
			'application/vnd.ms-excel.sheet.macroEnabled.12',
			'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
			'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
			'application/vnd.ms-excel.template.macroEnabled.12',
			'application/vnd.ms-excel.addin.macroEnabled.12',
		];
	}

	/**
	 * Get the MS PowerPoint mime types
	 *
	 * @return string[]
	 */
	public static function get_ms_powerpoint_mime_types() {
		return [
			'application/vnd.ms-powerpoint',
			'application/vnd.openxmlformats-officedocument.presentationml.presentation',
			'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
			'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
			'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
			'application/vnd.openxmlformats-officedocument.presentationml.template',
			'application/vnd.ms-powerpoint.template.macroEnabled.12',
			'application/vnd.ms-powerpoint.addin.macroEnabled.12',
			'application/vnd.openxmlformats-officedocument.presentationml.slide',
			'application/vnd.ms-powerpoint.slide.macroEnabled.12',
		];
	}

	/**
	 * Determine if PDF previews are available in WP via Imagick.
	 *
	 * @return bool
	 */
	public static function has_pdf_previews() {
		$fallback_sizes = [
			'thumbnail',
			'medium',
			'large',
		];

		if ( empty( apply_filters( 'fallback_intermediate_image_sizes', $fallback_sizes, [] ) ) ) {
			return false;
		}

		if ( ! extension_loaded( 'imagick' ) ) {
			return false;
		}

		if ( ! wp_image_editor_supports( [ 'mime_type' => 'application/pdf' ] ) ) {
			return false;
		}

		if ( ! class_exists( 'Imagick' ) ) {
			return false;
		}

		$imagick = new Imagick();
		$formats = $imagick->queryFormats();

		if ( in_array( 'PDF', $formats, true ) ) {
			return true;
		}

		return false;
	}
}