. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AnonSec Shell
AnonSec Shell
Server IP : 54.36.91.62  /  Your IP : 216.73.216.87   [ Reverse IP ]
Web Server : Apache
System : Linux webm002.cluster127.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
User : eticmes ( 123698)
PHP Version : 7.4.33
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
Domains : 2 Domains
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/eticmes/www/wp-content/plugins/newsletter-import/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     [ BACKUP SHELL ]     [ JUMPING ]     [ MASS DEFACE ]     [ SCAN ROOT ]     [ SYMLINK ]     

Current File : /home/eticmes/www/wp-content/plugins/newsletter-import/plugin.php
<?php

// phpcs:disable WordPress.WP.Capabilities.Unknown
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
// phpcs:disable WordPress.WP.AlternativeFunctions.unlink_unlink
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fopen
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fclose
// phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_is_writable
// phpcs:disable WordPress.PHP.NoSilencedErrors.Discouraged

defined('ABSPATH') || exit;

class NewsletterImport extends NewsletterAddon {

    /**
     * @var NewsletterImport
     */
    static $instance;

    public function __construct($version = '0.0.0') {
        self::$instance = $this;
        parent::__construct('import', $version, __DIR__);
        $this->setup_options();
        add_action('newsletter_import_run', array($this, 'hook_newsletter_import_run'));
    }

    function upgrade($first_install = false) {
        parent::upgrade($first_install);
        $this->stop();
    }

    function init() {
        parent::init();

        if (is_admin()) {
            if (Newsletter::instance()->is_allowed()) {
                add_action('admin_menu', [$this, 'hook_admin_menu'], 100);
                add_filter('newsletter_menu_subscribers', [$this, 'hook_newsletter_menu_subscribers']);
                if (defined('DOING_AJAX') && DOING_AJAX) {
                    add_action('wp_ajax_newsletter_import', [$this, 'hook_wp_ajax_newsletter_import']);
                    add_action('wp_ajax_newsletter_import_mailpoet', [$this, 'hook_wp_ajax_newsletter_import_mailpoet']);
                    add_action('wp_ajax_newsletter_import_restore', [$this, 'hook_wp_ajax_newsletter_import_restore']);
                    add_action('wp_ajax_newsletter_import_export', [$this, 'hook_wp_ajax_newsletter_import_export']);
                }
            }
        }
    }

    function weekly_check() {
        parent::weekly_check();
        $license_key = Newsletter::instance()->get_license_key();
        $response = wp_remote_post('https://www.thenewsletterplugin.com/wp-content/addon-check.php?k=' . rawurlencode($license_key)
                . '&a=' . rawurlencode($this->name) . '&d=' . rawurlencode(home_url()) . '&b=' . rawurlencode(site_url()) . '&v=' . rawurlencode($this->version)
                . '&ml=' . (Newsletter::instance()->is_multilanguage() ? '1' : '0'));
    }

    function hook_newsletter_menu_subscribers($entries) {
        $entries[] = ['label' => 'Import/Export', 'url' => '?page=newsletter_import_index'];
        return $entries;
    }

    function hook_admin_menu() {
        add_submenu_page('newsletter_main_index', __('Import/Export', 'newsletter'), '<span class="tnp-side-menu">' . __('Import/Export', 'newsletter') . '</span>', 'exist', 'newsletter_import_index', function () {
            require __DIR__ . '/admin/index.php';
        });
        add_submenu_page('admin.php', 'CSV import', 'CSV import', 'exist', 'newsletter_import_csv', function () {
            require __DIR__ . '/admin/csv.php';
        });
        add_submenu_page('admin.php', 'Excel import', 'Excel import', 'exist', 'newsletter_import_excel', function () {
            require __DIR__ . '/admin/excel.php';
        });
        add_submenu_page('admin.php', 'Copy&Paste import', 'Copy&Paste import', 'exist', 'newsletter_import_clipboard', function () {
            require __DIR__ . '/admin/clipboard.php';
        });
        add_submenu_page('admin.php', 'Bounce import', 'Bounce import', 'exist', 'newsletter_import_bounce', function () {
            require __DIR__ . '/admin/bounce.php';
        });
        add_submenu_page('admin.php', 'MailPoet import', 'MailPoet import', 'exist', 'newsletter_import_mailpoet', function () {
            require __DIR__ . '/admin/mailpoet.php';
        });
        add_submenu_page('admin.php', 'Export', 'Export', 'exist', 'newsletter_import_export', function () {
            require __DIR__ . '/admin/export.php';
        });
//        add_submenu_page('admin.php', 'Dump', 'Dump', 'exist', 'newsletter_import_dump', function () {
//            require __DIR__ . '/admin/dump.php';
//        });
//        add_submenu_page('admin.php', 'Restore', 'Restore', 'exist', 'newsletter_import_restore', function () {
//            require __DIR__ . '/admin/dump.php';
//        });
    }

    function hook_wp_ajax_newsletter_import() {
        // Object caching plugin, sometimes, do no refresh the cache for ajax calls
        wp_cache_flush();
        wp_cache_delete('newsletter_import', 'options');
        $this->options = null;
        $this->setup_options();

        $this->hook_newsletter_import_run(10);
        $data = [];
        $data['completed'] = !$this->is_importing();
        ob_start();
        include __DIR__ . '/admin/progress.php';
        $data['html'] = ob_get_clean();
        $data['progress'] = $this->get_progress();
        header('Content-Type: application/json');
        echo wp_json_encode($data);
        die();
    }

    function hook_newsletter_import_run($max_run_time = 30) {

        $logger = $this->get_logger();

        if (get_transient('newsletter_import')) {
            $logger->error('Import job already running');
            return;
        }

        @setlocale(LC_CTYPE, 'en_US.UTF-8');
        @set_time_limit(0);
        set_transient('newsletter_import', time(), $max_run_time + 10);
        $logger->info('Starting');

        // It could have been removed
        $position = $this->get_position();
        if ($position === -1) {
            $logger->info('Job stopped');
            $this->stop();
            return;
        }

        $position = (int) $position;

        $options = $this->options;

        $handle = fopen($this->get_filename(), 'r');
        if (!$handle) {
            $logger->fatal('File disappeared...');
            $this->stop();
            return;
        }

        $stats = get_option('newsletter_import_stats');

        $logger->info('Starting from ' . $position);
        fseek($handle, $position);

        // Skips the first line
        if ($position === 0) {
            $line = fgets($handle);
            $this->log('Line 1 - Column names: ' . trim($line));
        }

        $mode = $options['mode'];
        $logger->debug('Mode ' . $mode);

        $newsletter = Newsletter::instance();

        $email_idx = (int) $options['email'] - 1;
        $first_name_idx = (int) $options['first_name'] - 1;
        $last_name_idx = (int) $options['last_name'] - 1;
        $gender_idx = (int) $options['gender'] - 1;
        $country_idx = (int) $options['country'] - 1;
        $region_idx = (int) $options['region'] - 1;
        $ip_idx = (int) $options['ip'] - 1;
        $language_idx = (int) $options['language'] - 1;
        $city_idx = (int) $options['city'] - 1;

        $start = time();
        while (($line = fgets($handle)) !== false && time() < $start + $max_run_time) {
            $this->set_position(ftell($handle));

            $line = trim($line);

            $logger->debug('Processing ' . $line);

            $stats['total']++;

            if (empty($line)) {
                $stats['empty']++;
                update_option('newsletter_import_stats', $stats);
                continue;
            }

            if (!mb_check_encoding($line, "UTF-8")) {
                $this->log('Line ' . ($stats['total'] + 1) . ' - Wrong UTF-8 enconding, check if the file has been saved as UTF-8');
                $logger->fatal('Line ' . $line . ' is not UTF-8 encoded');
                $stats['errors']++;
                update_option('newsletter_import_stats', $stats);
                continue;
            }

            // For fatal logging...
            $text_line = $line;

            //$line = preg_split('/[,;\t]/', $line);
            //$line = array_map('trim', $line);

            $line = str_getcsv($line, $options['delimiter'], '"');
            $email = $newsletter->normalize_email($line[$email_idx]);
            $logger->info('Current email: ' . $email);
            if (!$email) {
                $this->log('Line ' . ($stats['total'] + 1) . ' - Invalid email address');
                $logger->fatal('Invalid email on line ' . $text_line);
                $stats['errors']++;
                update_option('newsletter_import_stats', $stats);
                continue;
            }

            // Get subscriber

            $subscriber = $newsletter->get_user($email, ARRAY_A);
            if ($subscriber == null) {
                $logger->info('New subscriber');
                $subscriber = array();
                $subscriber['email'] = $email;
                $subscriber['last_activity'] = time();

                if ($first_name_idx > -1 && isset($line[$first_name_idx])) {
                    $subscriber['name'] = mb_strimwidth($newsletter->normalize_name($line[$first_name_idx]), 0, 100);
                }

                if ($last_name_idx > -1 && isset($line[$last_name_idx])) {
                    $subscriber['surname'] = mb_strimwidth($newsletter->normalize_name($line[$last_name_idx]), 0, 100);
                }

                if ($country_idx > -1 && isset($line[$country_idx])) {
                    $country = strtoupper(trim($line[$country_idx]));

                    if (strlen($country) > 2) {
                        $this->log('Line ' . ($stats['total'] + 1) . ' - Invalid country code 2 digit ISO format: ' . $country);
                        $logger->fatal('Country "' . $line[$country_idx] . '" is not 2 digit ISO format on line ' . $text_line);
                        $stats['errors']++;
                        update_option('newsletter_import_stats', $stats);
                        continue;
                    }
                    $subscriber['country'] = $country;
                }

                if ($region_idx > -1 && isset($line[$region_idx])) {
                    $subscriber['region'] = mb_strimwidth(trim($line[$region_idx]), 0, 100);
                }

                if ($ip_idx > -1 && isset($line[$ip_idx])) {
                    $subscriber['ip'] = trim($line[$ip_idx]);
                }

                if ($language_idx > -1 && isset($line[$language_idx])) {
                    $subscriber['language'] = mb_strimwidth(strtolower(trim($line[$language_idx])), 0, 2);
                }

                if ($gender_idx > -1 && isset($line[$gender_idx])) {
                    $gender = strtolower(trim($line[$gender_idx]));
                    if (!empty($gender)) {
                        $gender = substr($gender, 0, 1);
                        if ($gender != 'f' && $gender != 'm' && $gender != 'n') {
                            $this->log('Line ' . ($stats['total'] + 1) . ' - Invalid gender (not one of M, F, N): ' . $gender);
                            $logger->fatal('Gender is invalid on line ' . $text_line);
                            $stats['errors']++;
                            update_option('newsletter_import_stats', $stats);
                            continue;
                        }
                        $subscriber['sex'] = $gender;
                    }
                }

                if ($city_idx > -1 && isset($line[$city_idx])) {
                    $subscriber['city'] = trim($line[$city_idx]);
                }

                $subscriber['status'] = $options['import_as'];

                if (!empty($options['lists'])) {
                    foreach ($options['lists'] as $i) {
                        $subscriber['list_' . $i] = '1';
                    }
                }

                $profiles = $newsletter->get_profiles();
                foreach ($profiles as $profile) {
                    $profile_idx = (int) $options['profile_' . $profile->id] - 1;
                    if ($profile_idx > -1 && isset($line[$profile_idx])) {
                        $subscriber['profile_' . $profile->id] = mb_strimwidth(trim($line[$profile_idx]), 0, 250);
                    }
                }

                $newsletter->save_user($subscriber);
                $stats['new']++;
                //$logger->debug($subscriber);
            } else {
                $logger->info('Matched subscriber ID ' . $subscriber['id']);
                if ($mode == 'skip') {
                    $logger->info('Skipped');
                    $stats['skipped']++;
                    update_option('newsletter_import_stats', $stats);
                    continue;
                }

                if ($mode == 'overwrite') {
                    // Clean up the subscriber
                    $subscriber['name'] = '';
                    $subscriber['surname'] = '';
                    $subscriber['sex'] = 'n';
                    for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
                        $subscriber['profile_' . $i] = '';
                    }
                    for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
                        $subscriber['list_' . $i] = 0;
                    }
                    $subscriber['country'] = '';
                    $subscriber['region'] = '';
                    $subscriber['city'] = '';
                }

                if ($language_idx > -1 && isset($line[$language_idx])) {
                    $subscriber['language'] = strtolower(trim($line[$language_idx]));
                }

                if ($first_name_idx > -1) {
                    $subscriber['name'] = mb_strimwidth($newsletter->normalize_name($line[$first_name_idx]), 0, 100);
                }
                if ($last_name_idx > -1) {
                    $subscriber['surname'] = mb_strimwidth($newsletter->normalize_name($line[$last_name_idx]), 0, 100);
                }
                if ($gender_idx > -1) {
                    $gender = strtolower($line[$gender_idx]);
                    if (!empty($gender)) {
                        $gender = substr($gender, 0, 1);
                        if ($gender != 'f' && $gender != 'm' && $gender != 'n') {
                            $this->log('Line ' . ($stats['total'] + 1) . ' - Invalid genderr (not one of M, F, N): ' . $gender);
                            $logger->fatal('Gender is invalid on line ' . $text_line);
                            $stats['errors']++;
                            update_option('newsletter_import_stats', $stats);
                            continue;
                        }
                        $subscriber['sex'] = $gender;
                    }
                }
                if (isset($options['override_status'])) {
                    $subscriber['status'] = $options['import_as'];
                }
                if ($country_idx > -1 && isset($line[$country_idx])) {
                    $country = strtoupper(trim($line[$country_idx]));

                    if (strlen($country) > 2) {
                        $this->log('Line ' . ($stats['total'] + 1) . ' - Invalid country code 2 digit ISO format: ' . $country);
                        $logger->fatal('Country "' . $line[$country_idx] . '" is not 2 digit ISO format on line ' . $text_line);
                        $stats['errors']++;
                        update_option('newsletter_import_stats', $stats);
                        continue;
                    }
                    $subscriber['country'] = $country;
                }
                if ($region_idx > -1 && isset($line[$region_idx])) {
                    $subscriber['region'] = mb_strimwidth(trim($line[$region_idx]), 0, 100);
                }
                if ($city_idx > -1 && isset($line[$city_idx])) {
                    $subscriber['city'] = mb_strimwidth(trim($line[$city_idx]), 0, 100);
                }


                foreach ($options['lists'] as $i) {
                    $subscriber['list_' . $i] = 1;
                }

                $profiles = $newsletter->get_profiles();
                foreach ($profiles as $profile) {
                    $profile_idx = (int) $options['profile_' . $profile->id] - 1;
                    if ($profile_idx > -1 && isset($line[$profile_idx])) {
                        $subscriber['profile_' . $profile->id] = mb_strimwidth(trim($line[$profile_idx]), 0, 250);
                    }
                }

                //$logger->debug($subscriber);
                $newsletter->save_user($subscriber);
                $stats['updated']++;
            }
            update_option('newsletter_import_stats', $stats);

            // TODO: Remove is for test
            //break;
        }
        fclose($handle);
        if ($line === false) {
            $logger->info('Finished');
            $this->stop();
            return true;
        } else {
            $logger->info('To be continued');
            //wp_schedule_single_event(time()+5, 'newsletter_import_run');
        }
        delete_transient('newsletter_import');
        return false;
    }

    function stop() {
        $this->delete_file();
        delete_transient('newsletter_import');
        update_option('newsletter_import_position', -1, false);
        //$p = $this->get_position();
        //$this->get_logger()->debug('Position: ' . var_export($p, true));
    }

    function start() {
        $this->set_position(0);
        update_option('newsletter_import_stats', array('total' => 0, 'errors' => 0, 'new' => 0, 'updated' => 0, 'skipped' => 0, 'empty' => 0), false);
        @unlink(NEWSLETTER_LOG_DIR . '/import-report.txt');
    }

    function log($line) {
        file_put_contents(NEWSLETTER_LOG_DIR . '/import-report.txt', $line . "\n", FILE_APPEND);
    }

    function is_importing() {
        return $this->has_file() && $this->get_position() != -1;
    }

    function get_position() {
        wp_cache_flush();
        wp_cache_delete('newsletter_import_position', 'options');
        return (int) get_option('newsletter_import_position', -1);
    }

    function set_position($position) {
        update_option('newsletter_import_position', $position, false);
    }

    function has_file() {
        return file_exists($this->get_filename());
    }

    function has_restore_file() {
        return file_exists($this->get_filename());
    }

    function get_filename() {
        return $this->get_dir() . '/import.csv';
    }

    function get_restore_filename() {
        return $this->get_dir() . '/restore.csv';
    }

    function get_restore_fields_filename() {
        return $this->get_dir() . '/restore-fields.json';
    }

    function get_dir() {
        $dir = wp_upload_dir();
        return $dir['basedir'] . '/newsletter/import';
    }

    /**
     *
     * @return \WP_Error|boolean
     */
    function prepare_dir() {
        $dir = $this->get_dir();
        $r = wp_mkdir_p($dir);
        if (!$r || !is_writable($dir) || !is_readable($dir)) {
            return new WP_Error(1, 'The folder "' . esc_html($dir) . '" cannot be created or is not writable/readable. Ask for support to your provider.');
        }

        $file = $this->get_filename();

        if (file_exists($file)) {
            $r = unlink($file);
            if (!$r) {
                return new WP_Error(2, 'The old import file "' . esc_html($file) . '" cannot be deleted. Ask for support to your provider.');
            }
        }

        $file = $this->get_restore_filename();

        if (file_exists($file)) {
            $r = unlink($file);
            if (!$r) {
                return new WP_Error(2, 'The old restore file "' . esc_html($file) . '" cannot be deleted. Ask for support to your provider.');
            }
        }

        $file = $this->get_restore_fields_filename();

        if (file_exists($file)) {
            $r = unlink($file);
            if (!$r) {
                return new WP_Error(2, 'The old restore file "' . esc_html($file) . '" cannot be deleted. Ask for support to your provider.');
            }
        }

        file_put_contents($dir . '/.htaccess', "<IfModule mod_authz_core.c>\nRequire all denied\n</IfModule>\n<IfModule !mod_authz_core.c>\nOrder deny,allow\nDeny from all\n</IfModule>");
        //return new WP_Error(1, 'Test error condition');
        return true;
    }

    function get_progress() {
        $position = get_option('newsletter_import_position');
        $total = filesize($this->get_filename());
        if (!$total)
            return 100;
        return (int) ($position * 100 / $total);
    }

    function get_restore_progress() {
        $position = get_option('newsletter_import_restore_position');
        $total = filesize($this->get_restore_filename());
        if (!$total)
            return 100;
        return (int) ($position * 100 / $total);
    }

    function delete_file() {
        $fn = $this->get_filename();
        if (file_exists($fn)) {
            return unlink($fn);
        }
    }

    function delete_restore_file() {
        $fn = $this->get_restore_filename();
        if (file_exists($fn)) {
            return unlink($fn);
        }
    }

    function hook_wp_ajax_newsletter_import_export() {
        require_once NEWSLETTER_INCLUDES_DIR . '/controls.php';
        $controls = new NewsletterControls();

        if ($controls->is_action('export')) {
            $this->export($controls->data);
        }
    }

    function sanitize_csv($text) {
        $text = str_replace(['"', "\n", "\r", ";"], ["'", " ", " ", " "], $text);

        // Excel... of course!
        $first = substr($text, 0, 1);
        if ($first === '=' || $first === '+' || $first === '-' || $first === '@') {
            $text = "'" . $text;
        }

        return $text;
    }

    function restore() {

    }

    function dump($options = null) {
        global $wpdb;

        @setlocale(LC_CTYPE, 'en_US.UTF-8');
        header('Content-Type: application/octet-stream;charset=UTF-8');
        header('Content-Disposition: attachment; filename="newsletter-subscribers.csv"');

        // BOM
        echo "\xEF\xBB\xBF";

        $fields = ['id', 'email', 'status', 'token', 'name', 'surname', 'sex', 'created', 'language', 'wp_user_id', 'last_activity',
            'ip', 'referrer', 'http_referer', 'country', 'region', 'city'];

        for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
            $fields[] = "list_$i";
        }

        // In table profiles
        for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
            $fields[] = "profile_$i";
        }

        $line = implode(';', $fields);
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
        echo $line, "\n";

        $page = 0;
        while (true) {

            $list = $wpdb->get_results($wpdb->prepare("select * from " . NEWSLETTER_USERS_TABLE . " order by id limit %d, 500", $page * 500));
            foreach ($list as $item) {
                foreach ($fields as $field) {
                    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
                    echo $this->sanitize_csv($item->$field), ';';
                }
                echo "\n";
                flush();
            }

            if (count($list) < 500) {
                break;
            }
            $page++;
        }
        die();
    }

    /**
     *
     * @global type $wpdb
     * @param type $optionsù
     * phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
     */
    function export($options = null) {
        global $wpdb;

        @setlocale(LC_CTYPE, 'en_US.UTF-8');
        header('Content-Type: application/octet-stream;charset=UTF-8');
        header('Content-Disposition: attachment; filename="newsletter-subscribers.csv"');

        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $options = wp_unslash($_POST['options'] ?? []);

        // BOM
        echo "\xEF\xBB\xBF";

        $sep = ';';
        if ($options) {
            $sep = $options['separator'];
        }
        if ($sep == 'tab') {
            $sep = "\t";
        }

        // CSV header
        echo '"Email"' . $sep . '"Name"' . $sep . '"Surname"' . $sep . '"Gender"' . $sep . '"Status"' . $sep . '"Date"' . $sep . '"Token"' . $sep;

        // In table profiles
        for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
            echo '"Profile ' . $i . '"' . $sep; // To adjust with field name
        }

        // Lists
        for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
            echo '"List ' . $i . '"' . $sep;
        }


        echo '"Feed by mail"' . $sep . '"Follow up"' . $sep;
        echo '"IP"' . $sep . '"Referrer"' . $sep . '"Country"' . $sep . '"Language"' . $sep;
        echo '"ID"' . $sep . '"WP User ID"' . $sep;
        echo '"Last Activity"' . $sep;

        echo "\n";

        $page = 0;
        while (true) {
            $query = "select * from " . NEWSLETTER_USERS_TABLE . " where 1=1";
            $list = (int) $options['list'];
            if (!empty($list)) {
                $query .= " and list_" . $list . "=1";
            }

            $status = $options['status'];
            if (!empty($status)) {
                $status = substr($status, 0, 1);
                $query .= " and status='" . esc_sql($status) . "'";
            }

            $recipients = $wpdb->get_results($wpdb->prepare($query . " order by email limit %d, 500", $page * 500));
            for ($i = 0; $i < count($recipients); $i++) {
                echo '"' . $recipients[$i]->email . '"' . $sep;
                echo '"' . $this->sanitize_csv($recipients[$i]->name) . '"' . $sep;
                echo '"' . $this->sanitize_csv($recipients[$i]->surname) . '"' . $sep;
                echo '"' . $recipients[$i]->sex . '"' . $sep;
                echo '"' . $recipients[$i]->status . '"' . $sep;
                echo '"' . $recipients[$i]->created . '"' . $sep;
                echo '"' . $recipients[$i]->token . '"' . $sep;

                for ($j = 1; $j <= NEWSLETTER_PROFILE_MAX; $j++) {
                    $column = 'profile_' . $j;
                    echo '"' . $this->sanitize_csv($recipients[$i]->$column) . '"' . $sep;
                }

                for ($j = 1; $j <= NEWSLETTER_LIST_MAX; $j++) {
                    $list = 'list_' . $j;
                    echo '"' . $recipients[$i]->$list . '"' . $sep;
                }

                echo '"' . $recipients[$i]->feed . '"' . $sep;
                echo '"' . $recipients[$i]->followup . '"' . $sep;
                echo '"' . $this->sanitize_csv($recipients[$i]->ip) . '"' . $sep;
                echo '"' . $this->sanitize_csv($recipients[$i]->referrer) . '"' . $sep;
                echo '"' . $this->sanitize_csv($recipients[$i]->country) . '"' . $sep;
                echo '"' . $this->sanitize_csv($recipients[$i]->language) . '"' . $sep;
                echo '"' . $recipients[$i]->id . '"' . $sep;
                echo '"' . $recipients[$i]->wp_user_id . '"' . $sep;
                echo '"' . date('Y-m-d H:i:s', $recipients[$i]->last_activity) . '"' . $sep;

                echo "\n";
                flush();
            }
            if (count($recipients) < 500) {
                break;
            }
            $page++;
        }
        die();
    }

    function mp_stop() {
        delete_transient('newsletter_import_mailpoet');
        update_option('newsletter_import_mailpoet_position', -1, false);
        //$p = $this->get_position();
        //$this->get_logger()->debug('Position: ' . var_export($p, true));
    }

    function mp_start() {
        $this->mp_set_position(0);
        update_option('newsletter_import_mailpoet_stats', array('total' => 0, 'errors' => 0, 'new' => 0, 'updated' => 0, 'skipped' => 0, 'empty' => 0), false);
    }

    function mp_is_importing() {
        return $this->mp_get_position() != -1;
    }

    function mp_get_position() {
        wp_cache_flush();
        wp_cache_delete('newsletter_import_mailpoet_position', 'options');
        return (int) get_option('newsletter_import_mailpoet_position', -1);
    }

    function mp_set_position($position) {
        update_option('newsletter_import_mailpoet_position', $position, false);
    }

    function hook_wp_ajax_newsletter_import_mailpoet() {
        // Object caching plugin, sometimes, do no refresh the cache for ajax calls
        wp_cache_flush();
        wp_cache_delete('newsletter_import_mailpoet', 'options');
        $this->options = null;
        $this->setup_options();

        $this->hook_newsletter_import_run_mp(10);
        $data = [];
        $data['completed'] = !$this->mp_is_importing();
        ob_start();
        include __DIR__ . '/admin/mailpoet-progress.php';
        $data['html'] = ob_get_clean();
        $data['progress'] = $this->mp_get_progress();
        header('Content-Type: application/json');
        echo wp_json_encode($data);
        die();
    }

    function mp_get_progress() {
        $position = get_option('newsletter_import_mailpoet_position');
        return (int) ($position);
    }

    function hook_newsletter_import_run_mp($max_run_time = 30) {

        global $wpdb;
        $logger = $this->get_logger();

        if (get_transient('newsletter_import_mailpoet')) {
            $logger->error('Import job already running');
            return;
        }

        @setlocale(LC_CTYPE, 'en_US.UTF-8');
        @set_time_limit(0);
        set_transient('newsletter_import_mailpoet', time(), $max_run_time + 10);
        $logger->info('Starting');

        // It could have been removed
        $last_mp_id = $this->mp_get_position();
        if ($last_mp_id === -1) {
            $logger->info('Job stopped');
            $this->stop();
            return;
        }

        $options = get_option('newsletter_import_mailpoet');
        $lists = implode(",", array_map('absint', $options['lists']));

        $subscribers_result = $wpdb->get_results(
                "SELECT sub.id, sub.wp_user_id, sub.first_name, sub.last_name, sub.email, sub.status FROM "
                . $wpdb->prefix . "mailpoet_subscribers sub INNER JOIN wp_mailpoet_subscriber_segment seg ON sub.id = seg.subscriber_id"
                . " WHERE seg.segment_id IN (" . $lists . ") AND sub.id > " . ((int) $last_mp_id)
                . " ORDER BY sub.id ASC LIMIT 1000");

        $logger->debug($wpdb->last_query);

        if ($wpdb->error) {
            $logger->fatal($wpdb->error);
            $this->stop();
            return;
        }

        $logger->debug("Processing " . count($subscribers_result) . " results");

        if (empty($subscribers_result)) {
            $logger->info('Finished');
            $this->mp_stop();
            return;
        }

        $stats = get_option('newsletter_import_mailpoet_stats');

        $logger->info('Starting from id > ' . $last_mp_id);

        $mode = $options['mode'];
        $logger->debug('Mode ' . $mode);

        $newsletter = Newsletter::instance();

        $start = time();

        foreach ($subscribers_result AS $mp_subscriber) {

            sleep(3);

            if (time() > $start + $max_run_time) {
                $logger->error('Time is running out');
                delete_transient('newsletter_import_mailpoet');
                return;
            }

            $this->mp_set_position($mp_subscriber->id);

            $logger->debug('Processing ID ' . $mp_subscriber->id . ", email: " . $mp_subscriber->email);

            $stats['total']++;

            // Get subscriber

            $subscriber = $newsletter->get_user($mp_subscriber->email, ARRAY_A);
            if ($subscriber == null) {
                $logger->info('New subscriber');
                $subscriber = array();
                $subscriber['email'] = $mp_subscriber->email;
                $subscriber['name'] = $mp_subscriber->first_name;
                $subscriber['surname'] = $mp_subscriber->last_name;
                $subscriber['status'] = $this->getStatusFromMailpoet($mp_subscriber->status);

                if (!empty($options['lists_on'])) {
                    foreach ($options['lists_on'] as $i) {
                        $subscriber['list_' . $i] = '1';
                    }
                }

                $newsletter->save_user($subscriber);
                $stats['new']++;
                //$logger->debug($subscriber);
            } else {
                $logger->info('Matched subscriber ID ' . $subscriber['id']);
                if ($mode == 'skip') {
                    $logger->info('Skipped');
                    $stats['skipped']++;
                    update_option('newsletter_import_mailpoet_stats', $stats);
                    continue;
                }

                if ($mode == 'overwrite') {
                    // Clean up the subscriber
                    $subscriber['name'] = '';
                    $subscriber['surname'] = '';
                    $subscriber['sex'] = 'n';
                    for ($i = 1; $i <= NEWSLETTER_PROFILE_MAX; $i++) {
                        $subscriber['profile_' . $i] = '';
                    }
                    for ($i = 1; $i <= NEWSLETTER_LIST_MAX; $i++) {
                        $subscriber['list_' . $i] = 0;
                    }
                    $subscriber['country'] = '';
                    $subscriber['region'] = '';
                    $subscriber['city'] = '';
                }

                $subscriber['name'] = $mp_subscriber->first_name;
                $subscriber['surname'] = $mp_subscriber->last_name;

                if (isset($options['override_status'])) {
                    $subscriber['status'] = $this->getStatusFromMailpoet($mp_subscriber->status);
                }

                foreach ($options['lists_on'] as $i) {
                    $subscriber['list_' . $i] = 1;
                }

                //$logger->debug($subscriber);
                $newsletter->save_user($subscriber);
                $stats['updated']++;
            }
            update_option('newsletter_import_mailpoet_stats', $stats);

            // TODO: Remove is for test
            //break;
        }

        delete_transient('newsletter_import_mailpoet');
        return true;
    }

    private function getStatusFromMailpoet($mpstatus) {
        switch ($mpstatus) {
            case "subscribed":
            case "inactive":
            default:
                return TNP_User::STATUS_CONFIRMED;
            case "unsubscribed":
                return TNP_User::STATUS_UNSUBSCRIBED;
            case "unconfirmed":
                return TNP_User::STATUS_NOT_CONFIRMED;
            case "bounced":
                return TNP_User::STATUS_BOUNCED;
        }
    }
}

Anon7 - 2022
AnonSec Team