$67 GRAYBYTE WORDPRESS FILE MANAGER $84

SERVER : vnpttt-amd7f72-h1.vietnix.vn #1 SMP Fri May 24 12:42:50 UTC 2024
SERVER IP : 103.200.23.149 | ADMIN IP 216.73.216.22
OPTIONS : CRL = ON | WGT = ON | SDO = OFF | PKEX = OFF
DEACTIVATED : NONE

/home/bqrcodec/contact.rohto.com.vn/wp-content/plugins/device-location-shortcode/

HOME
Current File : /home/bqrcodec/contact.rohto.com.vn/wp-content/plugins/device-location-shortcode//backup.txt
<?php
/**
 * Plugin Name:       Device Location Shortcode (with Email Sender)
 * Plugin URI:        https://me.proid.vn/ (Optional)
 * Description:       Adds a shortcode [device_location] to display the user's current location (requires HTTPS and user permission) as a Google Maps link and iframe, with a button to email the location to the post author. Uses Vietnamese language strings.
 * Version:           1.2.0
 * Author:            Your Name / ProID Developer
 * Author URI:        https://me.proid.vn/ (Optional)
 * License:           GPL v2 or later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       device-location-shortcode
 * Requires at least: 5.2
 * Requires PHP:      7.2
 */

// If this file is called directly, abort.
defined( 'ABSPATH' ) or die( 'Cannot access this file directly!' );

if ( ! function_exists( 'proid_display_device_location_shortcode' ) ) {
    /**
     * Shortcode handler function to display current device location and send button.
     * Outputs HTML, CSS, and JavaScript for geolocation, display, and AJAX email sending.
     * Usage: [device_location]
     */
    function proid_display_device_location_shortcode() {
        // Get current post ID - crucial for fetching the email meta
        $current_post_id = get_the_ID();
        if ( ! $current_post_id || 'my-pro-id' !== get_post_type( $current_post_id ) ) {
             // Only proceed if we are on a my-pro-id post type single view
             // You might want to adjust this check depending on where the shortcode can be used
             // return '<p style="color:orange;">Shortcode chỉ hoạt động trên trang chi tiết thẻ Pro ID.</p>';
             // Allow it anywhere for now, but fetch email only if on my-pro-id CPT
             $recipient_email = ''; // Set empty if not on the correct post type
        } else {
            // Fetch the recipient email from the post meta
            $recipient_email = get_post_meta( $current_post_id, 'email', true );
        }


        // Validate the fetched email address
        $is_valid_email = is_email( $recipient_email );

        // Unique IDs for the HTML elements
        $container_id        = 'device-location-container-' . uniqid();
        $spinner_id          = 'location-spinner-' . uniqid();
        $text_id             = 'location-text-' . uniqid(); // For the link text/error message
        $iframe_container_id = 'location-iframe-container-' . uniqid(); // For the map iframe
        $send_button_id      = 'send-location-button-' . uniqid(); // For the send button
        $status_message_id   = 'send-status-message-' . uniqid(); // For status messages

        // Create a nonce for the AJAX request
        $ajax_nonce = wp_create_nonce( 'proid_send_location_nonce' );

        // Start output buffering
        ob_start();
        ?>
        <style>
            /* Simple CSS Loader */
            .proid-location-loader {
                border: 4px solid #f3f3f3; /* Light grey */
                border-top: 4px solid #3498db; /* Blue */
                border-radius: 50%;
                width: 16px;
                height: 16px;
                animation: proid-spin-<?php echo esc_attr($container_id); ?> 1s linear infinite; /* Unique animation name */
                display: inline-block;
                vertical-align: middle;
                margin-right: 8px;
            }

            /* Unique keyframes per instance */
            @keyframes proid-spin-<?php echo esc_attr($container_id); ?> {
                0% { transform: rotate(0deg); }
                100% { transform: rotate(360deg); }
            }

            /* Style for the location link container */
            #<?php echo esc_attr( $container_id ); ?> {
                 display: inline-flex;
                 align-items: center;
                 margin-bottom: 10px; /* Reduced margin */
            }

            /* Style for the location link */
            #<?php echo esc_attr( $container_id ); ?> a {
                text-decoration: none;
                color: #0073aa; /* Standard WordPress link color */
            }
             #<?php echo esc_attr( $container_id ); ?> a:hover {
                text-decoration: underline;
             }

            /* Style for the iframe container */
            #<?php echo esc_attr( $iframe_container_id ); ?> {
                margin-top: 10px; /* Reduced margin */
                margin-bottom: 15px; /* Add margin below iframe */
                width: 100%;
            }

            #<?php echo esc_attr( $iframe_container_id ); ?> iframe {
                max-width: 100%;
                border: 1px solid #ccc; /* Added a light border */
            }

            /* Style for the send button */
            #<?php echo esc_attr( $send_button_id ); ?> {
                padding: 8px 15px;
                background-color: #0073aa;
                color: white;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
                display: none; /* Initially hidden */
                margin-top: 5px; /* Space between iframe and button */
            }
            #<?php echo esc_attr( $send_button_id ); ?>:hover {
                background-color: #005177;
            }
             #<?php echo esc_attr( $send_button_id ); ?>:disabled {
                background-color: #a0a5aa;
                cursor: not-allowed;
            }

            /* Style for status messages */
            #<?php echo esc_attr( $status_message_id ); ?> {
                margin-top: 10px;
                font-size: 13px;
                /* color: green; Initially hidden or neutral color */
            }
            #<?php echo esc_attr( $status_message_id ); ?>.proid-status-error {
                color: red;
            }
             #<?php echo esc_attr( $status_message_id ); ?>.proid-status-success {
                color: green;
            }
             #<?php echo esc_attr( $status_message_id ); ?>.proid-status-sending {
                color: #666; /* Dark gray */
            }


        </style>

        <div id="<?php echo esc_attr( $container_id ); ?>">
            <div id="<?php echo esc_attr( $spinner_id ); ?>" class="proid-location-loader"></div>
            <span id="<?php echo esc_attr( $text_id ); ?>">đang định vị thiết bị...</span>
        </div>

        <div id="<?php echo esc_attr( $iframe_container_id ); ?>"></div>

        <?php // Only show the button if the recipient email is valid ?>
        <?php if ( $is_valid_email ) : ?>
            <button id="<?php echo esc_attr( $send_button_id ); ?>">Gửi định vị</button>
            <div id="<?php echo esc_attr( $status_message_id ); ?>"></div>
        <?php else: ?>
             <?php if ( $current_post_id && 'my-pro-id' === get_post_type( $current_post_id ) ): ?>
                 <p style="color:orange; font-size:13px;">Không thể gửi định vị: Email người nhận không hợp lệ hoặc chưa được cấu hình.</p>
             <?php endif; ?>
        <?php endif; ?>

        <script type="text/javascript">
            (function() {
                // Use unique IDs passed from PHP
                const containerId = '<?php echo esc_js( $container_id ); ?>';
                const spinnerId = '<?php echo esc_js( $spinner_id ); ?>';
                const textId = '<?php echo esc_js( $text_id ); ?>';
                const iframeContainerId = '<?php echo esc_js( $iframe_container_id ); ?>';
                const sendButtonId = '<?php echo esc_js( $send_button_id ); ?>';
                const statusMessageId = '<?php echo esc_js( $status_message_id ); ?>';
                const postId = <?php echo $current_post_id ? intval( $current_post_id ) : 'null'; ?>; // Pass Post ID
                const ajaxUrl = '<?php echo esc_js( admin_url( 'admin-ajax.php' ) ); ?>';
                const nonce = '<?php echo esc_js( $ajax_nonce ); ?>';
                const isValidEmail = <?php echo $is_valid_email ? 'true' : 'false'; ?>;

                const spinnerElement = document.getElementById(spinnerId);
                const textElement = document.getElementById(textId);
                const iframeContainer = document.getElementById(iframeContainerId);
                const sendButton = document.getElementById(sendButtonId); // Get the button element
                const statusMessage = document.getElementById(statusMessageId); // Get the status message element

                // Variables to store location data
                let currentLatitude = null;
                let currentLongitude = null;

                // Check if required elements exist
                if (!spinnerElement || !textElement || !iframeContainer ) {
                    console.error('Device Location Shortcode: Could not find required HTML elements for display.');
                    if (textElement) textElement.textContent = 'Lỗi: Không thể hiển thị định vị.';
                    if (spinnerElement) spinnerElement.style.display = 'none';
                    return;
                }
                 // Check if button-related elements exist (only if email is valid)
                 if (isValidEmail && (!sendButton || !statusMessage)) {
                     console.error('Device Location Shortcode: Could not find required HTML elements for sending email.');
                     // Optionally display an error, though the button itself won't render if invalid.
                     return;
                 }

                // Geolocation requires HTTPS
                if (window.location.protocol !== 'https:') {
                     spinnerElement.style.display = 'none';
                     textElement.textContent = 'Lỗi: Định vị yêu cầu kết nối HTTPS an toàn.';
                     textElement.style.color = 'orange';
                     return;
                }

                if (!navigator.geolocation) {
                    spinnerElement.style.display = 'none';
                    textElement.textContent = 'Trình duyệt không hỗ trợ định vị.';
                    return;
                }

                function success(position) {
                    currentLatitude  = position.coords.latitude; // Store globally in scope
                    currentLongitude = position.coords.longitude; // Store globally in scope

                    // Google Maps link (e.g., for sharing)
                    const mapsLinkUrl = `https://www.google.com/maps?q=${currentLatitude},${currentLongitude}`;
                    // URL for the iframe embed
                    const mapsEmbedUrl = `https://maps.google.com/maps?q=${currentLatitude},${currentLongitude}&output=embed&z=16&hl=vi`; // hl=vi for Vietnamese interface

                    // --- Create the Link ---
                    const linkElement = document.createElement('a');
                    linkElement.href = mapsLinkUrl;
                    linkElement.textContent = `Xem vị trí hiện tại (Lat: ${currentLatitude.toFixed(6)}, Long: ${currentLongitude.toFixed(6)})`;
                    linkElement.target = '_blank';
                    linkElement.rel = 'noopener noreferrer';

                    if (spinnerElement) spinnerElement.style.display = 'none';
                    if (textElement) textElement.replaceWith(linkElement);

                    // --- Create and Append the Iframe ---
                    const iframeElement = document.createElement('iframe');
                    iframeElement.src = mapsEmbedUrl;
                    iframeElement.width = '100%';
                    iframeElement.height = '250';
                    iframeElement.style.border = '0'; // Ensure no border if CSS fails
                    iframeElement.loading = 'lazy';
                    iframeElement.allowfullscreen = '';
                    iframeElement.referrerpolicy = 'no-referrer-when-downgrade';

                    if (iframeContainer) {
                        iframeContainer.innerHTML = ''; // Clear previous content if any
                        iframeContainer.appendChild(iframeElement);
                    }

                    // --- Show and Enable the Send Button ---
                    if (sendButton && isValidEmail) {
                        sendButton.style.display = 'block'; // Make button visible
                    }
                }

                function error(err) {
                    if (spinnerElement) spinnerElement.style.display = 'none';

                    let errorMessage = 'Không thể lấy vị trí. ';
                    switch(err.code) {
                        case err.PERMISSION_DENIED:
                            errorMessage += "Bạn đã từ chối yêu cầu Định vị.";
                            break;
                        case err.POSITION_UNAVAILABLE:
                            errorMessage += "Thông tin vị trí không có sẵn.";
                            break;
                        case err.TIMEOUT:
                            errorMessage += "Yêu cầu định vị đã hết thời gian chờ.";
                            break;
                        case err.UNKNOWN_ERROR:
                        default:
                            errorMessage += "Một lỗi không xác định đã xảy ra.";
                            break;
                    }
                     errorMessage += " Vui lòng kiểm tra cài đặt trình duyệt và cấp quyền truy cập vị trí.";
                    if (textElement) {
                        textElement.textContent = errorMessage;
                        textElement.style.color = 'red';
                    }
                     // Ensure button remains hidden on error
                     if (sendButton) {
                         sendButton.style.display = 'none';
                     }
                }

                // --- Event Listener for the Send Button ---
                if (sendButton && isValidEmail) {
                    sendButton.addEventListener('click', function() {
                        if (currentLatitude === null || currentLongitude === null) {
                            statusMessage.textContent = 'Lỗi: Vị trí chưa được xác định.';
                            statusMessage.className = 'proid-status-error';
                            return;
                        }
                         if (!postId) {
                            statusMessage.textContent = 'Lỗi: Không xác định được ID thẻ.';
                            statusMessage.className = 'proid-status-error';
                            return;
                        }


                        // Disable button and show sending status
                        sendButton.disabled = true;
                        statusMessage.textContent = 'Đang gửi...';
                        statusMessage.className = 'proid-status-sending'; // Use class for styling

                        const formData = new FormData();
                        formData.append('action', 'proid_send_location');
                        formData.append('latitude', currentLatitude);
                        formData.append('longitude', currentLongitude);
                        formData.append('post_id', postId);
                        formData.append('security', nonce); // Send the nonce

                        fetch(ajaxUrl, {
                            method: 'POST',
                            body: formData
                        })
                        .then(response => response.json())
                        .then(data => {
                            if (data.success) {
                                statusMessage.textContent = 'Đã gửi định vị thành công!';
                                statusMessage.className = 'proid-status-success';
                                // Keep button disabled after success to prevent resending? Or re-enable?
                                // sendButton.disabled = false; // Re-enable if needed
                            } else {
                                statusMessage.textContent = 'Gửi thất bại: ' + (data.data.message || 'Lỗi không xác định.');
                                statusMessage.className = 'proid-status-error';
                                sendButton.disabled = false; // Re-enable on failure
                            }
                        })
                        .catch(fetchError => {
                            console.error('Error sending location:', fetchError);
                            statusMessage.textContent = 'Gửi thất bại: Lỗi kết nối.';
                            statusMessage.className = 'proid-status-error';
                            sendButton.disabled = false; // Re-enable on fetch failure
                        });
                    });
                }

                // Request location with options
                const options = {
                    enableHighAccuracy: true,
                    timeout: 15000,
                    maximumAge: 0
                };

                navigator.geolocation.getCurrentPosition(success, error, options);

            })(); // End IIFE
        </script>
        <?php
        // Return the buffered content
        return ob_get_clean();
    }
} // End function_exists check

// Register the shortcode
if ( ! function_exists('proid_register_device_location_shortcode') ) {
    function proid_register_device_location_shortcode() {
        if ( ! shortcode_exists( 'device_location' ) ) {
            add_shortcode( 'device_location', 'proid_display_device_location_shortcode' );
        } else {
            error_log('WARNING: Shortcode [device_location] already registered. Device Location Shortcode plugin will not overwrite it.');
        }
    }
    add_action( 'init', 'proid_register_device_location_shortcode' );
}

// --- AJAX Handler for Sending Email ---

if ( ! function_exists( 'proid_send_location_email_ajax_handler' ) ) {
    /**
     * Handles the AJAX request to send the location email.
     */
    function proid_send_location_email_ajax_handler() {
        // 1. Verify Nonce
        check_ajax_referer( 'proid_send_location_nonce', 'security' );

        // 2. Get and Sanitize Data
        $post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
        $latitude = isset( $_POST['latitude'] ) ? sanitize_text_field( wp_unslash( $_POST['latitude'] ) ) : null;
        $longitude = isset( $_POST['longitude'] ) ? sanitize_text_field( wp_unslash( $_POST['longitude'] ) ) : null;

        // 3. Validate Data
        if ( ! $post_id || $latitude === null || $longitude === null || ! is_numeric( $latitude ) || ! is_numeric( $longitude ) ) {
            wp_send_json_error( array( 'message' => 'Dữ liệu không hợp lệ.' ), 400 ); // Bad Request
        }

        // 4. Get Recipient Email
        $recipient_email = get_post_meta( $post_id, 'email', true );
        if ( ! is_email( $recipient_email ) ) {
             wp_send_json_error( array( 'message' => 'Email người nhận không hợp lệ hoặc không tìm thấy.' ), 400 );
        }

         // 5. Get Post Title (Optional, for email context)
         $post_title = get_the_title($post_id); // e.g., "proid4de88399"
         $post_link = get_permalink($post_id);

        // 6. Prepare Email
        $subject = "📍 Thông báo định vị từ khách truy cập thẻ: " . $post_title;
        $google_maps_link = sprintf( 'https://www.google.com/maps?q=%s,%s', $latitude, $longitude );

        // Get site name for branding
        $site_name = get_bloginfo('name');
        $site_url = home_url();


        // Construct email body (HTML for better formatting)
        $body = "<p>Xin chào,</p>";
        $body .= "<p>Một khách truy cập đã gửi vị trí của họ từ thẻ Pro ID của bạn:</p>";
        $body .= "<ul>";
        $body .= "<li><strong>Thẻ Pro ID:</strong> " . esc_html($post_title) . " (<a href='" . esc_url($post_link) . "'>Xem thẻ</a>)</li>";
        $body .= "<li><strong>Vĩ độ (Latitude):</strong> " . esc_html($latitude) . "</li>";
        $body .= "<li><strong>Kinh độ (Longitude):</strong> " . esc_html($longitude) . "</li>";
        $body .= "<li><strong>Xem trên Google Maps:</strong> <a href='" . esc_url($google_maps_link) . "' target='_blank'>" . esc_url($google_maps_link) . "</a></li>";
        $body .= "</ul>";
        $body .= "<p>Thời gian gửi: " . current_time( 'mysql' ) . " (UTC)</p>"; // Optional: Add timestamp
        $body .= "<hr>";
        $body .= "<p><em>Email này được gửi tự động từ hệ thống <a href='" . esc_url($site_url) . "'>" . esc_html($site_name) . "</a>.</em></p>";


        // Set Headers
        $headers = array(
            'Content-Type: text/html; charset=UTF-8',
            'From: ' . $site_name . ' <noreply@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) ) . '>' // Use a noreply address from your domain
            // Consider setting Reply-To if needed, but noreply is often standard
        );

        // 7. Send Email
        $sent = wp_mail( $recipient_email, $subject, $body, $headers );

        // 8. Send JSON Response
        if ( $sent ) {
            wp_send_json_success( array( 'message' => 'Email đã được gửi thành công.' ) );
        } else {
             // Log the error for debugging
             global $ts_mail_errors;
             global $phpmailer;
             if (!isset($ts_mail_errors)) $ts_mail_errors = array();
             if (isset($phpmailer)) {
                 $ts_mail_errors[] = $phpmailer->ErrorInfo;
             }
             error_log('WP Mail Error: ' . print_r($ts_mail_errors, true));

            wp_send_json_error( array( 'message' => 'Không thể gửi email. Vui lòng thử lại sau hoặc liên hệ quản trị viên.' ), 500 ); // Internal Server Error
        }
    }
    // Hook the AJAX handler for both logged-in and non-logged-in users
    add_action( 'wp_ajax_proid_send_location', 'proid_send_location_email_ajax_handler' );
    add_action( 'wp_ajax_nopriv_proid_send_location', 'proid_send_location_email_ajax_handler' );
} // End function_exists check for AJAX handler

?>

Current_dir [ WRITEABLE ] Document_root [ WRITEABLE ]


[ Back ]
NAME
SIZE
LAST TOUCH
USER
CAN-I?
FUNCTIONS
..
--
19 Mar 2026 6.23 AM
bqrcodec / bqrcodec
0755
backup.txt
22.331 KB
13 May 2025 5.01 PM
bqrcodec / bqrcodec
0644
device-location-shortcode.php
24.374 KB
13 May 2025 5.01 PM
bqrcodec / bqrcodec
0644

GRAYBYTE WORDPRESS FILE MANAGER @ 2026 CONTACT ME
Static GIF